UNPKG

pear-electron

Version:

Pear User-Interface Library for Electron

1,066 lines (627 loc) 35.6 kB
# pear-electron > Pear User-Interface Library for Electron ## Installation <a name="installation"></a> ```sh npm install pear-electron ``` ## Usage Ensure the `package.json` `pear` configuration object contains a `pre` field pointing to `pear-electron/pre`. ```js { "pear": { "pre": "pear-electron/pre" } } ``` Instantiate a `pear-electron` runtime instance from a Pear Application's entrypoint JavaScript file: ```js import Runtime from 'pear-electron' import Bridge from 'pear-bridge' const runtime = new Runtime() const bridge = new Bridge() await bridge.ready() const pipe = runtime.start({ bridge }) Pear.teardown(() => pipe.end()) ``` Call `runtime.start` to open the UI. > NOTE: naming the import `Runtime` instead of `PearElectron` is intentional, for two reasons. The `pear-electron` import resolves to a runtime start library or a User Interface library depending on environment and using `Runtime` and `ui` as assigned names means switching out `pear-electron` with an equivalent alternative only involves changing the two `pear-electron` import specifiers. Given an `index.html` containing `<script src="./app.js"></script>` in `app.js` import `pear-electron` User Interface API: ```js import ui from 'pear-electron' ``` ## Application Configuration <a name="application-configuration"></a> Set the [`pear.pre`](https://docs.pears.com/configuration#pear-pre) to `pear-electron/pre` (or ensure that it's imported at the top of any alternative pre script). ```json { "pear": { "pre": "pear-electron/pre" } } ``` Prior to run from disk and prior to run from key, the `pear-electron/pre` script automatically adjusts application configuration to include runtime binary [`pear.assets`](https://docs.pears.com/configuration#pear-assets) as well as adding statically analyzed script tags as [`pear.stage.entrypoints`](https://docs.pears.com/configuration#pear-stage-entrypoints) from the [`pear.gui.main`](#pear-gui-main) HTML entrypoint. The application `package.json` `pear` field can also define its own [`pear.assets`](https://docs.pears.com/configuration#pear-assets). ## Initialization API <a name="initialization-api"></a> ### `new Runtime() -> runtime` <a name="new-runtime"></a> Create the runtime instances with `new Runtime()`. ### `runtime.ready()` <a name="runtime-ready"></a> Prepare the runtime, runtime binaries for the runtime version may be bootstrapped peer-to-peer at this point. This only runs once per version and any prior bootstraps can be reused for subsequent versions where state hasn't changed. In a production scenario any bootstrapping would be performed in advance by the application distributable. ### `runtime.start(opts)` <a name="runtime-start"></a> Opens the UI. #### Options * `bridge` - An instance of [`pear-bridge`](https://github.com/holepunchto/pear-bridge). ## User-Interface API <a name="user-interface-api"></a> Inside the `pear-electron` runtime desktop application, pear-electron resolves to a UI control API. **index.html**: ```html <script src="./app.js" type="module"><script> ``` **app.js**: ```js import ui from 'pear-electron' // do something with ui: setTimeout(async () => { await ui.app.focus({ steal: true }) }) ``` > NOTE: naming the import `ui` instead of `PearElectron` is intentional, for two reasons. The `pear-electron` import resolves to a runtime start library or a User Interface library depending on environment and using `Runtime` and `ui` as assigned names means switching out `pear-electron` with an equivalent alternative only involves changing the two `pear-electron` import specifiers. ### `ui.app <Object>` <a name="ui-app"></a> UI Application controls ### `const success = await ui.app.focus([options <Object>])` <a name="ui-app-focus"></a> Resolves to: `<Boolean>` Foreground current view or window. **Options** * `steal` Default: `false` - focus input as well as foregrounding ### `const success = await ui.app.blur()` <a name="ui-app-blur"></a> Resolves to: `<Boolean>` Blur current view or window. ### `const success = await ui.app.show()` <a name="ui-app-show"></a> Resolves to: `<Boolean>` Show current view or window. ### `const success = await ui.app.hide()` <a name="ui-app-hide"></a> Resolves to: `<Boolean>` Hide current view or window. #### `const success = await ui.app.badge(count <Integer|null>)` <a name="ui-app-badge"></a> Resolves to: `<Boolean>` Set the badge number for the application on desktop for Linux & MacOS. Setting the `count` to `0` will hide the badge while `null` will display a plain dot on MacOS only. Returns a `Boolean` promise for whether the call succeeded. #### `const untray = await ui.app.tray(options <Object>[, listener <Function>])` <a name="ui-app-tray"></a> Resolves to: `<Function>` Configure a tray icon for the application. This method will return a promise which resolves to an `untray()` function for removing the tray. The `listener` function is triggered whenever a menu item or the tray icon is clicked. It receives a single argument `key` that represents the menu item `key` that was clicked or the special value of `'click'` for when the menu icon itself was clicked. If no `listener` function is provided, a default listener will show the application window when triggered with `'click'` or `'show'` and quits with `'quit'`. A Pear application should set `pear.gui.closeHide` option to `true` in `package.json` `pear` options object when using `ui.app.tray`. WARNING: Linux tray support varies which can cause scenarios where the application's tray doesn't work and closing the app will be hidden and inaccessible. Using a tray and `closeHide` on Linux is not recommended. Set `pear.gui.linux.closeHide` option to `false` in `package.json` `pear` options object. **Options** * `icon <String>` Default: The Pear icon - The path for icon for the tray relative to the project root. Supported formats: PNG & JPEG * `menu <Object>` Default: ``{ show: `Show ${Pear.app.name}`, quit: 'Quit' }`` - The tray menu items. Each property of the object is the `key` passed to the `listener` and whose value is the text displayed in the menu. * `os <Object>` Default: `{ win32: true, linux: true, darwin: true }` - which platforms support using the tray menu. The platform is checked via the `process.platform` value. ### `const sourceId = await ui.app.getMediaSourceId()` <a name="ui-app-getmediasourceid"></a> Get the sourceId of the current window or view. ### `const success = await ui.app.minimize()` <a name="ui-app-minimize"></a> Resolves to: `<Boolean>` Minimize current window. ### `const success = await ui.app.maximize()` <a name="ui-app-maximize"></a> Resolves to: `<Boolean>` Maximize current window. ### `const success = await ui.app.restore()` <a name="ui-app-restore"></a> Resolves to: `<Boolean>` Unmaximize/unminimize the current window if it is currently maximized/minimized. ### `const success = await ui.app.close()` <a name="ui-app-close"></a> Resolves to: `<Boolean>` Closes the current view or window. ### `const isVisible = await ui.app.isVisible()` <a name="ui-app-isvisible"></a> Resolves to: `<Boolean>` Whether the current window or view is visible. ### `const isMaximized = await ui.app.isMaximized()` <a name="ui-app-ismaximized"></a> Resolves to: `<Boolean>` ### `const isMinimized = await ui.app.isMinimized()` <a name="ui-app-isminimized"></a> Resolves to: `<Boolean>` ### `const found = await ui.app.find(options <Object>)` <a name="ui-app-find"></a> Resolves to: `<Found> extends <streamx.Readable>` Find and select text, emit matches as data events. **Options** * text `<String>` - search term * forward `<Boolean>` - search forward (`true`) or backward (`false`). Defaults `true`. * matchCase `<Boolean>` - case-sensitivity. Default `false`. #### `await found.proceed()` <a name="found-proceed"></a> Find & select next match, emit result as stream data. #### `await found.clear()` <a name="found-clear"></a> Stop search and clear matching text selection. Implies destroy. #### `await found.keep()` <a name="found-keep"></a> Stop search and convert matching text selection to text highlight. Implies destroy. #### `await found.activate()` <a name="found-activate"></a> Stop search and simulate a click event on the selected match. Implies destroy. ### `ui.media <Object>` <a name="ui-media"></a> Media interface #### `const status = await ui.media.status.microphone()` <a name="ui-media-status-microphone"></a> Resolves to: `<String>` If access to the microphone is available, resolved value will be `'granted'`. Any other string indicates lack of permission. Possible values are `'granted'`, `'not-determined'`, `'denied'`, `'restricted'`, `'unknown'`. #### `const status = await ui.media.status.camera()` <a name="ui-media-status-camera"></a> Resolves to: `<String>` If access to the camera is available, resolved value will be `'granted'`. Any other string indicates lack of permission. Possible values are `'granted'`, `'not-determined'`, `'denied'`, `'restricted'`, `'unknown'`. #### `const status = await ui.media.status.screen()` <a name="ui-media-status-screen"></a> Resolves to: `<String>` If access to the screen is available, resolved value will be `'granted'`. Any other string indicates lack of permission. Possible values are `'granted'`, `'not-determined'`, `'denied'`, `'restricted'`, `'unknown'`. #### `const success = await ui.media.access.microphone()` <a name="ui-media-access-microphone"></a> Resolves to: `<Boolean>` Request access to the microphone. Resolves to `true` if permission is granted. #### `const success = await ui.media.access.camera()` <a name="ui-media-access-camera"></a> Resolves to: `<Boolean>` Request access to the camera. Resolves to `true` if permission is granted. #### `const success = await ui.media.access.screen()` <a name="ui-media-access-screen"></a> Resolves to: `<Boolean>` Request access to screen sharing. Resolves to `true` if permission is granted. #### `const sources = await ui.media.desktopSources(options <Object>)` <a name="ui-media-desktopsources"></a> Captures available desktop sources. Resolves to an array of objects with shape `{ id <String>, name <String>, thumbnail <NativeImage>, display_id <String>, appIcon <NativeImage> }`. The `id` is the window or screen identifier. The `name` is the window title or `'Screen <index>'` in multiscreen scenarios or else `Entire Screen`. The `display_id` identifies the screen. The thumbnail is a scaled down screen capture of the window/screen. **Options** * `types <Array<String>>` - Default: `['screen', 'window']`. Filter by types. Types are `'screen'` and `'window'`. * `thumbnailSize <Object>` - Default: `{width: 150, height: 150}`. Set thumbnail scaling (pixels) * `fetchWindowIcons <Boolean>` - Default: `false`. Populate `appIcon` with Window icons, or else `null`. **See Also** * [app.getMediaSourceId()](#app-getmediasourceid) * [view.getMediaSourceId()](#view-getmediasourceid) * [win.getMediaSourceId()](#win-getmediasourceid) * [parent.getMediaSourceId()](#parent-getmediasourceid) * https://www.electronjs.org/docs/latest/api/desktop-capturer#desktopcapturergetsourcesoptions * https://www.electronjs.org/docs/latest/api/structures/desktop-capturer-source * [`<NativeImage>`](https://www.electronjs.org/docs/latest/api/native-image) Exits the process with the provided exit code. ### `const win = new ui.Window(entry <String>, options <Object>)` <a name="ui-window"></a> Desktop Applications only. Create a new `Window` instance. **Options** * `show <Boolean>` Default: `true` - show the window as soon as it has been opened * `x <Integer>` - the horizontal position of left side of the window (pixels) * `y <Integer>` - vertical window position (pixels) * `width <Integer>` - the width of the window (pixels) * `height <Integer>` - the height of the window (pixels) * `animate <Boolean>` Default: `false` - animate the dimensional change. MacOS only, ignored on other OS's. * `center <Boolean` - center the window upon opening * `minWidth <Integer>` - window minimum width (pixels) * `minHeight <Integer>` - window minimum height (pixels) * `maxWidth <Integer>` - window maximum width (pixels) * `maxHeight <Integer>` - window maximum height (pixels) * `resizable <Boolean>` - window resizability * `movable <Boolean>` - window movability * `minimizable <Boolean>` - window minimizability * `maximizable <Boolean>` - window maximizability * `closable <Boolean>` - window closability * `focusable <Boolean>` - window focusability * `alwaysOnTop <Boolean>` - Set window to always be on top * `fullscreen <Boolean>` - Set window to fullscreen upon open * `kiosk <Boolean>` - Set window to enter kiosk mode upon open * `autoHideMenuBar <Boolean>` - Hide menu bar unless Alt key is pressed (Linux, Windows) * `hasShadow <Boolean>` - Set window shadow * `opacity <Number>` - Set window opacity (0.0 - 1.0) (Windows, macOS) * `transparent <Boolean>` - Set window transparency * `backgroundColor <String>` Default: `'#FFF'` - window default background color. Hex, RGB, RGBA, HSL HSLA, CSS color ### `win.on[ce]('message', (...args) => { })` <a name="win-recieve-messages"></a> ### `for await (const [ ...args ] of win)` Receive a message from the window. The received `args` array is deserialized via `JSON.parse`. ### `const success = await win.open(options <Object>)` <a name="win-open"> Resolves to: `<Boolean>` Open the window. **Options** * `show` Default: `true` - show the window as soon as it has been opened * `x <Integer>` - the horizontal position of left side of the window (pixels) * `y <Integer>` - vertical window position (pixels) * `width <Integer>` - the width of the window (pixels) * `height <Integer>` - the height of the window (pixels) * `animate <Boolean>` Default: `false` - animate the dimensional change. MacOS only, ignored on other OS's. * `center <Boolean` - center the window upon opening * `minWidth <Integer>` - window minimum width (pixels) * `minHeight <Integer>` - window minimum height (pixels) * `maxWidth <Integer>` - window maximum width (pixels) * `maxHeight <Integer>` - window maximum height (pixels) * `resizable <Boolean>` - window resizability * `movable <Boolean>` - window movability * `minimizable <Boolean>` - window minimizability * `maximizable <Boolean>` - window maximizability * `closable <Boolean>` - window closability * `focusable <Boolean>` - window focusability * `alwaysOnTop <Boolean>` - Set window to always be on top * `fullscreen <Boolean>` - Set window to fullscreen upon open * `kiosk <Boolean>` - Set window to enter kiosk mode upon open * `autoHideMenuBar <Boolean>` - Hide menu bar unless Alt key is pressed (Linux, Windows) * `hasShadow <Boolean>` - Set window shadow * `opacity <Number>` - Set window opacity (0.0 - 1.0) (Windows, macOS) * `transparent <Boolean>` - Set window transparency * `backgroundColor <String>` Default: `'#FFF'` - window default background color. Hex, RGB, RGBA, HSL HSLA, CSS color ### `const success = await win.close()` <a name="win-close"></a> Resolves to: `<Boolean>` Close the window. ### `const success = await win.show()` <a name="win-show"></a> Resolves to: `<Boolean>` Show the window. ### `const success = await win.hide()` <a name="win-hide"></a> Resolves to: `<Boolean>` Hide the window. ### `const success = await win.focus([options <Object>])` <a name="win-focus"></a> Resolves to: `<Boolean>` Focus the window. **Options** * `steal` Default: `true` - ### `const success = await win.blur()` <a name="win-blur"></a> Resolves to: `<Boolean>` Blur the window. ### `const success = await win.minimize()` <a name="win-minimize"></a> Resolves to: `<Boolean>` Minimize the window. ### `const success = await win.maximize()` <a name="win-maximize"></a> Resolves to: `<Boolean>` Maximize the window. ### `const success = await win.restore()` <a name="win-restore"></a> Resolves to: `<Boolean>` Unmaximize/unminimize the window if it is currently maximized/minimized. ### `const sourceId = await win.getMediaSourceId()` <a name="win-getmediasourceid"></a> Resolves to: `<String>` Correlates to the `id` property of objects in the array returned from [ui.media.desktopSources](#ui-media-desktopsources). ### `await win.send(...args)` <a name="win-send"></a> Send arguments to the window. They will be serialized with `JSON.stringify`. ### `const found = await win.find(options <Object>)` <a name="win-find"></a> Resolves to: `<Found> extends <streamx.Readable>` Find and select text, emit matches as data events. **Options** * text `<String>` - search term * forward `<Boolean>` - search forward (`true`) or backward (`false`). Defaults `true`. * matchCase `<Boolean>` - case-sensitivity. Default `false`. #### `await found.proceed()` <a name="win-find-found-proceed"></a> Find & select next match, emit result as stream data. #### `await found.clear()` <a name="win-find-found-clear"></a> Stop search and clear matching text selection. Implies destroy. #### `await found.keep()` <a name="win-find-found-keep"></a> Stop search and convert matching text selection to text highlight. Implies destroy. #### `await found.activate()` <a name="win-find-found-activate"></a> Stop search and simulate a click event on the selected match. Implies destroy. ### `const dimensions = await win.dimensions([options <Object>])` <a name="win-dimensions"></a> When options object is not provided, behaves as a getter and resolves to a a bounds object. Resolves to: `{x <Integer>, y <Integer>, width <Integer>, height <Integer>} | null`. The height, width, horizontal (`x`), vertical (`y`) position of the window relative to the screen. All units are (pixels) If the window is closed this will resolve to `null`. When options object is provided, behaves as a setter and resolves to `undefined`. ```js const win = new ui.Window('./some.html', { x: 10, y: 450, width: 300, height: 350 }) await win.open() await new Promise((resolve) => setTimeout(resolve, 1000)) await win.dimensions({ x: 20, y: 50, width: 550, height: 300, animate: true // only has an effect on macOS }) ``` Sets the dimensions of the window. **Options** * `x <Integer>` - the horizontal position of left side of the window (pixels) * `y <Integer>` - the vertical position of the top of the window (pixels) * `width <Integer>` - the width of the window (pixels) * `height <Integer>` - the height of the window (pixels) * `animate <Boolean>` Default: `false` - animate the dimensional change. MacOS only, ignored on other OS's. * `position <String>` - may be `'center'` to set the window in the center of the screen or else `undefined`. ### `const visible = await win.isVisible()` <a name="win-isvisible"></a> Resolves to: `<Boolean>` Whether the window is visible. ### `const minimized = await win.isMinimized()` <a name="win-isminimized"></a> Resolves to: `<Boolean>` Whether the window is minimized. ### `const maximized = await win.isMaximized()` <a name="win-ismaximized"></a> Resolves to: `<Boolean>` Whether the window is maximized. ### `const closed = await win.isClosed()` <a name="win-isclosed"></a> Resolves to: `<Boolean>` Whether the window is closed. ### `const view = new ui.View(options <Object>)` <a name="ui-view"></a> Desktop Applications only. Create a new `View` instance. Views provide isolated content views. Frameless, chromeless windows that can be embedded inside other windows and views. **Options** * `x <Integer>` - the horizontal position of left side of the view (pixels) * `y <Integer>` - vertical view position (pixels) * `width <Integer>` - the width of the view (pixels) * `height <Integer>` - the height of the view (pixels) * `backgroundColor <String>` Default: `'#FFF'` - view default background color. Hex, RGB, RGBA, HSL HSLA, CSS color * `autoresize <Object>` Default `{ width=true, height=true, vertical=false, horizontal=false }` - dimensions for the view to autoresize alongside. For example, if `width` is `true` and the view container increases/decreases in width, the view will increase/decrease in width at the same rate. * https://www.electronjs.org/docs/latest/api/browser-view#viewsetbackgroundcolorcolor-experimental ### `view.on[ce]('message', (...args) => { })` <a name="view-recieve-messages"></a> ### `for await (const [ ...args ] of view)` Receive a message from the view. The received `args` array is deserialized via `JSON.parse`. ### `const success = await view.open(options <Object>)` <a name="view-open"></a> Resolves to: `<Boolean>` Open the view. **Options** * `x <Integer>` - the horizontal position of left side of the view (pixels) * `y <Integer>` - vertical view position (pixels) * `width <Integer>` - the width of the view (pixels) * `height <Integer>` - the height of the view (pixels) * `backgroundColor <String>` Default: `'#FFF'` - view default background color. Hex, RGB, RGBA, HSL HSLA, CSS color * `autoresize <Object>` Default `{ width=true, height=true, vertical=false, horizontal=false }` - dimensions for the view to autoresize alongside. For example, if `width` is `true` and the view container increases/decreases in width, the view will increase/decrease in width at the same rate. ### `const success = await view.close()` <a name="view-close"></a> Resolves to: `<Boolean>` Close the view. ### `const success = await view.show()` <a name="view-show"></a> Resolves to: `<Boolean>` Show the view. ### `const success = await view.hide()` <a name="view-hide"></a> Resolves to: `<Boolean>` Hide the view. ### `const success = await view.focus([options <Object>])` <a name="view-focus"></a> Resolves to: `<Boolean>` Foreground the view. **Options** * `steal` Default: `false` - focus input as well as foregrounding ### `const success = await view.blur()` <a name="view-blur"></a> Resolves to: `<Boolean>` Blur the view. ### `const sourceId = await view.getMediaSourceId()` <a name="view-getmediasourceid"></a> Resolves to: `<String>` Supplies the `id` property of objects in the array returned from [ui.media.desktopSources](#ui-media-desktopsources). ### `await view.send(...args)` <a name="view-send"></a> Send arguments to the view. They will be serialized with `JSON.stringify`. ### `const found = await view.find(options <Object>)` <a name="view-find"></a> Resolves to: `<Found> extends <streamx.Readable>` Find and select text, emit matches as data events. **Options** * text `<String>` - search term * forward `<Boolean>` - search forward (`true`) or backward (`false`). Defaults `true`. * matchCase `<Boolean>` - case-sensitivity. Default `false`. #### `await found.proceed()` <a name="view-find-found-proceed"></a> Find & select next match, emit result as stream data. #### `await found.clear()` <a name="view-find-found-clear"></a> Stop search and clear matching text selection. Implies destroy. #### `await found.keep()` <a name="view-find-found-keep"></a> Stop search and convert matching text selection to text highlight. Implies destroy. #### `await found.activate()` <a name="view-find-found-activate"></a> Stop search and simulate a click event on the selected match. Implies destroy. ### `const dimensions = await view.dimensions([options <Object>])` <a name="view-dimensions"></a> When options object is not provided, behaves as a getter and resolves to a a bounds object. Resolves to: `{x <Integer>, y <Integer>, width <Integer>, height <Integer>} | null`. The height, width, horizontal (`x`), vertical (`y`) position of the window relative to the screen. All units are (pixels) If the parent window is closed this will resolve to `null`. When options object is provided, behaves as a setter and resolves to `undefined`. ```js const view = new ui.View('./some.html', { x: 10, y: 450, width: 300, height: 350 }) await view.open() await new Promise((resolve) => setTimeout(resolve, 1000)) await view.dimensions({ x: 20, y: 50, width: 550, height: 300 }) ``` Sets the dimensions of the view. **Options** * `x <Integer>` - the horizontal position of left side of the window (pixels) * `y <Integer>` - the vertical position of the top of the window (pixels) * `width <Integer>` - the width of the window (pixels) * `height <Integer>` - the height of the window (pixels) ```js const view = new ui.View('./some.html', { x: 10, y: 450, width: 300, height: 350 }) await view.open() await new Promise((resolve) => setTimeout(resolve, 1000)) await view.dimensions({ x: 20, y: 50, width: 550, height: 300 }) ``` Sets the dimensions of the view. **Options** * `x <Integer>` - the horizontal position of left side of the window (pixels) * `y <Integer>` - the vertical position of the top of the window (pixels) * `width <Integer>` - the width of the window (pixels) * `height <Integer>` - the height of the window (pixels) ### `const visible = await view.isVisible()` <a name="view-isvisible"></a> Resolves to: `<Boolean>` Whether the view is visible. ### `const closed = await view.isClosed()` <a name="view-isclosed"></a> Resolves to: `<Boolean>` Whether the view is closed. ### `const { self } = ui.Window` `const { self } = ui.View` <a name="deprecated-self"></a> > DEPRECATED use `ui.app`. ### `const { parent } = ui.Window` `const { parent } = ui.View` <a name="parent"></a> ### `parent.on[ce]('message', (...args) => { })` <a name="parent-receive-messages"></a> ### `for await (const [ ...args ] of parent)` Receive a message from the parent window or view. The received `args` array is deserialized via `JSON.parse`. ### `await parent.send(...args)` <a name="parent-send"></a> Send arguments to the parent view or window. They will be serialized with `JSON.stringify`. ### `const success = await parent.focus([options <Object>])` <a name="parent-focus"></a> Resolves to: `<Boolean>` Foreground parent view or window. **Options** * `steal` Default: `false` - focus input as well as foregrounding ### `const success = await parent.blur()` <a name="parent-blur"></a> Resolves to: `<Boolean>` Blur parent view or window. ### `const success = await parent.show()` <a name="parent-show"></a> Resolves to: `<Boolean>` Show parent view or window. ### `const success = await parent.hide()` <a name="parent-hide"></a> Resolves to: `<Boolean>` Hide parent view or window. ### `const sourceId = await parent.getMediaSourceId()` <a name="parent-getmediasourceid"></a> Get the sourceId of the parent window or view. ### `const success = await parent.minimize()` <a name="parent-minimize"></a> Resolves to: `<Boolean>` Minimize parent window. Throws a `TypeError` if `parent` is a view. ### `const success = await parent.maximize()` <a name="parent-maximize"></a> Resolves to: `<Boolean>` Maximize parent window. Throws a `TypeError` if `parent` is a view. ### `const success = await parent.restore()` <a name="parent-restore"></a> Resolves to: `<Boolean>` Unmaximize/unminimize the parent window if it is currently maximized/minimized. Throws a `TypeError` if `parent` is a view. ### `const success = await parent.close()` <a name="parent-close"></a> Resolves to: `<Boolean>` Closes the parent view or window. ### `const isVisible = await parent.isVisible()` <a name="parent-isvisible"></a> Resolves to: `<Boolean>` Whether the parent window or view is visible. ### `const isMaximized = await parent.isMaximized()` <a name="parent-ismaximized"></a> Resolves to: `<Boolean>` Whether the parent window is maximized. Throws a `TypeError` if `parent` is a view. ### `const isMinimized = await parent.isMinimized()` <a name="parent-isminimized"></a> Resolves to: `<Boolean>` Whether the parent window is minimized. Throws a `TypeError` if `parent` is a view. ### `const found = await parent.find(options <Object>)` <a name="parent-find"></a> Resolves to: `<Found> extends <streamx.Readable>` Find and select text, emit matches as data events. **Options** * text `<String>` - search term * forward `<Boolean>` - search forward (`true`) or backward (`false`). Defaults `true`. * matchCase `<Boolean>` - case-sensitivity. Default `false`. #### `await found.proceed()` <a name="parent-find-found-proceed"></a> Find & select next match, emit result as stream data. #### `await found.clear()` <a name="parent-find-found-clear"></a> Stop search and clear matching text selection. Implies destroy. #### `await found.keep()` <a name="parent-find-found-keep"></a> Stop search and convert matching text selection to text highlight. Implies destroy. #### `await found.activate()` <a name="parent-find-found-activate"></a> Stop search and simulate a click event on the selected match. Implies destroy. ## Graphical User Interface Options <a name="pear-gui"></a> GUI options for an application are set in the application `package.json` `pear.gui` field. Example `package.json`: ```json { "name": "my-app", "pear": { "gui": { "width": 800, "height": 600 } } } ``` ### `pear.gui.width <Number>` <a name="pear-gui-width"></a> Window width (pixels). ### `pear.gui.height <Number>` <a name="pear-gui-height"></a> Window height (pixels). ### `pear.gui.x <Number>` <a name="pear-gui-x"></a> Horizontal window position (pixels). ### `pear.gui.y <Number>` <a name="pear-gui-y"></a> Vertical window position (pixels). ### `pear.gui.minWidth <Number>` <a name="pear-gui-minwidth"></a> Window minimum width (pixels). ### `pear.gui.minHeight <Number>` <a name="pear-gui-minheight"></a> Window minimum height (pixels). ### `pear.gui.maxWidth <Number>` <a name="pear-gui-maxwidth"></a> Window maximum width (pixels). ### `pear.gui.maxHeight <Number>` <a name="pear-gui-maxheight"></a> Window maximum height (pixels). ### `pear.gui.center <Boolean>` (default: `false`) <a name="pear-gui-center"></a> Center window. ### `pear.gui.resizable <Boolean>` (default: `true`) <a name="pear-gui-resizable"></a> Window resizability. ### `pear.gui.movable <Boolean>` (default: `true`) <a name="pear-gui-movable"></a> Window movability. ### `pear.gui.minimizable <Boolean>` (default: `true`) <a name="pear-gui-minimizable"></a> Window minimizability. ### `pear.gui.maximizable <Boolean>` (default: `true`) <a name="pear-gui-maximizable"></a> Window maximizability. ### `pear.gui.closable <Boolean>` (default: `true`) <a name="pear-gui-closable"></a> Window closability. ### `pear.gui.focusable <Boolean>` (default: `true`) <a name="pear-gui-focusable"></a> Window focusability. #### `pear.gui.closeHides <Boolean>` (default: `false`) <a name="pear-gui-closehides"></a> Keep app running when all windows are closed. WARNING: Linux tray support varies which can cause scenarios where the application's tray doesn't work and closing the app will be hidden and inaccessible. Using a tray and `closeHides` on Linux is not recommended. ### `pear.gui.alwaysOnTop <Boolean>` (default: `false`) <a name="pear-gui-alwaysontop"></a> Set window to always be on top. ### `pear.gui.fullscreen <Boolean>` (default: `false`) <a name="pear-gui-fullscreen"></a> Set window to fullscreen on start. ### `pear.gui.kiosk <Boolean>` (default: `false`) <a name="pear-gui-kiosk"></a> Set window to enter kiosk mode on start. ### `pear.gui.autoHideMenuBar <Boolean>` (default: `false`) <a name="pear-gui-autohidemenubar"></a> Hide menu bar unless Alt key is pressed (Linux, Windows). ### `pear.gui.hasShadow <Boolean>` (default: `true`) <a name="pear-gui-hasshadow"></a> Window shadow. ### `pear.gui.opacity <Number>` (default: `1`) <a name="pear-gui-opacity"></a> Set window opacity (0.0 - 1.0) (Windows, macOS). ### `pear.gui.transparent <Boolean>` (default: `false`) <a name="pear-gui-transparent"></a> Enable transparency. Must be set for opacity to work. ### `pear.gui.backgroundColor <String>` (default: "#000" non-transparent, "#00000000" transparent) <a name="pear-gui-backgroundcolor"></a> Background color (Hex, RGB, RGBA, HSL, HSLA, CSS color). ### `pear.gui.userAgent <string>` <a name="pear-gui-useragent"></a> User Agent override to use when electron makes web requests. #### `pear.gui[platform] <Object>` <a name="pear-gui-platform"></a> Platform specific options can be set by nesting options under the platform name. For example the following sets the macOS version to not be resizable: ```json { "pear": { "gui": { "darwin": { "resizable": false } } } } ``` The following `platform`s are supported: - `darwin` - `linux` - `win32` ## Web APIs <a name="web-apis"></a> Most [Web APIs](https://developer.mozilla.org/en-US/docs/Web/API) will work as-is. This section details deviations in behavior from and notable aspects of Web APIs as they relate to `pear-electron`. ### `window.open` The [`window.open`](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) Web API function will ignore all arguments except for the URL parameter. In browsers, `window.open` opens a new browser window. The opened window belongs to the same browser from which `window.open` is called. With `pear-electron` UI Library, `window.open` loads the URL in the **default system browser**. It does *not* create a new application window (use `Pear.Window` to create application windows). Therefore Pear's `window.open` only supports a single URL argument. The `target` and `windowFeatures` parameters that browsers support are discarded. ### Scripts and Modules <a name="scripts-and-modules"></a> Like browsers, there is no support for CommonJS (e.g. the `require` function as used by Node.js is not supported in Pear Applications). Like browsers, there is support for native EcmaScript Modules (ESM). A JavaScript Script has no module capabilities. A JavaScript Module has ESM capabilities. Use `<script type="module" src="path/to/my-file.js">` to load a JavaScript Module. Use `<script src="path/to/my-file.js">` to load a JavaScript Script. ## Development <a name="development"></a> The `pear-electron` library is a Pear User Interface Runtime Library, providing multiple capabilities: * When loaded into a pear entrypoint JS file, `pear-electron` exports `runtime.js`, the runtime initializor. * When loaded into electron, `pear-electron` exports a UI library that is injected via `Pear[Pear.constructor.UI]` inside the runtime build that becomes the asset defined on `pear.assets.ui` configuration. * The `pear-electron/pre` script provides autoconfiguration, it sets `pear.assets.ui` on the application per `pear.assets.ui` in the `pear-electron/package.json`. The `pear-electron` repo is self-bootstrapping and generates the runtime drive with `by-arch`, `prebuilds` and `boot.bundle`, which can then be staged with Pear. ```sh npm run prestage ``` ```sh pear stage dev ``` Set the `package.json` `pear.assets.ui.link` to the versioned pear link (`pear://<fork>.<length>.<key>`) of the staged application. This means the `pear-electron/pre` of the next publish of `pear-electron` will autoconfigure the applications `pear.assets.ui` to the updated versioned pear link. This effectively locks runtime builds for a given SemVer to a specific runtime drive checkout. To check a change with an application, use `npm pack` to get `tar.gz` archive and then install that archive into an application: ```sh cd pear-electron npm pack cd ../some-pear-app npm i ../pear-electron/name-of-the-tar.gz ``` Then run the app with the `-d` (development) and `--pre-io` flag (to see any output from the `pear-electron/pre` script). ```sh pear run --pre-io -d . ``` # LICENSE <a name="license"></a> Apache 2.0