electrobun 0.5.0-beta.0 → 0.7.0-beta.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 (80) hide show
  1. package/{templates/multitab-browser/bun.lock → bun.lock} +20 -13
  2. package/dist/api/bun/core/BrowserView.ts +5 -1
  3. package/dist/api/bun/events/webviewEvents.ts +8 -0
  4. package/dist/api/bun/proc/native.ts +95 -21
  5. package/package.json +14 -16
  6. package/BETA_RELEASE.md +0 -67
  7. package/BUILD.md +0 -90
  8. package/LICENSE +0 -21
  9. package/README.md +0 -102
  10. package/debug.js +0 -5
  11. package/templates/hello-world/README.md +0 -57
  12. package/templates/hello-world/bun.lock +0 -225
  13. package/templates/hello-world/electrobun.config.ts +0 -28
  14. package/templates/hello-world/package.json +0 -16
  15. package/templates/hello-world/src/bun/index.ts +0 -15
  16. package/templates/hello-world/src/mainview/index.css +0 -124
  17. package/templates/hello-world/src/mainview/index.html +0 -46
  18. package/templates/hello-world/src/mainview/index.ts +0 -1
  19. package/templates/interactive-playground/README.md +0 -26
  20. package/templates/interactive-playground/assets/tray-icon.png +0 -0
  21. package/templates/interactive-playground/electrobun.config.ts +0 -36
  22. package/templates/interactive-playground/package-lock.json +0 -1112
  23. package/templates/interactive-playground/package.json +0 -15
  24. package/templates/interactive-playground/src/bun/demos/files.ts +0 -70
  25. package/templates/interactive-playground/src/bun/demos/menus.ts +0 -139
  26. package/templates/interactive-playground/src/bun/demos/rpc.ts +0 -83
  27. package/templates/interactive-playground/src/bun/demos/system.ts +0 -72
  28. package/templates/interactive-playground/src/bun/demos/updates.ts +0 -105
  29. package/templates/interactive-playground/src/bun/demos/windows.ts +0 -90
  30. package/templates/interactive-playground/src/bun/index.ts +0 -124
  31. package/templates/interactive-playground/src/bun/types/rpc.ts +0 -109
  32. package/templates/interactive-playground/src/mainview/components/EventLog.ts +0 -107
  33. package/templates/interactive-playground/src/mainview/components/Sidebar.ts +0 -65
  34. package/templates/interactive-playground/src/mainview/components/Toast.ts +0 -57
  35. package/templates/interactive-playground/src/mainview/demos/FileDemo.ts +0 -211
  36. package/templates/interactive-playground/src/mainview/demos/MenuDemo.ts +0 -102
  37. package/templates/interactive-playground/src/mainview/demos/RPCDemo.ts +0 -229
  38. package/templates/interactive-playground/src/mainview/demos/TrayDemo.ts +0 -132
  39. package/templates/interactive-playground/src/mainview/demos/WebViewDemo.ts +0 -465
  40. package/templates/interactive-playground/src/mainview/demos/WindowDemo.ts +0 -207
  41. package/templates/interactive-playground/src/mainview/index.css +0 -538
  42. package/templates/interactive-playground/src/mainview/index.html +0 -103
  43. package/templates/interactive-playground/src/mainview/index.ts +0 -238
  44. package/templates/multitab-browser/README.md +0 -34
  45. package/templates/multitab-browser/electrobun.config.ts +0 -32
  46. package/templates/multitab-browser/package-lock.json +0 -20
  47. package/templates/multitab-browser/package.json +0 -12
  48. package/templates/multitab-browser/src/bun/index.ts +0 -144
  49. package/templates/multitab-browser/src/bun/tabManager.ts +0 -200
  50. package/templates/multitab-browser/src/bun/types/rpc.ts +0 -78
  51. package/templates/multitab-browser/src/mainview/index.css +0 -487
  52. package/templates/multitab-browser/src/mainview/index.html +0 -94
  53. package/templates/multitab-browser/src/mainview/index.ts +0 -634
  54. package/templates/photo-booth/README.md +0 -108
  55. package/templates/photo-booth/bun.lock +0 -239
  56. package/templates/photo-booth/electrobun.config.ts +0 -32
  57. package/templates/photo-booth/package.json +0 -17
  58. package/templates/photo-booth/src/bun/index.ts +0 -92
  59. package/templates/photo-booth/src/mainview/index.css +0 -465
  60. package/templates/photo-booth/src/mainview/index.html +0 -124
  61. package/templates/photo-booth/src/mainview/index.ts +0 -499
  62. package/test-new-window-events.ts +0 -26
  63. package/test-new-window.html +0 -75
  64. package/test-npm-install.sh +0 -34
  65. package/tests/bun.lock +0 -14
  66. package/tests/electrobun.config.ts +0 -45
  67. package/tests/package-lock.json +0 -36
  68. package/tests/package.json +0 -13
  69. package/tests/src/bun/index.ts +0 -100
  70. package/tests/src/bun/test-runner.ts +0 -508
  71. package/tests/src/mainview/index.html +0 -110
  72. package/tests/src/mainview/index.ts +0 -458
  73. package/tests/src/mainview/styles/main.css +0 -451
  74. package/tests/src/testviews/tray-test.html +0 -57
  75. package/tests/src/testviews/webview-mask.html +0 -114
  76. package/tests/src/testviews/webview-navigation.html +0 -36
  77. package/tests/src/testviews/window-create.html +0 -17
  78. package/tests/src/testviews/window-events.html +0 -29
  79. package/tests/src/testviews/window-focus.html +0 -37
  80. package/tests/src/webviewtag/index.ts +0 -11
@@ -2,9 +2,16 @@
2
2
  "lockfileVersion": 1,
3
3
  "workspaces": {
4
4
  "": {
5
- "name": "multitab-browser",
5
+ "name": "electrobun",
6
6
  "dependencies": {
7
- "electrobun": "file:../../",
7
+ "@oneidentity/zstd-js": "^1.0.3",
8
+ "archiver": "^7.0.1",
9
+ "rpc-anywhere": "1.5.0",
10
+ "tar": "^6.2.1",
11
+ },
12
+ "devDependencies": {
13
+ "@types/archiver": "^6.0.3",
14
+ "@types/bun": "1.1.9",
8
15
  },
9
16
  },
10
17
  },
@@ -15,7 +22,7 @@
15
22
 
16
23
  "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
17
24
 
18
- "@types/archiver": ["@types/archiver@6.0.3", "", { "dependencies": { "@types/readdir-glob": "*" } }, "sha512-a6wUll6k3zX6qs5KlxIggs1P1JcYJaTCx2gnlr+f0S1yd2DoaEwoIK10HmBaLnZwWneBz+JBm0dwcZu0zECBcQ=="],
25
+ "@types/archiver": ["@types/archiver@6.0.4", "", { "dependencies": { "@types/readdir-glob": "*" } }, "sha512-ULdQpARQ3sz9WH4nb98mJDYA0ft2A8C4f4fovvUcFwINa1cgGjY36JCAYuP5YypRq4mco1lJp1/7jEMS2oR0Hg=="],
19
26
 
20
27
  "@types/bun": ["@types/bun@1.1.9", "", { "dependencies": { "bun-types": "1.1.27" } }, "sha512-SXJRejXpmAc3qxyN/YS4/JGWEzLf4dDBa5fLtRDipQXHqNccuMU4EUYCooXNTsylG0DmwFQsGgEDHxZF+3DqRw=="],
21
28
 
@@ -37,9 +44,9 @@
37
44
 
38
45
  "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
39
46
 
40
- "ansi-regex": ["ansi-regex@6.2.0", "", {}, "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg=="],
47
+ "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
41
48
 
42
- "ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
49
+ "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
43
50
 
44
51
  "archiver": ["archiver@7.0.1", "", { "dependencies": { "archiver-utils": "^5.0.2", "async": "^3.2.4", "buffer-crc32": "^1.0.0", "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", "zip-stream": "^6.0.1" } }, "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ=="],
45
52
 
@@ -47,11 +54,11 @@
47
54
 
48
55
  "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="],
49
56
 
50
- "b4a": ["b4a@1.6.7", "", {}, "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg=="],
57
+ "b4a": ["b4a@1.7.3", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q=="],
51
58
 
52
59
  "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
53
60
 
54
- "bare-events": ["bare-events@2.6.1", "", {}, "sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g=="],
61
+ "bare-events": ["bare-events@2.8.2", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ=="],
55
62
 
56
63
  "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
57
64
 
@@ -83,21 +90,21 @@
83
90
 
84
91
  "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
85
92
 
86
- "electrobun": ["electrobun@file:../..", { "dependencies": { "@oneidentity/zstd-js": "^1.0.3", "archiver": "^7.0.1", "rpc-anywhere": "1.5.0", "tar": "^6.2.1" }, "devDependencies": { "@types/archiver": "^6.0.3", "@types/bun": "1.1.9" }, "bin": { "electrobun": "./bin/electrobun.cjs" } }],
87
-
88
93
  "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
89
94
 
90
95
  "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
91
96
 
92
97
  "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
93
98
 
99
+ "events-universal": ["events-universal@1.0.1", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="],
100
+
94
101
  "fast-fifo": ["fast-fifo@1.3.2", "", {}, "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="],
95
102
 
96
103
  "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
97
104
 
98
105
  "fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="],
99
106
 
100
- "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
107
+ "glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
101
108
 
102
109
  "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
103
110
 
@@ -127,7 +134,7 @@
127
134
 
128
135
  "minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
129
136
 
130
- "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
137
+ "mkdirp": ["mkdirp@1.0.4", "", { "bin": "bin/cmd.js" }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
131
138
 
132
139
  "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
133
140
 
@@ -155,7 +162,7 @@
155
162
 
156
163
  "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
157
164
 
158
- "streamx": ["streamx@2.22.1", "", { "dependencies": { "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" }, "optionalDependencies": { "bare-events": "^2.2.0" } }, "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA=="],
165
+ "streamx": ["streamx@2.23.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg=="],
159
166
 
160
167
  "string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
161
168
 
@@ -163,7 +170,7 @@
163
170
 
164
171
  "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
165
172
 
166
- "strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
173
+ "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
167
174
 
168
175
  "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
169
176
 
@@ -237,7 +237,11 @@ export class BrowserView<T> {
237
237
  | "did-navigate"
238
238
  | "did-navigate-in-page"
239
239
  | "did-commit-navigation"
240
- | "dom-ready",
240
+ | "dom-ready"
241
+ | "download-started"
242
+ | "download-progress"
243
+ | "download-completed"
244
+ | "download-failed",
241
245
  handler
242
246
  ) {
243
247
  const specificName = `${name}-${this.id}`;
@@ -23,4 +23,12 @@ export default {
23
23
  }, {}>("new-window-open", data),
24
24
  hostMessage: (data) =>
25
25
  new ElectrobunEvent<{ detail: string }, {}>("host-message", data),
26
+ downloadStarted: (data) =>
27
+ new ElectrobunEvent<{ detail: string }, {}>("download-started", data),
28
+ downloadProgress: (data) =>
29
+ new ElectrobunEvent<{ detail: string }, {}>("download-progress", data),
30
+ downloadCompleted: (data) =>
31
+ new ElectrobunEvent<{ detail: string }, {}>("download-completed", data),
32
+ downloadFailed: (data) =>
33
+ new ElectrobunEvent<{ detail: string }, {}>("download-failed", data),
26
34
  };
@@ -599,24 +599,92 @@ export const ffi = {
599
599
  window.addEventListener('popstate', function(event) {
600
600
  emitWebviewEvent('did-navigate-in-page', window.location.href);
601
601
  });
602
-
602
+
603
603
  window.addEventListener('hashchange', function(event) {
604
- emitWebviewEvent('did-navigate-in-page', window.location.href);
604
+ emitWebviewEvent('did-navigate-in-page', window.location.href);
605
605
  });
606
-
607
- document.addEventListener('click', function(event) {
608
- if ((event.metaKey || event.ctrlKey) && event.target.tagName === 'A') {
609
- event.preventDefault();
610
- event.stopPropagation();
611
-
612
- // Get the href of the link
613
- const url = event.target.href;
614
-
615
- // Open the URL in a new window or tab
616
- // Note: we already handle new windows in objc
617
- window.open(url, '_blank');
618
- }
619
- }, true);
606
+
607
+ // Track cmd key state for SPA navigation detection
608
+ let __electrobunCmdKeyHeld = false;
609
+ let __electrobunCmdKeyTimestamp = 0;
610
+ const CMD_KEY_THRESHOLD_MS = 500; // How long after cmd release to still consider it a cmd+click
611
+
612
+ window.addEventListener('keydown', function(event) {
613
+ if (event.key === 'Meta' || event.metaKey) {
614
+ __electrobunCmdKeyHeld = true;
615
+ __electrobunCmdKeyTimestamp = Date.now();
616
+ }
617
+ }, true);
618
+
619
+ window.addEventListener('keyup', function(event) {
620
+ if (event.key === 'Meta') {
621
+ __electrobunCmdKeyHeld = false;
622
+ __electrobunCmdKeyTimestamp = Date.now();
623
+ }
624
+ }, true);
625
+
626
+ // Also track on blur in case key release happens outside window
627
+ window.addEventListener('blur', function() {
628
+ __electrobunCmdKeyHeld = false;
629
+ });
630
+
631
+ function __electrobunIsCmdHeld() {
632
+ if (__electrobunCmdKeyHeld) return true;
633
+ // Also return true if cmd was released very recently (for race conditions)
634
+ return (Date.now() - __electrobunCmdKeyTimestamp) < CMD_KEY_THRESHOLD_MS && __electrobunCmdKeyTimestamp > 0;
635
+ }
636
+
637
+ // Intercept cmd+clicks on anchors before SPA frameworks (like Turbo) can handle them
638
+ // Uses capture phase on window - this fires before document capture listeners
639
+ window.addEventListener('click', function(event) {
640
+ if (event.metaKey || event.ctrlKey) {
641
+ // Find the closest anchor element (handles clicks on nested elements inside <a>)
642
+ const anchor = event.target.closest('a');
643
+ if (anchor && anchor.href) {
644
+ event.preventDefault();
645
+ event.stopPropagation();
646
+ event.stopImmediatePropagation();
647
+ emitWebviewEvent('new-window-open', JSON.stringify({
648
+ url: anchor.href,
649
+ isCmdClick: true,
650
+ isSPANavigation: false
651
+ }));
652
+ }
653
+ }
654
+ }, true);
655
+
656
+ // Intercept history.pushState and replaceState for SPA navigation
657
+ // This catches cases where cmd is held but the SPA still manages to call pushState
658
+ const originalPushState = history.pushState;
659
+ const originalReplaceState = history.replaceState;
660
+
661
+ history.pushState = function(state, title, url) {
662
+ if (__electrobunIsCmdHeld() && url) {
663
+ // Resolve relative URLs
664
+ const resolvedUrl = new URL(url, window.location.href).href;
665
+ emitWebviewEvent('new-window-open', JSON.stringify({
666
+ url: resolvedUrl,
667
+ isCmdClick: true,
668
+ isSPANavigation: true
669
+ }));
670
+ // Don't call original - block the navigation
671
+ return;
672
+ }
673
+ return originalPushState.apply(this, arguments);
674
+ };
675
+
676
+ history.replaceState = function(state, title, url) {
677
+ if (__electrobunIsCmdHeld() && url) {
678
+ const resolvedUrl = new URL(url, window.location.href).href;
679
+ emitWebviewEvent('new-window-open', JSON.stringify({
680
+ url: resolvedUrl,
681
+ isCmdClick: true,
682
+ isSPANavigation: true
683
+ }));
684
+ return;
685
+ }
686
+ return originalReplaceState.apply(this, arguments);
687
+ };
620
688
 
621
689
  // prevent overscroll
622
690
  document.addEventListener('DOMContentLoaded', () => {
@@ -1029,6 +1097,10 @@ const webviewEventHandler = (id, eventName, detail) => {
1029
1097
  "dom-ready": "domReady",
1030
1098
  "new-window-open": "newWindowOpen",
1031
1099
  "host-message": "hostMessage",
1100
+ "download-started": "downloadStarted",
1101
+ "download-progress": "downloadProgress",
1102
+ "download-completed": "downloadCompleted",
1103
+ "download-failed": "downloadFailed",
1032
1104
  };
1033
1105
 
1034
1106
  // todo: the events map should use the same hyphenated names instead of camelCase
@@ -1040,9 +1112,11 @@ const webviewEventHandler = (id, eventName, detail) => {
1040
1112
  return { success: false };
1041
1113
  }
1042
1114
 
1043
- // Parse JSON data for new-window-open and host-message events
1115
+ // Parse JSON data for events that send JSON
1044
1116
  let parsedDetail = detail;
1045
- if (eventName === "new-window-open" || eventName === "host-message") {
1117
+ if (eventName === "new-window-open" || eventName === "host-message" ||
1118
+ eventName === "download-started" || eventName === "download-progress" ||
1119
+ eventName === "download-completed" || eventName === "download-failed") {
1046
1120
  try {
1047
1121
  parsedDetail = JSON.parse(detail);
1048
1122
  } catch (e) {
@@ -1063,10 +1137,10 @@ const webviewEventHandler = (id, eventName, detail) => {
1063
1137
  result = electrobunEventEmitter.emitEvent(event, id);
1064
1138
  }
1065
1139
 
1066
- const webviewEventJSCallback = new JSCallback((id, _eventName, _detail) => {
1140
+ const webviewEventJSCallback = new JSCallback((id, _eventName, _detail) => {
1067
1141
  let eventName = "";
1068
1142
  let detail = "";
1069
-
1143
+
1070
1144
  try {
1071
1145
  // Convert cstring pointers to actual strings
1072
1146
  eventName = new CString(_eventName).toString();
@@ -1076,7 +1150,7 @@ const webviewEventJSCallback = new JSCallback((id, _eventName, _detail) => {
1076
1150
  console.error('[webviewEventJSCallback] Raw values:', { _eventName, _detail });
1077
1151
  return;
1078
1152
  }
1079
-
1153
+
1080
1154
  webviewEventHandler(id, eventName, detail);
1081
1155
  }, {
1082
1156
  args: [FFIType.u32, FFIType.cstring, FFIType.cstring],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electrobun",
3
- "version": "0.5.0-beta.0",
3
+ "version": "0.7.0-beta.0",
4
4
  "description": "Build ultra fast, tiny, and cross-platform desktop apps with Typescript.",
5
5
  "license": "MIT",
6
6
  "author": "Blackboard Technologies Inc.",
@@ -31,24 +31,22 @@
31
31
  "check-zig-version": "vendors/zig/zig version",
32
32
  "build:dev": "bun build.ts",
33
33
  "build:release": "bun build.ts --release",
34
- "dev:playground": "bun build:dev && bun build:cli && cd playground && npm install && bun build:dev && bun start",
35
- "dev:playground:linux": "bun build:dev && npm link && cd playground && npm link electrobun && bun build:dev && bun start",
36
- "dev:playground:clean": "cd playground && rm -rf node_modules && rm -rf vendors/cef && npm install && cd .. && bun dev:playground",
37
- "dev:playground:clean:linux": "cd playground && rm -rf node_modules && rm -rf vendors/cef && npm install && cd .. && bun dev:playground:linux",
38
- "dev:playground:rerun": "cd playground && bun start",
39
- "dev:playground:canary": "bun build:release && cd playground && npm install && bun build:canary && bun start:canary",
40
- "run:playground": "bun build:dev && bun build:cli && cd templates/interactive-playground && npm install && bun build:dev && bun start",
41
- "dev:docs": "cd documentation && bun start",
42
- "build:docs:release": "cd documentation && bun run build",
34
+ "dev": "bun install && bun build:dev && bun build:cli && cd ../kitchen && bun install && bun build:dev && bun start",
35
+ "dev:clean": "cd ../kitchen && rm -rf node_modules && rm -rf vendors/cef && cd ../package && bun dev",
36
+ "dev:rerun": "cd ../kitchen && bun start",
37
+ "dev:canary": "bun install && bun build:release && cd ../kitchen && bun install && bun build:canary && bun start:canary",
38
+ "run:template": "bun install && bun build:dev && bun build:cli && cd ../templates/interactive-playground && bun install && bun build:dev && bun start",
39
+ "dev:docs": "cd ../documentation && bun start",
40
+ "build:docs:release": "cd ../documentation && bun run build",
43
41
  "npm:publish": "bun build:release && npm publish",
44
42
  "npm:publish:beta": "bun build:release && npm publish --tag beta",
45
- "push:beta": "npm version prerelease --preid=beta && git push origin main --tags",
46
- "push:patch": "npm version prepatch --preid=beta && git push origin main --tags",
47
- "push:minor": "npm version preminor --preid=beta && git push origin main --tags",
48
- "push:major": "npm version premajor --preid=beta && git push origin main --tags",
49
- "push:stable": "npm version patch && git push origin main --tags",
43
+ "push:beta": "bun scripts/push-version.js beta",
44
+ "push:patch": "bun scripts/push-version.js patch",
45
+ "push:minor": "bun scripts/push-version.js minor",
46
+ "push:major": "bun scripts/push-version.js major",
47
+ "push:stable": "bun scripts/push-version.js stable",
50
48
  "build:push:artifacts": "bun scripts/build-and-upload-artifacts.js",
51
- "test": "bun build:dev && bun build:cli && cd tests && npm install && bun build:dev && bun start"
49
+ "test": "bun install && bun build:dev && bun build:cli && cd ../tests && bun install && bun build:dev && bun start"
52
50
  },
53
51
  "devDependencies": {
54
52
  "@types/archiver": "^6.0.3",
package/BETA_RELEASE.md DELETED
@@ -1,67 +0,0 @@
1
- # Electrobun Beta Releases
2
-
3
- ## For Users
4
-
5
- ### Installing Beta Versions
6
-
7
- ```bash
8
- # Install latest beta
9
- npm install electrobun@beta
10
-
11
- # Install specific beta version
12
- npm install electrobun@0.0.19-beta.1
13
-
14
- # View available versions
15
- npm view electrobun versions --json
16
- ```
17
-
18
- ### Switching Between Stable and Beta
19
-
20
- ```bash
21
- # Switch to stable
22
- npm install electrobun@latest
23
-
24
- # Switch to beta
25
- npm install electrobun@beta
26
- ```
27
-
28
- ## For Maintainers
29
-
30
- ### Publishing Beta Releases
31
-
32
- 1. **Update version:**
33
- ```bash
34
- # First beta of a new version
35
- npm version 0.0.19-beta.1
36
-
37
- # Increment beta number
38
- bun npm:version:beta
39
- ```
40
-
41
- 2. **Create GitHub Release:**
42
- ```bash
43
- git push origin v0.0.19-beta.1
44
- ```
45
- Or manually trigger the workflow with the beta tag.
46
-
47
- 3. **Publish to npm:**
48
- ```bash
49
- bun npm:publish:beta
50
- ```
51
-
52
- ### Beta Release Workflow
53
-
54
- 1. Beta versions use semantic versioning: `MAJOR.MINOR.PATCH-beta.NUMBER`
55
- 2. GitHub Actions automatically marks releases with `-beta` as pre-releases
56
- 3. npm publishes to the `beta` dist-tag (not `latest`)
57
- 4. Users on stable versions won't get beta updates
58
-
59
- ### Promoting Beta to Stable
60
-
61
- ```bash
62
- # Update version to stable
63
- npm version 0.0.19
64
-
65
- # Publish as latest
66
- bun npm:publish
67
- ```
package/BUILD.md DELETED
@@ -1,90 +0,0 @@
1
- # Build System
2
-
3
- This document describes Electrobun's build system and cross-platform compilation approach.
4
-
5
- ## Overview
6
-
7
- Electrobun uses a custom build system (`build.ts`) that handles:
8
- - Vendoring dependencies (Bun, Zig, CEF, WebView2)
9
- - Building native wrappers for each platform
10
- - Creating distribution packages
11
-
12
- ## Platform-Specific Native Wrappers
13
-
14
- ### macOS
15
- - Single `libNativeWrapper.dylib` with weak linking to CEF framework
16
- - Uses `-weak_framework 'Chromium Embedded Framework'` for optional CEF support
17
- - Gracefully falls back to WebKit when CEF is not bundled
18
-
19
- ### Windows
20
- - Single `libNativeWrapper.dll` with runtime CEF detection
21
- - Links both WebView2 and CEF libraries at build time
22
- - Uses runtime checks to determine which webview engine to use
23
-
24
- ### Linux
25
- **Dual Binary Approach** - Linux builds create two separate native wrapper binaries:
26
-
27
- #### `libNativeWrapper.so` (GTK-only)
28
- - Size: ~1.46MB
29
- - Dependencies: WebKitGTK, GTK+3, AppIndicator only
30
- - No CEF dependencies linked
31
- - Used when `bundleCEF: false` in electrobun.config
32
-
33
- #### `libNativeWrapper_cef.so` (CEF-enabled)
34
- - Size: ~3.47MB
35
- - Dependencies: WebKitGTK, GTK+3, AppIndicator + CEF libraries
36
- - Full CEF functionality available
37
- - Used when `bundleCEF: true` in electrobun.config
38
-
39
- #### Why Dual Binaries?
40
-
41
- Unlike macOS and Windows, Linux doesn't have reliable weak linking for shared libraries. Hard linking CEF libraries causes `dlopen` failures when CEF isn't bundled. The dual binary approach provides:
42
-
43
- 1. **Small bundle sizes** - Developers can ship lightweight apps without CEF overhead
44
- 2. **Flexibility** - Same codebase supports both system WebKitGTK and CEF rendering
45
- 3. **Reliability** - No runtime linking failures or undefined symbols
46
-
47
- #### CLI Binary Selection
48
-
49
- The Electrobun CLI automatically copies the appropriate binary based on the `bundleCEF` setting:
50
-
51
- ```typescript
52
- const useCEF = config.build.linux?.bundleCEF;
53
- const nativeWrapperSource = useCEF
54
- ? PATHS.NATIVE_WRAPPER_LINUX_CEF
55
- : PATHS.NATIVE_WRAPPER_LINUX;
56
- ```
57
-
58
- Both binaries are included in the distributed `electrobun` npm package, ensuring developers can toggle CEF support without recompilation.
59
-
60
- ## Build Commands
61
-
62
- ```bash
63
- # Full build with all platforms
64
- bun build.ts
65
-
66
- # Development build with playground
67
- bun dev:playground
68
-
69
- # Release build
70
- bun build.ts --release
71
-
72
- # CI build
73
- bun build.ts --ci
74
- ```
75
-
76
- ## Architecture Support
77
-
78
- - **macOS**: ARM64 (Apple Silicon), x64 (Intel)
79
- - **Windows**: x64 only (ARM Windows users run via automatic emulation)
80
- - **Linux**: x64, ARM64
81
-
82
- ### Windows Architecture Notes
83
-
84
- Windows builds are created on ARM VMs but target x64 architecture. Both x64 and ARM Windows users use the same x64 binary:
85
- - **x64 Windows**: Runs natively
86
- - **ARM Windows**: Runs via automatic Windows emulation layer
87
-
88
- This approach simplifies distribution while maintaining compatibility across Windows architectures.
89
-
90
- The build system automatically detects the host architecture and downloads appropriate dependencies.
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Blackboard Technologies inc.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,102 +0,0 @@
1
- <p align="center">
2
- <a href="https://electrobun.dev"><img src="https://github.com/blackboardsh/electrobun/assets/75102186/8799b522-0507-45e9-86e3-c3cfded1aa7c" alt="Logo" height=170></a>
3
- </p>
4
- <h1 align="center">Electrobun</h1>
5
-
6
- <div align="center">
7
- </div>
8
-
9
- ## What is Electrobun?
10
-
11
- Electrobun aims to be a complete **solution-in-a-box** for building, updating, and shipping ultra fast, tiny, and cross-platform desktop applications written in Typescript.
12
- Under the hood it uses <a href="https://bun.sh">bun</a> to execute the main process and to bundle webview typescript, and has native bindings written in <a href="https://ziglang.org/">zig</a>.
13
-
14
- Visit <a href="https://blackboard.sh/electrobun/">https://blackboard.sh/electrobun/</a> to see api documentation, guides, and more.
15
-
16
- **Project Goals**
17
-
18
- - Write typescript for the main process and webviews without having to think about it.
19
- - Isolation between main and webview processes with fast, typed, easy to implement RPC between them.
20
- - Small self-extracting app bundles ~12MB (when using system webview, most of this is the bun runtime)
21
- - Even smaller app updates as small as 14KB (using bsdiff it only downloads tiny patches between versions)
22
- - Provide everything you need in one tightly integrated workflow to start writing code in 5 minutes and distribute in 10.
23
-
24
- ## Architecture
25
-
26
- Read about how Electrobun is designed, and why, in our <a href="https://www.electrobun.dev/docs/guides/Architecture/Overview">architecture docs</a>.
27
-
28
- ## Apps Built with Electrobun
29
- - [Co(lab)](https://blackboard.sh/colab/) - a hybrid web browser + code editor for deep work
30
-
31
- ## Roadmap
32
-
33
- See the <a href="https://github.com/orgs/blackboardsh/projects/5">roadmap</a>
34
-
35
- ## Contributing
36
-
37
- On the road to a stable 1.0.0 I'm probably going to just be pushing directly to main a lot.
38
-
39
- As we get closer to 1.0.0 I'll probably make guidelines for PRs and stuff. In the meantime if you find this project and want to contribute code it's probably best to create an issue first or ping me on twitter or discord to discuss when, what, and how is best to do that.
40
-
41
- Ways to get involved at this early stage:
42
-
43
- - Follow us on X for updates <a href="https://twitter.com/BlackboardTech">@BlackboardTech</a> or <a href="https://bsky.app/profile/yoav.codes">@yoav.codes</a>
44
- - Join the conversation on <a href="https://discord.gg/ueKE4tjaCE">Discord</a>
45
- - Create and participate in Github issues and discussions
46
-
47
- ## Development Setup
48
-
49
- ### Prerequisites
50
-
51
- **macOS:**
52
- - Xcode command line tools
53
- - cmake (install via homebrew: `brew install cmake`)
54
-
55
- **Windows:**
56
- - Visual Studio Build Tools or Visual Studio with C++ development tools
57
- - cmake
58
-
59
- **Linux:**
60
- - build-essential package
61
- - cmake
62
- - webkit2gtk and GTK development packages
63
-
64
- On Ubuntu/Debian based distros: `sudo apt install build-essential cmake pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev`
65
-
66
- ### First-time Setup
67
-
68
- ```bash
69
- git clone --recurse-submodules https://github.com/blackboardsh/electrobun.git
70
- cd electrobun
71
- bun install
72
- bun dev:playground:clean
73
- # On Linux, use:
74
- bun dev:playground:clean:linux
75
- ```
76
-
77
- ### Development Workflow
78
-
79
- ```bash
80
- # After making changes to source code
81
- bun dev:playground
82
- # On Linux, use:
83
- bun dev:playground:linux
84
-
85
- # If you only changed playground code (not electrobun source)
86
- bun dev:playground:rerun
87
-
88
- # If you need a completely fresh start
89
- bun dev:playground:clean
90
- # On Linux, use:
91
- bun dev:playground:clean:linux
92
- ```
93
-
94
- ### Additional Commands
95
-
96
- - `bun dev:playground:canary` - Build and run playground in canary mode
97
- - `bun build:dev` - Build electrobun in development mode
98
- - `bun build:release` - Build electrobun in release mode
99
-
100
- ### Debugging
101
-
102
- **macOS:** Use `lldb <path-to-bundle>/Contents/MacOS/launcher` and then `run` to debug release builds
package/debug.js DELETED
@@ -1,5 +0,0 @@
1
- console.log('process.argv:', process.argv);
2
- const indexOfElectrobun = process.argv.findIndex((arg) => arg.includes('electrobun'));
3
- console.log('indexOfElectrobun:', indexOfElectrobun);
4
- const commandArg = process.argv[indexOfElectrobun + 1] || 'build';
5
- console.log('commandArg:', commandArg);