plusui-native-core 0.1.18 → 0.1.20

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.
@@ -1,182 +1,229 @@
1
+ #include <algorithm>
1
2
  #include <iostream>
2
3
  #include <plusui/browser.hpp>
3
4
  #include <plusui/webview.hpp>
5
+ #include <plusui/window.hpp>
6
+ #include <vector>
7
+
8
+
9
+ #ifdef _WIN32
10
+ #define WIN32_LEAN_AND_MEAN
11
+ #include <shellapi.h>
12
+ #include <windows.h>
13
+
14
+ #endif
4
15
 
5
16
  namespace plusui {
6
17
 
18
+ // Keep secondary windows alive
19
+ static std::vector<std::shared_ptr<Window>> g_windows;
20
+ static std::vector<std::shared_ptr<WebView>> g_webviews;
21
+
7
22
  struct Browser::Impl {
8
- WebView* webview = nullptr;
9
- std::map<std::string, std::string> routes;
10
- std::string currentRoute;
11
- BrowserState state;
12
-
13
- std::vector<NavigateCallback> navigateCallbacks;
14
- std::vector<StateCallback> stateCallbacks;
15
- std::vector<LoadCallback> loadStartCallbacks;
16
- std::vector<LoadCallback> loadEndCallbacks;
17
- std::vector<std::function<void(const std::string&)>> loadErrorCallbacks;
18
-
19
- void updateState() {
20
- if (webview) {
21
- state.url = webview->getURL();
22
- state.title = webview->getTitle();
23
- state.canGoBack = webview->canGoBack();
24
- state.canGoForward = webview->canGoForward();
25
- state.isLoading = webview->isLoading();
26
-
27
- for (auto& cb : stateCallbacks) {
28
- cb(state);
29
- }
30
- }
23
+ WebView *webview = nullptr;
24
+ std::map<std::string, std::string> routes;
25
+ std::string currentRoute;
26
+ BrowserState state;
27
+
28
+ std::vector<NavigateCallback> navigateCallbacks;
29
+ std::vector<StateCallback> stateCallbacks;
30
+ std::vector<LoadCallback> loadStartCallbacks;
31
+ std::vector<LoadCallback> loadEndCallbacks;
32
+ std::vector<std::function<void(const std::string &)>> loadErrorCallbacks;
33
+
34
+ void updateState() {
35
+ if (webview) {
36
+ state.url = webview->getURL();
37
+ state.title = webview->getTitle();
38
+ state.canGoBack = webview->canGoBack();
39
+ state.canGoForward = webview->canGoForward();
40
+ state.isLoading = webview->isLoading();
41
+
42
+ for (auto &cb : stateCallbacks) {
43
+ cb(state);
44
+ }
31
45
  }
32
-
33
- void notifyNavigate(const std::string& url) {
34
- state.url = url;
35
- for (auto& cb : navigateCallbacks) {
36
- cb(url);
37
- }
38
- updateState();
46
+ }
47
+
48
+ void notifyNavigate(const std::string &url) {
49
+ state.url = url;
50
+ for (auto &cb : navigateCallbacks) {
51
+ cb(url);
39
52
  }
53
+ updateState();
54
+ }
40
55
  };
41
56
 
42
57
  Browser::Browser() : pImpl(std::make_shared<Impl>()) {}
43
58
 
44
59
  Browser::~Browser() = default;
45
60
 
46
- Browser Browser::create(WebView* webview) {
47
- Browser browser;
48
- browser.pImpl->webview = webview;
49
-
50
- if (webview) {
51
- webview->onNavigationStart([impl = browser.pImpl](const std::string& url) {
52
- impl->notifyNavigate(url);
53
- return true;
54
- });
55
-
56
- webview->onLoadStart([impl = browser.pImpl]() {
57
- impl->state.isLoading = true;
58
- for (auto& cb : impl->loadStartCallbacks) {
59
- cb();
60
- }
61
+ Browser Browser::create(WebView *webview) {
62
+ Browser browser;
63
+ browser.pImpl->webview = webview;
64
+
65
+ if (webview) {
66
+ webview->onNavigationStart([impl = browser.pImpl](const std::string &url) {
67
+ impl->notifyNavigate(url);
68
+ return true;
69
+ });
70
+
71
+ webview->onLoadStart([impl = browser.pImpl]() {
72
+ impl->state.isLoading = true;
73
+ for (auto &cb : impl->loadStartCallbacks) {
74
+ cb();
75
+ }
76
+ });
77
+
78
+ webview->onLoadEnd([impl = browser.pImpl]() {
79
+ impl->state.isLoading = false;
80
+ impl->updateState();
81
+ for (auto &cb : impl->loadEndCallbacks) {
82
+ cb();
83
+ }
84
+ });
85
+
86
+ webview->onLoadError(
87
+ [impl = browser.pImpl](const std::string &error, int code) {
88
+ (void)code; // Suppress unused warning
89
+ impl->state.isLoading = false;
90
+ for (auto &cb : impl->loadErrorCallbacks) {
91
+ cb(error);
92
+ }
61
93
  });
62
-
63
- webview->onLoadEnd([impl = browser.pImpl]() {
64
- impl->state.isLoading = false;
65
- impl->updateState();
66
- for (auto& cb : impl->loadEndCallbacks) {
67
- cb();
68
- }
69
- });
70
-
71
- webview->onLoadError([impl = browser.pImpl](const std::string& error, int code) {
72
- (void)code; // Suppress unused warning
73
- impl->state.isLoading = false;
74
- for (auto& cb : impl->loadErrorCallbacks) {
75
- cb(error);
76
- }
77
- });
78
- }
79
-
80
- return browser;
94
+ }
95
+
96
+ return browser;
81
97
  }
82
98
 
83
- void Browser::navigate(const std::string& url) {
84
- if (pImpl->webview) {
85
- pImpl->webview->navigate(url);
86
- pImpl->notifyNavigate(url);
87
- }
99
+ void Browser::navigate(const std::string &url) {
100
+ if (pImpl->webview) {
101
+ pImpl->webview->navigate(url);
102
+ pImpl->notifyNavigate(url);
103
+ }
88
104
  }
89
105
 
90
106
  void Browser::goBack() {
91
- if (pImpl->webview && pImpl->webview->canGoBack()) {
92
- pImpl->webview->goBack();
93
- pImpl->updateState();
94
- }
107
+ if (pImpl->webview && pImpl->webview->canGoBack()) {
108
+ pImpl->webview->goBack();
109
+ pImpl->updateState();
110
+ }
95
111
  }
96
112
 
97
113
  void Browser::goForward() {
98
- if (pImpl->webview && pImpl->webview->canGoForward()) {
99
- pImpl->webview->goForward();
100
- pImpl->updateState();
101
- }
114
+ if (pImpl->webview && pImpl->webview->canGoForward()) {
115
+ pImpl->webview->goForward();
116
+ pImpl->updateState();
117
+ }
102
118
  }
103
119
 
104
120
  void Browser::reload() {
105
- if (pImpl->webview) {
106
- pImpl->webview->reload();
107
- }
121
+ if (pImpl->webview) {
122
+ pImpl->webview->reload();
123
+ }
108
124
  }
109
125
 
110
126
  void Browser::stop() {
111
- if (pImpl->webview) {
112
- pImpl->webview->stop();
113
- }
127
+ if (pImpl->webview) {
128
+ pImpl->webview->stop();
129
+ }
130
+ }
131
+
132
+ void Browser::openExternal(const std::string &url) {
133
+ #ifdef _WIN32
134
+ ShellExecuteA(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
135
+ #elif __APPLE__
136
+ std::string command = "open \"" + url + "\"";
137
+ system(command.c_str());
138
+ #else
139
+ std::string command = "xdg-open \"" + url + "\"";
140
+ system(command.c_str());
141
+ #endif
142
+ }
143
+
144
+ void Browser::openNewWindow(const std::string &url) {
145
+ WindowConfig winConfig;
146
+ winConfig.title = "New Window";
147
+
148
+ auto win = std::make_shared<Window>(Window::create(winConfig));
149
+ win->show();
150
+ g_windows.push_back(win);
151
+
152
+ WebViewConfig webConfig;
153
+ auto wv = std::make_shared<WebView>(
154
+ WebView::create(win->nativeHandle(), webConfig));
155
+ wv->setWindow(win);
156
+ wv->navigate(url);
157
+ g_webviews.push_back(wv);
158
+
159
+ win->onClose([win, wv]() {
160
+ auto itW = std::find(g_windows.begin(), g_windows.end(), win);
161
+ if (itW != g_windows.end())
162
+ g_windows.erase(itW);
163
+
164
+ auto itV = std::find(g_webviews.begin(), g_webviews.end(), wv);
165
+ if (itV != g_webviews.end())
166
+ g_webviews.erase(itV);
167
+ });
114
168
  }
115
169
 
116
170
  std::string Browser::getURL() const {
117
- return pImpl->webview ? pImpl->webview->getURL() : "";
171
+ return pImpl->webview ? pImpl->webview->getURL() : "";
118
172
  }
119
173
 
120
174
  std::string Browser::getTitle() const {
121
- return pImpl->webview ? pImpl->webview->getTitle() : "";
175
+ return pImpl->webview ? pImpl->webview->getTitle() : "";
122
176
  }
123
177
 
124
- BrowserState Browser::getState() const {
125
- return pImpl->state;
126
- }
178
+ BrowserState Browser::getState() const { return pImpl->state; }
127
179
 
128
180
  bool Browser::canGoBack() const {
129
- return pImpl->webview ? pImpl->webview->canGoBack() : false;
181
+ return pImpl->webview ? pImpl->webview->canGoBack() : false;
130
182
  }
131
183
 
132
184
  bool Browser::canGoForward() const {
133
- return pImpl->webview ? pImpl->webview->canGoForward() : false;
185
+ return pImpl->webview ? pImpl->webview->canGoForward() : false;
134
186
  }
135
187
 
136
- bool Browser::isLoading() const {
137
- return pImpl->state.isLoading;
138
- }
188
+ bool Browser::isLoading() const { return pImpl->state.isLoading; }
139
189
 
140
190
  void Browser::onNavigate(NavigateCallback callback) {
141
- pImpl->navigateCallbacks.push_back(callback);
191
+ pImpl->navigateCallbacks.push_back(callback);
142
192
  }
143
193
 
144
194
  void Browser::onStateChange(StateCallback callback) {
145
- pImpl->stateCallbacks.push_back(callback);
195
+ pImpl->stateCallbacks.push_back(callback);
146
196
  }
147
197
 
148
198
  void Browser::onLoadStart(LoadCallback callback) {
149
- pImpl->loadStartCallbacks.push_back(callback);
199
+ pImpl->loadStartCallbacks.push_back(callback);
150
200
  }
151
201
 
152
202
  void Browser::onLoadEnd(LoadCallback callback) {
153
- pImpl->loadEndCallbacks.push_back(callback);
203
+ pImpl->loadEndCallbacks.push_back(callback);
154
204
  }
155
205
 
156
- void Browser::onLoadError(std::function<void(const std::string& error)> callback) {
157
- pImpl->loadErrorCallbacks.push_back(callback);
206
+ void Browser::onLoadError(
207
+ std::function<void(const std::string &error)> callback) {
208
+ pImpl->loadErrorCallbacks.push_back(callback);
158
209
  }
159
210
 
160
- void Browser::setRoutes(const std::map<std::string, std::string>& routes) {
161
- pImpl->routes = routes;
211
+ void Browser::setRoutes(const std::map<std::string, std::string> &routes) {
212
+ pImpl->routes = routes;
162
213
  }
163
214
 
164
- void Browser::push(const std::string& route) {
165
- pImpl->currentRoute = route;
166
- auto it = pImpl->routes.find(route);
167
- if (it != pImpl->routes.end()) {
168
- navigate(it->second);
169
- } else {
170
- navigate(route);
171
- }
215
+ void Browser::push(const std::string &route) {
216
+ pImpl->currentRoute = route;
217
+ auto it = pImpl->routes.find(route);
218
+ if (it != pImpl->routes.end()) {
219
+ navigate(it->second);
220
+ } else {
221
+ navigate(route);
222
+ }
172
223
  }
173
224
 
174
- void Browser::replace(const std::string& route) {
175
- push(route);
176
- }
225
+ void Browser::replace(const std::string &route) { push(route); }
177
226
 
178
- std::string Browser::getCurrentRoute() const {
179
- return pImpl->currentRoute;
180
- }
227
+ std::string Browser::getCurrentRoute() const { return pImpl->currentRoute; }
181
228
 
182
229
  } // namespace plusui
@@ -25,7 +25,7 @@ async function invoke(method: string, args?: unknown[]): Promise<unknown> {
25
25
  throw new Error('Browser API not initialized');
26
26
  }
27
27
  }
28
- return _invoke(method, args);
28
+ return _invoke!(method, args);
29
29
  }
30
30
 
31
31
  const _navigateCallbacks: NavigateCallback[] = [];
@@ -66,6 +66,18 @@ export const browser = {
66
66
  await invoke('browser.navigate', [url]);
67
67
  },
68
68
 
69
+ async open(url: string): Promise<void> {
70
+ await invoke('browser.navigate', [url]);
71
+ },
72
+
73
+ async openExternal(url: string): Promise<void> {
74
+ await invoke('browser.openExternal', [url]);
75
+ },
76
+
77
+ async openNewWindow(url: string): Promise<void> {
78
+ await invoke('browser.openNewWindow', [url]);
79
+ },
80
+
69
81
  async goBack(): Promise<void> {
70
82
  await invoke('browser.goBack', []);
71
83
  },
@@ -140,6 +140,35 @@ WebView WebView::create(void *windowHandle, const WebViewConfig &config) {
140
140
  nullptr);
141
141
  }
142
142
 
143
+ // Disable default webview drag & drop behavior
144
+ // This prevents files from being loaded in the browser
145
+ // and allows the native FileDrop API to handle them instead
146
+ std::string disableDragDropScript = R"(
147
+ (function() {
148
+ // Prevent default drag and drop behavior on document/window
149
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(eventName) {
150
+ document.addEventListener(eventName, function(e) {
151
+ // Only prevent default on document.body or document.documentElement
152
+ // to allow custom drop zones to still work
153
+ if (e.target === document.body || e.target === document.documentElement || e.target === document) {
154
+ e.preventDefault();
155
+ e.stopPropagation();
156
+ }
157
+ }, true);
158
+
159
+ window.addEventListener(eventName, function(e) {
160
+ e.preventDefault();
161
+ e.stopPropagation();
162
+ }, true);
163
+ });
164
+ })();
165
+ )";
166
+ pImpl->webview->AddScriptToExecuteOnDocumentCreated(
167
+ std::wstring(disableDragDropScript.begin(),
168
+ disableDragDropScript.end())
169
+ .c_str(),
170
+ nullptr);
171
+
143
172
  // Set up WebMessageReceived handler for JS->C++ bridge
144
173
  pImpl->webview->add_WebMessageReceived(
145
174
  Callback<
@@ -617,6 +646,45 @@ WebView WebView::create(void *windowHandle, const WebViewConfig &config) {
617
646
  [config.preferences setValue:@YES forKey:@"developerExtrasEnabled"];
618
647
  }
619
648
 
649
+ // Disable default drag & drop behavior to allow native FileDrop API
650
+ NSString *disableDragDropScript = @"(function() {"
651
+ "['dragenter', 'dragover', 'dragleave', 'drop'].forEach(function(eventName) {"
652
+ "document.addEventListener(eventName, function(e) {"
653
+ "if (e.target === document.body || e.target === document.documentElement || e.target === document) {"
654
+ "e.preventDefault();"
655
+ "e.stopPropagation();"
656
+ "}"
657
+ "}, true);"
658
+ "window.addEventListener(eventName, function(e) {"
659
+ "e.preventDefault();"
660
+ "e.stopPropagation();"
661
+ "}, true);"
662
+ "});"
663
+ "})();";
664
+
665
+ WKUserScript *userScript = [[WKUserScript alloc]
666
+ initWithSource:disableDragDropScript
667
+ injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
668
+ forMainFrameOnly:NO];
669
+ [config.userContentController addUserScript:userScript];
670
+
671
+ // Hide scrollbars if disabled
672
+ if (!wv.pImpl->config.scrollbars) {
673
+ NSString *scrollbarScript = @"(function() {"
674
+ "var css = 'html, body { overflow: hidden !important; margin: 0 !important; padding: 0 !important; } ::-webkit-scrollbar { display: none !important; width: 0 !important; height: 0 !important; }';"
675
+ "var style = document.createElement('style');"
676
+ "style.type = 'text/css';"
677
+ "style.appendChild(document.createTextNode(css));"
678
+ "(document.head || document.documentElement).appendChild(style);"
679
+ "})();";
680
+
681
+ WKUserScript *scrollScript = [[WKUserScript alloc]
682
+ initWithSource:scrollbarScript
683
+ injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
684
+ forMainFrameOnly:NO];
685
+ [config.userContentController addUserScript:scrollScript];
686
+ }
687
+
620
688
  NSView *parentView = (__bridge NSView *)windowHandle;
621
689
  wv.pImpl->wkWebView =
622
690
  [[WKWebView alloc] initWithFrame:parentView.bounds configuration:config];
@@ -1,66 +1,69 @@
1
1
  #pragma once
2
2
 
3
3
  #include <functional>
4
+ #include <map>
4
5
  #include <memory>
5
6
  #include <string>
6
- #include <map>
7
7
 
8
8
  namespace plusui {
9
9
 
10
10
  class WebView;
11
11
 
12
12
  struct BrowserState {
13
- std::string url;
14
- std::string title;
15
- bool canGoBack = false;
16
- bool canGoForward = false;
17
- bool isLoading = false;
13
+ std::string url;
14
+ std::string title;
15
+ bool canGoBack = false;
16
+ bool canGoForward = false;
17
+ bool isLoading = false;
18
18
  };
19
19
 
20
20
  struct RouteConfig {
21
- std::string path;
22
- std::string url;
21
+ std::string path;
22
+ std::string url;
23
23
  };
24
24
 
25
25
  class Browser {
26
26
  public:
27
- using NavigateCallback = std::function<void(const std::string& url)>;
28
- using StateCallback = std::function<void(const BrowserState& state)>;
29
- using LoadCallback = std::function<void()>;
30
-
31
- Browser();
32
- ~Browser();
33
-
34
- static Browser create(WebView* webview);
35
-
36
- void navigate(const std::string& url);
37
- void goBack();
38
- void goForward();
39
- void reload();
40
- void stop();
41
-
42
- std::string getURL() const;
43
- std::string getTitle() const;
44
- BrowserState getState() const;
45
-
46
- bool canGoBack() const;
47
- bool canGoForward() const;
48
- bool isLoading() const;
49
-
50
- void onNavigate(NavigateCallback callback);
51
- void onStateChange(StateCallback callback);
52
- void onLoadStart(LoadCallback callback);
53
- void onLoadEnd(LoadCallback callback);
54
- void onLoadError(std::function<void(const std::string& error)> callback);
55
-
56
- void setRoutes(const std::map<std::string, std::string>& routes);
57
- void push(const std::string& route);
58
- void replace(const std::string& route);
59
- std::string getCurrentRoute() const;
27
+ using NavigateCallback = std::function<void(const std::string &url)>;
28
+ using StateCallback = std::function<void(const BrowserState &state)>;
29
+ using LoadCallback = std::function<void()>;
30
+
31
+ Browser();
32
+ ~Browser();
33
+
34
+ static Browser create(WebView *webview);
35
+
36
+ void navigate(const std::string &url);
37
+ void goBack();
38
+ void goForward();
39
+ void reload();
40
+ void stop();
41
+
42
+ void openExternal(const std::string &url);
43
+ void openNewWindow(const std::string &url);
44
+
45
+ std::string getURL() const;
46
+ std::string getTitle() const;
47
+ BrowserState getState() const;
48
+
49
+ bool canGoBack() const;
50
+ bool canGoForward() const;
51
+ bool isLoading() const;
52
+
53
+ void onNavigate(NavigateCallback callback);
54
+ void onStateChange(StateCallback callback);
55
+ void onLoadStart(LoadCallback callback);
56
+ void onLoadEnd(LoadCallback callback);
57
+ void onLoadError(std::function<void(const std::string &error)> callback);
58
+
59
+ void setRoutes(const std::map<std::string, std::string> &routes);
60
+ void push(const std::string &route);
61
+ void replace(const std::string &route);
62
+ std::string getCurrentRoute() const;
60
63
 
61
64
  private:
62
- struct Impl;
63
- std::shared_ptr<Impl> pImpl;
65
+ struct Impl;
66
+ std::shared_ptr<Impl> pImpl;
64
67
  };
65
68
 
66
69
  } // namespace plusui
@@ -0,0 +1,18 @@
1
+ /**
2
+ * PlusUI - Main Framework Header
3
+ *
4
+ * Standard library style include (no .hpp extension needed)
5
+ *
6
+ * Usage:
7
+ * #include <plusui>
8
+ * using namespace plusui;
9
+ *
10
+ * This provides access to all core framework features including:
11
+ * - App & Window management
12
+ * - Browser & WebView
13
+ * - Events & Bindings
14
+ * - FileDrop, Keyboard, Clipboard
15
+ * - Display, Tray, Menu
16
+ */
17
+
18
+ #include <plusui/plusui.hpp>
@@ -0,0 +1,40 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * PlusUI - Umbrella Header (Auto-generated)
5
+ *
6
+ * This file is automatically generated by scripts/generate-umbrella-header.mjs
7
+ * DO NOT EDIT MANUALLY - your changes will be overwritten!
8
+ *
9
+ * To regenerate: node Core/scripts/generate-umbrella-header.mjs
10
+ *
11
+ * This umbrella header includes all PlusUI framework headers.
12
+ * Include this single file to access the entire framework:
13
+ *
14
+ * Usage:
15
+ * #include <plusui> // Standard library style (recommended)
16
+ * // OR
17
+ * #include <plusui/plusui.hpp>
18
+ *
19
+ * using namespace plusui;
20
+ *
21
+ * For faster compile times in production, you can include only
22
+ * the specific headers you need instead of this convenience header.
23
+ */
24
+
25
+ #include <plusui/app.hpp>
26
+ #include <plusui/bindings.hpp>
27
+ #include <plusui/browser.hpp>
28
+ #include <plusui/clipboard.hpp>
29
+ #include <plusui/custom_bindings.hpp>
30
+ #include <plusui/display.hpp>
31
+ #include <plusui/events.hpp>
32
+ #include <plusui/filedrop.hpp>
33
+ #include <plusui/keyboard.hpp>
34
+ #include <plusui/menu.hpp>
35
+ #include <plusui/native_bindings.hpp>
36
+ #include <plusui/tray.hpp>
37
+ #include <plusui/webgpu.hpp>
38
+ #include <plusui/webview.hpp>
39
+ #include <plusui/window.hpp>
40
+ #include <plusui/window_manager.hpp>
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Generate the plusui.hpp umbrella header
4
+ *
5
+ * This script automatically scans all .hpp files in Core/include/plusui/
6
+ * and generates the umbrella header that includes them all.
7
+ *
8
+ * Run this whenever you add a new header file to the framework.
9
+ */
10
+
11
+ import { readdir, writeFile } from 'node:fs/promises';
12
+ import { resolve, dirname } from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = dirname(__filename);
17
+
18
+ const includeDir = resolve(__dirname, '../include/plusui');
19
+ const outputFile = resolve(includeDir, 'plusui.hpp');
20
+
21
+ async function generateUmbrellaHeader() {
22
+ // Read all files in the include directory
23
+ const files = await readdir(includeDir);
24
+
25
+ // Filter to only .hpp files, excluding plusui.hpp itself
26
+ const headerFiles = files
27
+ .filter(file => file.endsWith('.hpp') && file !== 'plusui.hpp')
28
+ .sort();
29
+
30
+ if (headerFiles.length === 0) {
31
+ throw new Error('No header files found to include');
32
+ }
33
+
34
+ // Generate the header content
35
+ const includes = headerFiles
36
+ .map(file => `#include <plusui/${file}>`)
37
+ .join('\n');
38
+
39
+ const content = `#pragma once
40
+
41
+ /**
42
+ * PlusUI - Umbrella Header (Auto-generated)
43
+ *
44
+ * This file is automatically generated by scripts/generate-umbrella-header.mjs
45
+ * DO NOT EDIT MANUALLY - your changes will be overwritten!
46
+ *
47
+ * To regenerate: node Core/scripts/generate-umbrella-header.mjs
48
+ *
49
+ * This umbrella header includes all PlusUI framework headers.
50
+ * Include this single file to access the entire framework:
51
+ *
52
+ * Usage:
53
+ * #include <plusui> // Standard library style (recommended)
54
+ * // OR
55
+ * #include <plusui/plusui.hpp>
56
+ *
57
+ * using namespace plusui;
58
+ *
59
+ * For faster compile times in production, you can include only
60
+ * the specific headers you need instead of this convenience header.
61
+ */
62
+
63
+ ${includes}
64
+ `;
65
+
66
+ // Write the generated header
67
+ await writeFile(outputFile, content, 'utf8');
68
+
69
+ console.log('✓ Generated plusui.hpp');
70
+ console.log(` Included ${headerFiles.length} headers:`);
71
+ headerFiles.forEach(file => console.log(` - ${file}`));
72
+ }
73
+
74
+ generateUmbrellaHeader().catch((error) => {
75
+ console.error(`Failed to generate umbrella header: ${error.message}`);
76
+ process.exit(1);
77
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plusui-native-core",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "PlusUI Core framework (frontend + backend implementations)",
5
5
  "type": "module",
6
6
  "files": [
@@ -8,7 +8,7 @@
8
8
  "README.md"
9
9
  ],
10
10
  "scripts": {
11
- "prepack": "node scripts/sync-core.mjs"
11
+ "prepack": "node ../../Core/scripts/generate-umbrella-header.mjs && node scripts/sync-core.mjs"
12
12
  },
13
13
  "keywords": [
14
14
  "desktop",