electrobun 0.0.19-beta.97 → 0.1.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 (77) hide show
  1. package/README.md +1 -1
  2. package/dist/api/browser/webviewtag.ts +54 -2
  3. package/dist/api/bun/ElectrobunConfig.ts +171 -0
  4. package/dist/api/bun/core/BrowserWindow.ts +4 -0
  5. package/dist/api/bun/core/Tray.ts +14 -0
  6. package/dist/api/bun/core/Updater.ts +4 -3
  7. package/dist/api/bun/index.ts +2 -0
  8. package/dist/api/bun/proc/native.ts +107 -5
  9. package/dist/main.js +5 -4
  10. package/package.json +4 -2
  11. package/src/cli/index.ts +565 -148
  12. package/templates/hello-world/bun.lock +164 -2
  13. package/templates/hello-world/electrobun.config.ts +28 -0
  14. package/templates/hello-world/src/bun/index.ts +2 -2
  15. package/templates/hello-world/src/mainview/index.html +5 -6
  16. package/templates/hello-world/src/mainview/index.ts +1 -5
  17. package/templates/interactive-playground/README.md +26 -0
  18. package/templates/interactive-playground/assets/tray-icon.png +0 -0
  19. package/templates/interactive-playground/electrobun.config.ts +36 -0
  20. package/templates/interactive-playground/package-lock.json +36 -0
  21. package/templates/interactive-playground/package.json +15 -0
  22. package/templates/interactive-playground/src/bun/demos/files.ts +70 -0
  23. package/templates/interactive-playground/src/bun/demos/menus.ts +139 -0
  24. package/templates/interactive-playground/src/bun/demos/rpc.ts +83 -0
  25. package/templates/interactive-playground/src/bun/demos/system.ts +72 -0
  26. package/templates/interactive-playground/src/bun/demos/updates.ts +105 -0
  27. package/templates/interactive-playground/src/bun/demos/windows.ts +90 -0
  28. package/templates/interactive-playground/src/bun/index.ts +124 -0
  29. package/templates/interactive-playground/src/bun/types/rpc.ts +109 -0
  30. package/templates/interactive-playground/src/mainview/components/EventLog.ts +107 -0
  31. package/templates/interactive-playground/src/mainview/components/Sidebar.ts +65 -0
  32. package/templates/interactive-playground/src/mainview/components/Toast.ts +57 -0
  33. package/templates/interactive-playground/src/mainview/demos/FileDemo.ts +211 -0
  34. package/templates/interactive-playground/src/mainview/demos/MenuDemo.ts +102 -0
  35. package/templates/interactive-playground/src/mainview/demos/RPCDemo.ts +229 -0
  36. package/templates/interactive-playground/src/mainview/demos/TrayDemo.ts +132 -0
  37. package/templates/interactive-playground/src/mainview/demos/WebViewDemo.ts +411 -0
  38. package/templates/interactive-playground/src/mainview/demos/WindowDemo.ts +207 -0
  39. package/templates/interactive-playground/src/mainview/index.css +538 -0
  40. package/templates/interactive-playground/src/mainview/index.html +103 -0
  41. package/templates/interactive-playground/src/mainview/index.ts +238 -0
  42. package/templates/multitab-browser/README.md +34 -0
  43. package/templates/multitab-browser/bun.lock +224 -0
  44. package/templates/multitab-browser/electrobun.config.ts +32 -0
  45. package/templates/multitab-browser/package-lock.json +20 -0
  46. package/templates/multitab-browser/package.json +12 -0
  47. package/templates/multitab-browser/src/bun/index.ts +144 -0
  48. package/templates/multitab-browser/src/bun/tabManager.ts +200 -0
  49. package/templates/multitab-browser/src/bun/types/rpc.ts +78 -0
  50. package/templates/multitab-browser/src/mainview/index.css +487 -0
  51. package/templates/multitab-browser/src/mainview/index.html +94 -0
  52. package/templates/multitab-browser/src/mainview/index.ts +634 -0
  53. package/templates/photo-booth/README.md +108 -0
  54. package/templates/photo-booth/bun.lock +239 -0
  55. package/templates/photo-booth/electrobun.config.ts +28 -0
  56. package/templates/photo-booth/package.json +16 -0
  57. package/templates/photo-booth/src/bun/index.ts +92 -0
  58. package/templates/photo-booth/src/mainview/index.css +465 -0
  59. package/templates/photo-booth/src/mainview/index.html +124 -0
  60. package/templates/photo-booth/src/mainview/index.ts +499 -0
  61. package/tests/bun.lock +14 -0
  62. package/tests/electrobun.config.ts +45 -0
  63. package/tests/package-lock.json +36 -0
  64. package/tests/package.json +13 -0
  65. package/tests/src/bun/index.ts +100 -0
  66. package/tests/src/bun/test-runner.ts +508 -0
  67. package/tests/src/mainview/index.html +110 -0
  68. package/tests/src/mainview/index.ts +458 -0
  69. package/tests/src/mainview/styles/main.css +451 -0
  70. package/tests/src/testviews/tray-test.html +57 -0
  71. package/tests/src/testviews/webview-mask.html +114 -0
  72. package/tests/src/testviews/webview-navigation.html +36 -0
  73. package/tests/src/testviews/window-create.html +17 -0
  74. package/tests/src/testviews/window-events.html +29 -0
  75. package/tests/src/testviews/window-focus.html +37 -0
  76. package/tests/src/webviewtag/index.ts +11 -0
  77. package/templates/hello-world/electrobun.config +0 -18
@@ -0,0 +1,207 @@
1
+ export class WindowDemo {
2
+ private windows: Array<{ id: number; title: string }> = [];
3
+ private rpc: any;
4
+
5
+ render() {
6
+ return `
7
+ <div class="demo-section">
8
+ <div class="demo-header">
9
+ <span class="demo-icon">🪟</span>
10
+ <div>
11
+ <h2 class="demo-title">Window Management</h2>
12
+ <p class="demo-description">Create and manage multiple application windows with different properties</p>
13
+ </div>
14
+ </div>
15
+
16
+ <div class="demo-controls">
17
+ <div class="control-group">
18
+ <label class="control-label">Width:</label>
19
+ <input type="number" id="window-width" class="control-input" value="800" min="200" max="2000">
20
+
21
+ <label class="control-label">Height:</label>
22
+ <input type="number" id="window-height" class="control-input" value="600" min="200" max="1200">
23
+
24
+ <label class="control-label">X:</label>
25
+ <input type="number" id="window-x" class="control-input" value="100" min="0" max="2000">
26
+
27
+ <label class="control-label">Y:</label>
28
+ <input type="number" id="window-y" class="control-input" value="100" min="0" max="1200">
29
+ </div>
30
+
31
+ <div class="control-group">
32
+ <label class="control-checkbox">
33
+ <input type="checkbox" id="window-frameless"> Frameless
34
+ </label>
35
+ <label class="control-checkbox" title="Transparency is for webviews, not windows">
36
+ <input type="checkbox" id="window-transparent" disabled> Transparent (WebView only)
37
+ </label>
38
+ <label class="control-checkbox" title="Not yet implemented">
39
+ <input type="checkbox" id="window-always-on-top" disabled> Always on Top (Coming soon)
40
+ </label>
41
+ </div>
42
+
43
+ <div class="control-group">
44
+ <button class="btn btn-primary" id="create-window">Create Window</button>
45
+ <button class="btn btn-secondary" id="get-window-list">Refresh List</button>
46
+ <button class="btn btn-danger" id="close-all-windows">Close All</button>
47
+ </div>
48
+ </div>
49
+
50
+ <div class="demo-results">
51
+ <div class="results-header">Active Windows (<span id="window-count">0</span>):</div>
52
+ <div class="window-grid" id="window-grid">
53
+ <div class="no-windows" style="grid-column: 1 / -1; text-align: center; color: #718096; padding: 2rem;">
54
+ No windows created yet. Use the controls above to create your first window.
55
+ </div>
56
+ </div>
57
+ </div>
58
+ </div>
59
+ `;
60
+ }
61
+
62
+ initialize(rpc: any) {
63
+ this.rpc = rpc; // Store RPC reference
64
+
65
+ // Get DOM elements
66
+ const createBtn = document.getElementById('create-window');
67
+ const refreshBtn = document.getElementById('get-window-list');
68
+ const closeAllBtn = document.getElementById('close-all-windows');
69
+
70
+ // Event listeners
71
+ createBtn?.addEventListener('click', async () => {
72
+ const width = parseInt((document.getElementById('window-width') as HTMLInputElement).value);
73
+ const height = parseInt((document.getElementById('window-height') as HTMLInputElement).value);
74
+ const x = parseInt((document.getElementById('window-x') as HTMLInputElement).value);
75
+ const y = parseInt((document.getElementById('window-y') as HTMLInputElement).value);
76
+ const frameless = (document.getElementById('window-frameless') as HTMLInputElement).checked;
77
+ // Transparent and alwaysOnTop are disabled for now
78
+ // const transparent = (document.getElementById('window-transparent') as HTMLInputElement).checked;
79
+ // const alwaysOnTop = (document.getElementById('window-always-on-top') as HTMLInputElement).checked;
80
+
81
+ try {
82
+ const result = await rpc.request.createWindow({
83
+ width, height, x, y, frameless
84
+ });
85
+ console.log('Window created:', result);
86
+ } catch (error) {
87
+ console.error('Error creating window:', error);
88
+ }
89
+ });
90
+
91
+ refreshBtn?.addEventListener('click', async () => {
92
+ try {
93
+ const windows = await rpc.request.getWindowList();
94
+ this.updateWindowList(windows);
95
+ } catch (error) {
96
+ console.error('Error getting window list:', error);
97
+ }
98
+ });
99
+
100
+ closeAllBtn?.addEventListener('click', async () => {
101
+ for (const window of this.windows) {
102
+ try {
103
+ await rpc.request.closeWindow(window.id);
104
+ } catch (error) {
105
+ console.error(`Error closing window ${window.id}:`, error);
106
+ }
107
+ }
108
+ });
109
+
110
+ // Load initial window list
111
+ this.loadWindowList(rpc);
112
+ }
113
+
114
+ private async loadWindowList(rpc: any) {
115
+ try {
116
+ const windows = await rpc.request.getWindowList();
117
+ this.updateWindowList(windows);
118
+ } catch (error) {
119
+ console.error('Error loading window list:', error);
120
+ }
121
+ }
122
+
123
+ updateWindowList(windows: Array<{ id: number; title: string }>) {
124
+ this.windows = windows;
125
+ const grid = document.getElementById('window-grid');
126
+ const count = document.getElementById('window-count');
127
+
128
+ if (!grid || !count) return;
129
+
130
+ count.textContent = windows.length.toString();
131
+
132
+ if (windows.length === 0) {
133
+ grid.innerHTML = `
134
+ <div class="no-windows" style="grid-column: 1 / -1; text-align: center; color: #718096; padding: 2rem;">
135
+ No windows created yet. Use the controls above to create your first window.
136
+ </div>
137
+ `;
138
+ return;
139
+ }
140
+
141
+ grid.innerHTML = windows.map(window => `
142
+ <div class="window-card" data-window-id="${window.id}">
143
+ <div class="window-preview">Window Preview</div>
144
+ <div class="window-title">${window.title}</div>
145
+ <div class="window-actions">
146
+ <button class="btn btn-small btn-secondary focus-window" data-window-id="${window.id}">Focus</button>
147
+ <button class="btn btn-small btn-danger close-window" data-window-id="${window.id}">×</button>
148
+ </div>
149
+ </div>
150
+ `).join('');
151
+
152
+ // Add event listeners for window actions
153
+ this.attachWindowActionListeners();
154
+ }
155
+
156
+ private attachWindowActionListeners() {
157
+ const focusButtons = document.querySelectorAll('.focus-window');
158
+ const closeButtons = document.querySelectorAll('.close-window');
159
+
160
+ focusButtons.forEach(btn => {
161
+ btn.addEventListener('click', async (e) => {
162
+ const id = parseInt((e.target as HTMLElement).getAttribute('data-window-id') || '0');
163
+ try {
164
+ await this.rpc.request.focusWindow(id);
165
+ console.log(`Focused window ${id}`);
166
+ } catch (error) {
167
+ console.error(`Error focusing window ${id}:`, error);
168
+ }
169
+ });
170
+ });
171
+
172
+ closeButtons.forEach(btn => {
173
+ btn.addEventListener('click', async (e) => {
174
+ const id = parseInt((e.target as HTMLElement).getAttribute('data-window-id') || '0');
175
+ try {
176
+ await this.rpc.request.closeWindow(id);
177
+ console.log(`Closed window ${id}`);
178
+ // Remove from local list
179
+ this.windows = this.windows.filter(w => w.id !== id);
180
+ this.updateWindowList(this.windows);
181
+ } catch (error) {
182
+ console.error(`Error closing window ${id}:`, error);
183
+ }
184
+ });
185
+ });
186
+ }
187
+
188
+ // Handle events from the backend
189
+ onWindowCreated(data: { id: number; title: string }) {
190
+ this.windows.push(data);
191
+ this.updateWindowList(this.windows);
192
+ }
193
+
194
+ onWindowClosed(data: { id: number }) {
195
+ this.windows = this.windows.filter(w => w.id !== data.id);
196
+ this.updateWindowList(this.windows);
197
+ }
198
+
199
+ onWindowFocused(data: { id: number }) {
200
+ // Visual feedback for focused window
201
+ const windowCard = document.querySelector(`[data-window-id="${data.id}"]`);
202
+ if (windowCard) {
203
+ windowCard.classList.add('focused');
204
+ setTimeout(() => windowCard.classList.remove('focused'), 1000);
205
+ }
206
+ }
207
+ }