@phystack/browser 4.3.40-dev

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 ADDED
@@ -0,0 +1,44 @@
1
+ # @phystack/browser
2
+
3
+ A simple Electron browser for the Phygrid platform.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @phystack/browser
9
+ # or
10
+ yarn global add @phystack/browser
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ # Basic usage - opens default URL
17
+ phy-browser
18
+
19
+ # Open a specific URL
20
+ phy-browser --url https://example.com
21
+
22
+ # Set window dimensions
23
+ phy-browser --width 1280 --height 800
24
+
25
+ # Launch in fullscreen mode
26
+ phy-browser --fullscreen
27
+
28
+ # Launch in kiosk mode
29
+ phy-browser --kiosk
30
+
31
+ # Open with DevTools
32
+ phy-browser --dev
33
+ ```
34
+
35
+ ## Options
36
+
37
+ - `-u, --url <url>`: URL to open in the browser window (default: "https://phygrid.com")
38
+ - `-w, --width <width>`: Window width (default: "1024")
39
+ - `-h, --height <height>`: Window height (default: "768")
40
+ - `-f, --fullscreen`: Launch in fullscreen mode
41
+ - `-k, --kiosk`: Launch in kiosk mode
42
+ - `-d, --dev`: Open DevTools on startup
43
+ - `-V, --version`: Output the version number
44
+ - `--help`: Display help for command
package/bin/index.js ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawn } = require('child_process');
4
+ const path = require('path');
5
+ const electron = require('electron');
6
+ const isDev = process.env.NODE_ENV === 'development';
7
+
8
+ // Pass all arguments to electron
9
+ const args = process.argv.slice(2);
10
+ args.unshift(path.join(__dirname, '../dist/index.js'));
11
+
12
+ // Set environment variables
13
+ const env = Object.assign({}, process.env);
14
+ if (isDev) {
15
+ console.log('Starting Electron in development mode');
16
+ env.NODE_ENV = 'development';
17
+ } else {
18
+ console.log('Starting Electron in production mode');
19
+ env.NODE_ENV = 'production';
20
+ }
21
+
22
+ // Spawn electron process
23
+ const proc = spawn(electron, args, {
24
+ stdio: 'inherit',
25
+ env
26
+ });
27
+
28
+ proc.on('close', (code) => {
29
+ process.exit(code);
30
+ });
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const electron_1 = require("electron");
7
+ const commander_1 = require("commander");
8
+ const path_1 = __importDefault(require("path"));
9
+ // Define the command line options
10
+ commander_1.program
11
+ .version('1.0.0')
12
+ .option('-u, --url <url>', 'URL to open in the browser window', 'https://phygrid.com')
13
+ .option('-w, --width <width>', 'Window width', '1280')
14
+ .option('-h, --height <height>', 'Window height', '800')
15
+ .option('-f, --fullscreen', 'Launch in fullscreen mode')
16
+ .option('-k, --kiosk', 'Launch in kiosk mode')
17
+ .option('-d, --dev', 'Open DevTools on startup');
18
+ commander_1.program.parse(process.argv);
19
+ const options = commander_1.program.opts();
20
+ // Check if we're in development mode
21
+ const isDev = process.env.NODE_ENV === 'development';
22
+ // Store URL for preload script
23
+ electron_1.app.commandLine.appendSwitch('app-url', options.url);
24
+ // Prevent multiple instances of the app
25
+ const gotTheLock = electron_1.app.requestSingleInstanceLock();
26
+ if (!gotTheLock) {
27
+ console.log('Another instance is already running. Exiting...');
28
+ electron_1.app.quit();
29
+ }
30
+ else {
31
+ // Create window when the app is ready
32
+ let mainWindow = null;
33
+ function createWindow() {
34
+ mainWindow = new electron_1.BrowserWindow({
35
+ width: parseInt(options.width, 10),
36
+ height: parseInt(options.height, 10),
37
+ fullscreen: options.fullscreen || false,
38
+ kiosk: options.kiosk || false,
39
+ webPreferences: {
40
+ preload: path_1.default.join(__dirname, 'preload.js'),
41
+ nodeIntegration: false,
42
+ contextIsolation: true,
43
+ sandbox: true,
44
+ webSecurity: true,
45
+ webviewTag: true, // Enable the webview tag
46
+ },
47
+ });
48
+ // Load the app
49
+ if (isDev) {
50
+ console.log('Running in development mode - loading from dev server at http://localhost:3424');
51
+ // In development mode, load from webpack dev server
52
+ mainWindow.loadURL('http://localhost:3424');
53
+ }
54
+ else {
55
+ console.log('Running in production mode - loading from built files');
56
+ // In production mode, load from the built files
57
+ mainWindow.loadFile(path_1.default.join(__dirname, 'renderer/index.html'));
58
+ }
59
+ if (options.dev || isDev) {
60
+ mainWindow.webContents.openDevTools();
61
+ }
62
+ mainWindow.on('closed', () => {
63
+ mainWindow = null;
64
+ });
65
+ }
66
+ electron_1.app.on('ready', createWindow);
67
+ electron_1.app.on('window-all-closed', () => {
68
+ if (process.platform !== 'darwin') {
69
+ electron_1.app.quit();
70
+ }
71
+ });
72
+ electron_1.app.on('activate', () => {
73
+ if (mainWindow === null) {
74
+ createWindow();
75
+ }
76
+ });
77
+ // Handle second instance
78
+ electron_1.app.on('second-instance', () => {
79
+ if (mainWindow) {
80
+ if (mainWindow.isMinimized()) {
81
+ mainWindow.restore();
82
+ }
83
+ mainWindow.focus();
84
+ }
85
+ });
86
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const electron_1 = require("electron");
4
+ // Get the URL from command line arguments or use default when in dev mode
5
+ let url = 'https://phygrid.com';
6
+ // In production, try to get URL from command line
7
+ const urlArg = process.argv.find(arg => arg.startsWith('--app-url='));
8
+ if (urlArg) {
9
+ url = urlArg.split('=')[1];
10
+ }
11
+ // Expose protected methods that allow the renderer process to use
12
+ // the ipcRenderer without exposing the entire object
13
+ electron_1.contextBridge.exposeInMainWorld('electron', {
14
+ // Add any needed IPC methods here
15
+ appUrl: url,
16
+ isDev: process.env.NODE_ENV === 'development',
17
+ sendMessage: (channel, data) => {
18
+ // Whitelist channels to ensure only approved channels are used
19
+ const validChannels = ['toMain'];
20
+ if (validChannels.includes(channel)) {
21
+ electron_1.ipcRenderer.send(channel, data);
22
+ }
23
+ },
24
+ receive: (channel, func) => {
25
+ const validChannels = ['fromMain'];
26
+ if (validChannels.includes(channel)) {
27
+ // Remove the event listener to avoid memory leaks
28
+ electron_1.ipcRenderer.removeAllListeners(channel);
29
+ // Add a new listener
30
+ electron_1.ipcRenderer.on(channel, (_, ...args) => func(...args));
31
+ }
32
+ }
33
+ });
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const App: React.FC;
3
+ export default App;
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
7
+ /** @jsxImportSource @emotion/react */
8
+ const react_1 = require("@emotion/react");
9
+ const react_2 = require("react");
10
+ const Sidebar_1 = __importDefault(require("./Sidebar"));
11
+ const appContainerStyle = (0, react_1.css) `
12
+ position: absolute;
13
+ top: 0;
14
+ left: 0;
15
+ right: 0;
16
+ bottom: 0;
17
+ display: flex;
18
+ flex-direction: row;
19
+ height: 100%;
20
+ width: 100%;
21
+ `;
22
+ const mainContentStyle = (0, react_1.css) `
23
+ flex: 1;
24
+ height: 100%;
25
+ position: relative;
26
+ overflow: hidden;
27
+ `;
28
+ const webviewStyle = (0, react_1.css) `
29
+ width: 100%;
30
+ height: 100%;
31
+ border: none;
32
+ display: block;
33
+ border: 5px solid red;
34
+ `;
35
+ const dividerStyle = (0, react_1.css) `
36
+ width: 4px;
37
+ height: 100%;
38
+ background-color: #3C4043;
39
+ cursor: col-resize;
40
+ flex-shrink: 0;
41
+ position: relative;
42
+ &:hover {
43
+ background-color: #4285F4;
44
+ }
45
+ `;
46
+ const sidebarContainerStyle = (0, react_1.css) `
47
+ width: 450px;
48
+ min-width: 250px;
49
+ max-width: 50%;
50
+ height: 100%;
51
+ background-color: #202124;
52
+ color: #E8EAED;
53
+ overflow-y: auto;
54
+ flex-shrink: 0;
55
+ display: flex;
56
+ flex-direction: column;
57
+ `;
58
+ const App = () => {
59
+ const dividerRef = (0, react_2.useRef)(null);
60
+ const appRef = (0, react_2.useRef)(null);
61
+ const sidebarRef = (0, react_2.useRef)(null);
62
+ const mainRef = (0, react_2.useRef)(null);
63
+ const [isDragging, setIsDragging] = (0, react_2.useState)(false);
64
+ // Get the URL from the preload script
65
+ const appUrl = window.electron?.appUrl || 'https://phygrid.com';
66
+ (0, react_2.useEffect)(() => {
67
+ const divider = dividerRef.current;
68
+ const container = appRef.current;
69
+ const sidebar = sidebarRef.current;
70
+ const main = mainRef.current;
71
+ if (!divider || !container || !sidebar || !main)
72
+ return;
73
+ let startX = 0;
74
+ let startSidebarWidth = 0;
75
+ const onMouseDown = (e) => {
76
+ setIsDragging(true);
77
+ startX = e.clientX;
78
+ startSidebarWidth = sidebar.offsetWidth;
79
+ document.addEventListener('mousemove', onMouseMove);
80
+ document.addEventListener('mouseup', onMouseUp);
81
+ document.body.style.cursor = 'col-resize';
82
+ document.body.style.userSelect = 'none';
83
+ // Prevent text selection during drag
84
+ e.preventDefault();
85
+ };
86
+ const onMouseMove = (e) => {
87
+ if (!isDragging)
88
+ return;
89
+ // Calculate new width based on mouse movement
90
+ // For right sidebar: we need to SUBTRACT the movement from initial width
91
+ // (moving left = make sidebar bigger, moving right = make sidebar smaller)
92
+ const dx = e.clientX - startX;
93
+ let newWidth = startSidebarWidth - dx;
94
+ // Apply constraints
95
+ newWidth = Math.max(250, newWidth); // Min width
96
+ newWidth = Math.min(container.offsetWidth * 0.7, newWidth); // Max width
97
+ // Set sidebar width
98
+ sidebar.style.width = `${newWidth}px`;
99
+ // Force webview update
100
+ const webview = main.querySelector('webview');
101
+ if (webview) {
102
+ webview.style.width = '100%';
103
+ }
104
+ };
105
+ const onMouseUp = () => {
106
+ setIsDragging(false);
107
+ document.removeEventListener('mousemove', onMouseMove);
108
+ document.removeEventListener('mouseup', onMouseUp);
109
+ document.body.style.cursor = '';
110
+ document.body.style.userSelect = '';
111
+ };
112
+ divider.addEventListener('mousedown', onMouseDown);
113
+ return () => {
114
+ divider.removeEventListener('mousedown', onMouseDown);
115
+ document.removeEventListener('mousemove', onMouseMove);
116
+ document.removeEventListener('mouseup', onMouseUp);
117
+ };
118
+ }, [isDragging]);
119
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: appRef, css: appContainerStyle, children: [(0, jsx_runtime_1.jsx)("div", { ref: mainRef, css: mainContentStyle, children: (0, jsx_runtime_1.jsx)("webview", { src: appUrl, css: webviewStyle }) }), (0, jsx_runtime_1.jsx)("div", { ref: dividerRef, css: dividerStyle }), (0, jsx_runtime_1.jsx)("div", { ref: sidebarRef, css: sidebarContainerStyle, children: (0, jsx_runtime_1.jsx)(Sidebar_1.default, {}) })] }));
120
+ };
121
+ exports.default = App;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ declare const Sidebar: React.FC;
3
+ export default Sidebar;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const jsx_runtime_1 = require("@emotion/react/jsx-runtime");
4
+ /** @jsxImportSource @emotion/react */
5
+ const react_1 = require("@emotion/react");
6
+ const sidebarStyle = (0, react_1.css) `
7
+ height: 100%;
8
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
9
+ display: flex;
10
+ flex-direction: column;
11
+ font-size: 12px;
12
+ `;
13
+ const sidebarHeaderStyle = (0, react_1.css) `
14
+ padding: 8px 12px;
15
+ border-bottom: 1px solid #3C4043;
16
+ background-color: #202124;
17
+ `;
18
+ const headingStyle = (0, react_1.css) `
19
+ color: #fff;
20
+ font-size: 16px;
21
+ font-weight: 400;
22
+ `;
23
+ const sectionStyle = (0, react_1.css) `
24
+ margin-bottom: 8px;
25
+ border-bottom: 1px solid #3C4043;
26
+ `;
27
+ const sectionHeaderStyle = (0, react_1.css) `
28
+ padding: 8px 12px;
29
+ font-size: 12px;
30
+ font-weight: 500;
31
+ color: #E8EAED;
32
+ background-color: #2D2F31;
33
+ cursor: pointer;
34
+ user-select: none;
35
+ `;
36
+ const sectionContentStyle = (0, react_1.css) `
37
+ padding: 8px 12px;
38
+ `;
39
+ const paragraphStyle = (0, react_1.css) `
40
+ color: #9AA0A6;
41
+ margin-bottom: 6px;
42
+ line-height: 1.4;
43
+ font-size: 12px;
44
+ `;
45
+ const codeStyle = (0, react_1.css) `
46
+ font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
47
+ color: #E8EAED;
48
+ `;
49
+ const consoleLineStyle = (0, react_1.css) `
50
+ font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
51
+ margin-bottom: 4px;
52
+ line-height: 1.5;
53
+ `;
54
+ const consoleInfoStyle = (0, react_1.css) `
55
+ color: #8AB4F8;
56
+ margin-right: 6px;
57
+ `;
58
+ const consoleWarningStyle = (0, react_1.css) `
59
+ color: #F29900;
60
+ margin-right: 6px;
61
+ `;
62
+ const consoleInputStyle = (0, react_1.css) `
63
+ color: #9AA0A6;
64
+ `;
65
+ const consoleOutputStyle = (0, react_1.css) `
66
+ color: #80CBC4;
67
+ `;
68
+ const indentStyle = (level) => (0, react_1.css) `
69
+ margin-left: ${level * 20}px;
70
+ `;
71
+ const Sidebar = () => {
72
+ return ((0, jsx_runtime_1.jsxs)("div", { css: sidebarStyle, children: [(0, jsx_runtime_1.jsx)("div", { css: sidebarHeaderStyle, children: (0, jsx_runtime_1.jsx)("h1", { css: headingStyle, children: "DevTools Panel" }) }), (0, jsx_runtime_1.jsxs)("div", { css: sectionStyle, children: [(0, jsx_runtime_1.jsx)("div", { css: sectionHeaderStyle, children: "Elements" }), (0, jsx_runtime_1.jsxs)("div", { css: sectionContentStyle, children: [(0, jsx_runtime_1.jsx)("p", { css: paragraphStyle, children: (0, jsx_runtime_1.jsx)("code", { css: codeStyle, children: "<html>" }) }), (0, jsx_runtime_1.jsx)("p", { css: [paragraphStyle, indentStyle(1)], children: (0, jsx_runtime_1.jsx)("code", { css: codeStyle, children: "<head>...</head>" }) }), (0, jsx_runtime_1.jsx)("p", { css: [paragraphStyle, indentStyle(1)], children: (0, jsx_runtime_1.jsx)("code", { css: codeStyle, children: "<body>" }) }), (0, jsx_runtime_1.jsx)("p", { css: [paragraphStyle, indentStyle(2)], children: (0, jsx_runtime_1.jsx)("code", { css: codeStyle, children: "<div id=\"root\">" }) }), (0, jsx_runtime_1.jsx)("p", { css: [paragraphStyle, indentStyle(3)], children: (0, jsx_runtime_1.jsx)("code", { css: codeStyle, children: "<div class=\"app-container\">" }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { css: sectionStyle, children: [(0, jsx_runtime_1.jsx)("div", { css: sectionHeaderStyle, children: "Console" }), (0, jsx_runtime_1.jsxs)("div", { css: sectionContentStyle, children: [(0, jsx_runtime_1.jsxs)("p", { css: consoleLineStyle, children: [(0, jsx_runtime_1.jsx)("span", { css: consoleInfoStyle, children: "\u2139\uFE0F " }), "React app loaded successfully"] }), (0, jsx_runtime_1.jsxs)("p", { css: consoleLineStyle, children: [(0, jsx_runtime_1.jsx)("span", { css: consoleWarningStyle, children: "\u26A0\uFE0F " }), "Resizable sidebar is active"] }), (0, jsx_runtime_1.jsx)("p", { css: [consoleLineStyle, consoleInputStyle], children: "> document.title" }), (0, jsx_runtime_1.jsx)("p", { css: [consoleLineStyle, consoleOutputStyle], children: "\"Phygrid Browser\"" })] })] }), (0, jsx_runtime_1.jsxs)("div", { css: sectionStyle, children: [(0, jsx_runtime_1.jsx)("div", { css: sectionHeaderStyle, children: "Instructions" }), (0, jsx_runtime_1.jsxs)("div", { css: sectionContentStyle, children: [(0, jsx_runtime_1.jsx)("p", { css: paragraphStyle, children: "This sidebar emulates Chrome DevTools" }), (0, jsx_runtime_1.jsxs)("p", { css: paragraphStyle, children: [(0, jsx_runtime_1.jsx)("strong", { children: "Drag the vertical divider" }), " to resize this panel"] })] })] })] }));
73
+ };
74
+ exports.default = Sidebar;