[
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "[//]: # \"Hey there and thank you for using Menubar's issue tracker!\"\n[//]: # \"Please fill in these information to describe your issue.\"\n\n### Description\n\n### Steps to Reproduce the Problem\n\n1. ...\n2. ...\n3. ...\n\n### Expected Behaviour\n\n### Actual Behaviour\n\n### Specifications\n\n- Menubar version:\n- Platform:\n- Electron version: (Run `electron -v` or `node_modules/.bin/electron -v` to get it)\n\n### Other information\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: npm\n  directory: \"/\"\n  schedule:\n    interval: weekly\n    time: \"02:00\"\n    timezone: Europe/Berlin\n  open-pull-requests-limit: 10\n"
  },
  {
    "path": ".github/workflows/lint.yml",
    "content": "name: Linting\n\non:\n    push:\n        branches:\n            - master\n    pull_request:\n\njobs:\n    lint:\n        name: Lint\n        runs-on: ubuntu-latest\n\n        steps:\n            - uses: actions/checkout@v4\n            - uses: actions/setup-node@v4\n              with:\n                  node-version-file: '.nvmrc'\n            - run: yarn install\n            - run: yarn lint\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Run Tests\n\non:\n    push:\n        branches:\n            - master\n    pull_request:\n\njobs:\n    lint:\n        name: Run Tests\n        runs-on: macos-latest\n\n        steps:\n            - uses: actions/checkout@v4\n            - uses: actions/setup-node@v4\n              with:\n                  node-version-file: '.nvmrc'\n            - run: yarn install\n            - run: yarn test\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\ncoverage\nlib\ndist\n*.app\n*.log\n"
  },
  {
    "path": ".nvmrc",
    "content": "20\n"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\"biomejs.biome\"]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"editor.codeActionsOnSave\": {\n    \"source.fixAll.eslint\": \"explicit\",\n    \"source.organizeImports.biome\": \"explicit\",\n    \"quickfix.biome\": \"explicit\"\n  },\n  \"editor.defaultFormatter\": \"biomejs.biome\"\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.\n\n### [9.5.2](https://github.com/maxogden/menubar/compare/v9.5.1...v9.5.2) (2025-10-10)\n\n### [9.5.1](https://github.com/maxogden/menubar/compare/v9.5.0...v9.5.1) (2024-10-11)\n\n## [9.5.0](https://github.com/maxogden/menubar/compare/v9.4.0...v9.5.0) (2024-06-25)\n\n\n### Features\n\n* widen electron support ([#473](https://github.com/maxogden/menubar/issues/473)) ([bd3beb2](https://github.com/maxogden/menubar/commit/bd3beb2c2bc9700f4738a4e0f25085aa8a0f5e86))\n\n\n### Bug Fixes\n\n* Fix for Broken Native Menubar Example ([#471](https://github.com/maxogden/menubar/issues/471)) ([b000c86](https://github.com/maxogden/menubar/commit/b000c86777cb0cf6fa883fb0256410981e154ce1))\n* win32 position ([#479](https://github.com/maxogden/menubar/issues/479)) ([9e5cb86](https://github.com/maxogden/menubar/commit/9e5cb86a276f29efd36d10a07e27fa820343f880))\n\n## [9.4.0](https://github.com/maxogden/menubar/compare/v9.3.0...v9.4.0) (2023-11-28)\n\n\n### Features\n\n* Update electron to 27 ([#458](https://github.com/maxogden/menubar/issues/458)) ([f3dbac6](https://github.com/maxogden/menubar/commit/f3dbac66582baa322c2c8caa5027f1b8ef480e67))\n\n\n### Bug Fixes\n\n* Avoid setVisibleOnAllWorkspaces from destroying the original visible state of app.dock ([#442](https://github.com/maxogden/menubar/issues/442)) ([d8df2ab](https://github.com/maxogden/menubar/commit/d8df2ab4b65564c8ec58dc7156128bfd53fab2c9))\n\n## [9.3.0](https://github.com/maxogden/menubar/compare/v9.2.3...v9.3.0) (2023-02-13)\n\n\n### Features\n\n* add electron 22 support ([#414](https://github.com/maxogden/menubar/issues/414)) ([a39382f](https://github.com/maxogden/menubar/commit/a39382fe843953395bf99267ee83102def70b06e))\n\n### [9.2.3](https://github.com/maxogden/menubar/compare/v9.2.2...v9.2.3) (2022-10-05)\n\n\n### Features\n\n* electron 21 support ([#382](https://github.com/maxogden/menubar/issues/382)) ([c9d5b61](https://github.com/maxogden/menubar/commit/c9d5b61da2b55e20e9b2d0f4c0181c57f33a27c3))\n\n### [9.2.2](https://github.com/maxogden/menubar/compare/v9.2.1...v9.2.2) (2022-09-05)\n\n\n### Features\n\n* Add Electron 20 as a peerDependency ([#379](https://github.com/maxogden/menubar/issues/379)) ([4c027b2](https://github.com/maxogden/menubar/commit/4c027b22499c7c83a4d87b9aa17d5e86f3172b68))\n\n\n### Bug Fixes\n\n* arrow example problem ([#342](https://github.com/maxogden/menubar/issues/342)) ([64b80d5](https://github.com/maxogden/menubar/commit/64b80d5f49ebb367b75e21e88af15fdc874cda86))\n\n### [9.2.1](https://github.com/maxogden/menubar/compare/v9.2.0...v9.2.1) (2022-07-11)\n\n\n### Bug Fixes\n\n* Add support for electron 19 ([#376](https://github.com/maxogden/menubar/issues/376)) ([6d0feb0](https://github.com/maxogden/menubar/commit/6d0feb0e492681200966dde10a63a73cfb503138))\n\n## [9.2.0](https://github.com/maxogden/menubar/compare/v9.1.2...v9.2.0) (2022-04-11)\n\n\n### Features\n\n* add `before-load` event ([#370](https://github.com/maxogden/menubar/issues/370)) ([3247986](https://github.com/maxogden/menubar/commit/3247986f164d8b2fb2912ab33beb25c9c6d8ece3))\n\n### [9.1.2](https://github.com/maxogden/menubar/compare/v9.1.1...v9.1.2) (2022-03-29)\n\n\n### Bug Fixes\n\n* Add electron 17 support ([#373](https://github.com/maxogden/menubar/issues/373)) ([fafc29f](https://github.com/maxogden/menubar/commit/fafc29f168e91369ad5d60a61abc0363076c303a))\n\n### [9.1.1](https://github.com/maxogden/menubar/compare/v9.1.0...v9.1.1) (2021-12-09)\n\n\n### Bug Fixes\n\n* Add electron 16 support ([#364](https://github.com/maxogden/menubar/issues/364)) ([325e151](https://github.com/maxogden/menubar/commit/325e1517cfc407bc0ccc98be776d8d9590d6f119))\n\n## [9.1.0](https://github.com/maxogden/menubar/compare/v9.0.6...v9.1.0) (2021-10-27)\n\n\n### Features\n\n* add option activateWithApp to allow not activate with this event ([#361](https://github.com/maxogden/menubar/issues/361)) ([8384bf2](https://github.com/maxogden/menubar/commit/8384bf24abe6138aded26fcd7bd6d1d7a325f319))\n\n### [9.0.6](https://github.com/maxogden/menubar/compare/v9.0.5...v9.0.6) (2021-10-15)\n\n\n### Bug Fixes\n\n* Add support for electron 14 and 15 ([#358](https://github.com/maxogden/menubar/issues/358)) ([8eaba8c](https://github.com/maxogden/menubar/commit/8eaba8cdfcd3ce9427ee3ffd65b3426c62f65048))\n\n### [9.0.5](https://github.com/maxogden/menubar/compare/v9.0.4...v9.0.5) (2021-06-28)\n\n\n### Bug Fixes\n\n* Add support for Electron 13 ([#347](https://github.com/maxogden/menubar/issues/347)) ([fbf07bd](https://github.com/maxogden/menubar/commit/fbf07bd0bd24b2aac26cdd1db61eb55924f3ee63))\n* window position on linux & windows when taskbar is on the left ([#343](https://github.com/maxogden/menubar/issues/343)) ([5d8e0c8](https://github.com/maxogden/menubar/commit/5d8e0c89996f67b58f059ec767a87db104a90292))\n\n### [9.0.4](https://github.com/maxogden/menubar/compare/v9.0.3...v9.0.4) (2021-05-03)\n\n\n### Bug Fixes\n\n* Add support for Electron 12 ([#332](https://github.com/maxogden/menubar/issues/332)) ([c1f055d](https://github.com/maxogden/menubar/commit/c1f055daed76be2d0f408fda5d4835defcd59dcc))\n\n### [9.0.3](https://github.com/maxogden/menubar/compare/v9.0.2...v9.0.3) (2021-02-24)\n\n\n### Bug Fixes\n\n* Add support for Electron 10 and 11 ([#321](https://github.com/maxogden/menubar/issues/321)) ([4a89656](https://github.com/maxogden/menubar/commit/4a8965628a0a1a7a14602fef3add7bef436a508f))\n\n### [9.0.2](https://github.com/maxogden/menubar/compare/v9.0.1...v9.0.2) (2021-01-20)\n\n\n### Bug Fixes\n\n* Improve 'windows' OS detection of taskbar location ([#307](https://github.com/maxogden/menubar/issues/307)) ([4726584](https://github.com/maxogden/menubar/commit/4726584664148a57656c40872836ebba2d030980))\n\n### [9.0.1](https://github.com/maxogden/menubar/compare/v9.0.0...v9.0.1) (2020-05-28)\n\n\n### Bug Fixes\n\n* calling showWindow() prevents menubar window from closing ([#287](https://github.com/maxogden/menubar/issues/287)) ([53d8f82](https://github.com/maxogden/menubar/commit/53d8f82b604ad5555f59108a97234ebf32e43f80))\n\n## [9.0.0](https://github.com/maxogden/menubar/compare/v8.0.2...v9.0.0) (2020-05-27)\n\n\n### ⚠ BREAKING CHANGES\n\n* Please use Electron 9 with this menubar version.\n\n### Features\n\n* Support Electron 9 ([#286](https://github.com/maxogden/menubar/issues/286)) ([44cf1b1](https://github.com/maxogden/menubar/commit/44cf1b1e6cce83f9e63a39f1d32fbb664396e7bc))\n\n### [8.0.2](https://github.com/maxogden/menubar/compare/v8.0.1...v8.0.2) (2020-04-27)\n\n\n### Bug Fixes\n\n* Show window on dock icon click ([#279](https://github.com/maxogden/menubar/issues/279)) ([a8607fa](https://github.com/maxogden/menubar/commit/a8607fa708d229d9124471127482fe461198f1f3))\n* update prevent flicker on Windows (fixes [#274](https://github.com/maxogden/menubar/issues/274)) ([#276](https://github.com/maxogden/menubar/issues/276)) ([9592f34](https://github.com/maxogden/menubar/commit/9592f3437ce3660b6464f5b436ed111291eb75d3))\n\n### [8.0.1](https://github.com/maxogden/menubar/compare/v8.0.0...v8.0.1) (2020-03-14)\n\n\n### Bug Fixes\n\n* **deps:** [Security] bump acorn from 6.1.1 to 6.4.1 ([#272](https://github.com/maxogden/menubar/issues/272)) ([1332b77](https://github.com/maxogden/menubar/commit/1332b774372de69c04e2a098833ae35775c35cad))\n\n## [8.0.0](https://github.com/maxogden/menubar/compare/v7.2.0...v8.0.0) (2020-02-10)\n\n\n### ⚠ BREAKING CHANGES\n\n* Menubar's recommended peer dependency is `electron@^8.0.0`\n\n### Features\n\n* Support Electron 8 ([#268](https://github.com/maxogden/menubar/issues/268)) ([ad99c5a](https://github.com/maxogden/menubar/commit/ad99c5add02ab6d0d751cf6bda8a2c96c674620f))\n\n## [7.2.0](https://github.com/maxogden/menubar/compare/v7.1.0...v7.2.0) (2020-01-16)\n\n\n### Features\n\n* Adding a loadUrlOptions option ([#263](https://github.com/maxogden/menubar/issues/263)) ([8e6bd01](https://github.com/maxogden/menubar/commit/8e6bd0154aaee02a5d601bbe37c51c55065c3923))\n\n## [7.1.0](https://github.com/maxogden/menubar/compare/v7.0.0...v7.1.0) (2019-11-25)\n\n\n### Features\n\n* Allow skipping loadUrl ([#257](https://github.com/maxogden/menubar/issues/257)) ([095486a](https://github.com/maxogden/menubar/commit/095486ab338df26fc4d6a1e7a658cfa9fa4a69b7))\n\n# [7.0.0](https://github.com/maxogden/menubar/compare/v6.0.8...v7.0.0) (2019-10-23)\n\n\n* feat!: Support Electron 7 (#250) ([b54dce5](https://github.com/maxogden/menubar/commit/b54dce5)), closes [#250](https://github.com/maxogden/menubar/issues/250)\n\n\n### BREAKING CHANGES\n\n* - Drop support for Electron 4, 5, and 6.\n- Remove deprecated passing string argument to `menubar`, use `dir` field instead\n```diff\n- menubar('/home/me/MY_ABSOLUTE_PATH');\n+ menubar({ dir: '/home/me/MY_ABSOLUTE_PATH' });\n```\n- Remove deprecated passing `x`, `y`, `height`, `width`, `alwaysOnTop` fields to `menubar`, pass them instead into the `browserWindow` field\n```diff\n- menubar({\n-   x: 12,\n-   y: 34,\n-   height: 500,\n-   width: 320,\n-   alwaysOnTop: true\n- });\n+ menubar({\n+   browserWindow: {\n+     x: 12,\n+     y: 34,\n+     height: 500,\n+     width: 320,\n+     alwaysOnTop: true\n+  }\n+ });\n```\n\n\n\n## [6.0.8](https://github.com/maxogden/menubar/compare/v6.0.7...v6.0.8) (2019-09-16)\n\n\n### Bug Fixes\n\n* Move doc tool to `devDependencies` ([#245](https://github.com/maxogden/menubar/issues/245)) ([2756c7a](https://github.com/maxogden/menubar/commit/2756c7a))\n\n\n\n## [6.0.7](https://github.com/maxogden/menubar/compare/v6.0.6...v6.0.7) (2019-07-31)\n\n\n### Bug Fixes\n\n* Support Electron 6 ([#242](https://github.com/maxogden/menubar/issues/242)) ([1fd9bd7](https://github.com/maxogden/menubar/commit/1fd9bd7))\n\n\n\n## [6.0.6](https://github.com/maxogden/menubar/compare/v6.0.5...v6.0.6) (2019-07-02)\n\n\n### Bug Fixes\n\n* Fix crash on windows position ([#235](https://github.com/maxogden/menubar/issues/235)) ([cbbe175](https://github.com/maxogden/menubar/commit/cbbe175))\n\n\n\n## [6.0.5](https://github.com/maxogden/menubar/compare/v6.0.4...v6.0.5) (2019-06-11)\n\n\n### Bug Fixes\n\n* Remove postinstall, export taskbarLocation ([#226](https://github.com/maxogden/menubar/issues/226)) ([941b3be](https://github.com/maxogden/menubar/commit/941b3be))\n\n\n\n## [6.0.4](https://github.com/maxogden/menubar/compare/v6.0.3...v6.0.4) (2019-06-11)\n\n\n### Bug Fixes\n\n* Correct position on Windows & multi-taskbar ([#217](https://github.com/maxogden/menubar/issues/217)) ([4f29fe2](https://github.com/maxogden/menubar/commit/4f29fe2)), closes [#196](https://github.com/maxogden/menubar/issues/196)\n* Fix double 'after-hide' event ([#216](https://github.com/maxogden/menubar/issues/216)) ([a4d900e](https://github.com/maxogden/menubar/commit/a4d900e))\n\n\n\n## [6.0.3](https://github.com/maxogden/menubar/compare/v6.0.2...v6.0.3) (2019-06-05)\n\n\n### Bug Fixes\n\n* Fix accessing Menubar.window ([#214](https://github.com/maxogden/menubar/issues/214)) ([cd5ef73](https://github.com/maxogden/menubar/commit/cd5ef73))\n\n\n\n## [6.0.2](https://github.com/maxogden/menubar/compare/v6.0.1...v6.0.2) (2019-05-31)\n\n\n### Bug Fixes\n\n* Use cat icon if no icon provided ([#205](https://github.com/maxogden/menubar/issues/205)) ([fc02e02](https://github.com/maxogden/menubar/commit/fc02e02))\n\n\n\n## [6.0.1](https://github.com/maxogden/menubar/compare/v6.0.0...v6.0.1) (2019-05-31)\n\n\n### Bug Fixes\n\n* Fix changelog links ([#204](https://github.com/maxogden/menubar/issues/204)) ([de96756](https://github.com/maxogden/menubar/commit/de96756))\n\n\n\n# [6.0.0](https://github.com/maxogden/menubar/compare/v5.2.3...v6.0.0) (2019-05-31)\n\n\n### Bug Fixes\n\n* Update to Electron 5 ([#15](https://github.com/amaurym/g/menubar/issues/15)) ([ce86216](https://github.com/maxogden/menubar/commit/ce86216))\n* Window does not show when already app is ready ([#8](https://github.com/amaurym/g/menubar/issues/8)) ([251fb21](https://github.com/maxogden/menubar/commit/251fb21))\n\n\n### Code Refactoring\n\n* Convert all codebase to typescript ([#2](https://github.com/amaurym/g/menubar/issues/2)) ([820d41a](https://github.com/maxogden/menubar/commit/820d41a))\n\n\n### Features\n\n* Add `browserWindow` field in options, deprecate `height`, `width`, `x`, `y`, `alwaysOnTop` in favor of `browserWindow` ([#18](https://github.com/amaurym/g/menubar/issues/18)) ([0b2d897](https://github.com/maxogden/menubar/commit/0b2d897))\n* Support Electron.NativeImage icon argument ([#7](https://github.com/amaurym/g/menubar/issues/7)) ([03d67f3](https://github.com/maxogden/menubar/commit/03d67f3))\n\n\n### BREAKING CHANGES\n\n* We're using a named export in Typescript now:\n```diff\n- var menubar = require('menubar');\n+ var { menubar } = require('menubar');\n```\n\nAlternatively, using ES6/TS syntax:\n```javascript\nimport { menubar } from 'menubar';\n```\n"
  },
  {
    "path": "COLLABORATORS.md",
    "content": "## Collaborators\n\nmenubar is only possible due to the excellent work of the following collaborators:\n\n<table>\n<tbody>\n<tr><th align=\"left\">maxogden</th><td><a href=\"https://github.com/maxogden\">GitHub/maxogden</a></td></tr>\n<tr><th align=\"left\">fritzy</th><td><a href=\"https://github.com/fritzy\">GitHub/fritzy</a></td></tr>\n<tr><th align=\"left\">pquerna</th><td><a href=\"https://github.com/pquerna\">GitHub/pquerna</a></td></tr>\n<tr><th align=\"left\">fabien-d</th><td><a href=\"https://github.com/fabien-d\">GitHub/fabien-d</a></td></tr>\n<tr><th align=\"left\">jenslind</th><td><a href=\"https://github.com/jenslind\">GitHub/jenslind</a></td></tr>\n<tr><th align=\"left\">amaurym</th><td><a href=\"https://github.com/amaurym\">GitHub/amaurym</a></td></tr>\n</tbody>\n</table>\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Before opening issues\n\n**If you are asking a question**:\n\nRemember that `menubar` is just a lightweight wrapper around Electron. Most of the time you can probably find the answer to your question already answered in the [Electron Issue Tracker](https://github.com/electron/electron/issues)\n\n**For bug reports/technical issues**:\n\nPlease provide the following information when opening issues:\n\n- Which version of menubar are you using?\n- What cli arguments are you passing?\n- What platform are you running menubar on?\n- Is there a stack trace in the error message you're seeing?\n- If possible, please provide instructions to reproduce your problem.\n\nThanks!\n\n## Releases\n\n- commit your changes\n- `npm version <major|minor|patch>`\n- `git push && git push --tags` (or `git push` with `git config --global push.followTags true` on latest git)\n- `npm publish`\n"
  },
  {
    "path": "LICENSE",
    "content": "BSD 2-Clause License\n\nCopyright (c) 2015-2019, Max Ogden\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/max-mapper/menubar/test.yml)\n[![npm (scoped)](https://img.shields.io/npm/v/menubar.svg)](https://www.npmjs.com/package/menubar)\n![Libraries.io dependency status for GitHub repo](https://img.shields.io/librariesio/github/max-mapper/menubar)\n![npm bundle size](https://img.shields.io/bundlephobia/minzip/menubar.svg)\n![npm bundle size](https://img.shields.io/bundlephobia/min/menubar.svg)\n\n<br /><br /><br />\n\n<h1 align=\"center\">➖ Menubar</h1>\n<h4 align=\"center\">High level way to create menubar desktop applications with Electron.</h4>\n\n<br /><br /><br />\n\nThis module provides boilerplate for setting up a menubar application using Electron. All you have to do is point it at your `index.html` and `menubar` will handle the rest.\n\n✅ Only one dependency, and one peer-dependency.\n\n✅ Works on macOS, Windows and most Linuxes. See [details](./WORKING_PLATFORMS.md).\n\n✅ 💥 [**3.6kB minified + gzipped**](https://bundlephobia.com/result?p=menubar) 💥\n\n| <img src=\"assets/screenshot-macos-dark.png\" height=\"250px\" /> | <img src=\"assets/screenshot-windows.png\" height=\"250px\" /> | <img src=\"assets/screenshot-linux.png\" height=\"250px\" /> |\n| :-----------------------------------------------------------: | :--------------------------------------------------------: | :------------------------------------------------------: |\n|                      macOS Mojave 10.14                       |                         Windows 10                         |                       Ubuntu 18.04                       |\n\n## Installation\n\n```bash\nyarn add menubar\n```\n\n## Usage\n\nStarting with your own new project, run these commands:\n\n```bash\n$ yarn add menubar\n$ touch myApp.js\n$ touch index.html\n```\n\nFill `index.html` with some HTML, and `myApp.js` like this:\n\n```javascript\nconst { menubar } = require('menubar');\n\nconst mb = menubar();\n\nmb.on('ready', () => {\n  console.log('app is ready');\n  // your app code here\n});\n```\n\nThen use `electron` to run the app:\n\n```bash\n$ electron myApp.js\n```\n\nAlternatively, see [`examples/hello-world`](/examples/hello-world) folder for a simple working example.\n\n## `Menubar` Class\n\nThe return value of `menubar()` is a `Menubar` class instance, which has these properties:\n\n- `app`: the [Electron App](https://electronjs.org/docs/api/app) instance,\n- `window`: the [Electron Browser Window](https://electronjs.org/docs/api/browser-window) instance,\n- `tray`: the [Electron Tray](https://electronjs.org/docs/api/tray) instance,\n- `positioner`: the [Electron Positioner](https://github.com/jenslind/electron-positioner) instance,\n- `setOption(option, value)`: change an option after menubar is created,\n- `getOption(option)`: get an menubar option,\n- `showWindow()`: show the menubar window,\n- `hideWindow()`: hide the menubar window\n\nSee the reference [API docs](./docs/classes/_menubar_.menubar.md).\n\n## `menubar()` Options\n\nYou can pass an optional options object into the `menubar({ ... })` function:\n\n- `dir` (default `process.cwd()`) - the app source directory\n- `index` (default `file:// + opts.dir + index.html`) - The URL to load the menubar's browserWindow with. The url can be a remote address (e.g. `http://`) or a path to a local HTML file using the `file://` protocol.\n- `browserWindow` - BrowserWindow options to be passed to the BrowserWindow constructor, see [Electron docs](https://electronjs.org/docs/api/browser-window#new-browserwindowoptions). Some interesting fields to passed down are:\n  - `x` (default `undefined`) - the x position of the window\n  - `y` (default `undefined`) - the y position of the window\n  - `width` (default 400) - window width\n  - `height` (default 400) - window height\n  - `alwaysOnTop` (default false) - if true, the window will not hide on blur\n- `icon` (default `opts.dir + IconTemplate.png`) - the png icon to use for the menubar. A good size to start with is 20x20. To support retina, supply a 2x sized image (e.g. 40x40) with `@2x` added to the end of the name, so `icon.png` and `icon@2x.png` and Electron will automatically use your `@2x` version on retina screens.\n- `tooltip` (default empty) - menubar tray icon tooltip text\n- `tray` (default created on-the-fly) - an electron `Tray` instance. if provided `opts.icon` will be ignored\n- `preloadWindow` (default false) - Create [BrowserWindow](https://electronjs.org/docs/api/browser-window#new-browserwindowoptions) instance before it is used -- increasing resource usage, but making the click on the menubar load faster.\n- `loadUrlOptions` - (default undefined) The options passed when loading the index URL in the menubar's browserWindow. Everything browserWindow.loadURL supports is supported; this object is simply passed onto [browserWindow.loadURL](https://electronjs.org/docs/api/browser-window#winloadurlurl-options)\n- `showOnAllWorkspaces` (default true) - Makes the window available on all OS X workspaces.\n- `windowPosition` (default trayCenter and trayBottomCenter on Windows) - Sets the window position (x and y will still override this), check [positioner docs](https://github.com/jenslind/electron-positioner#docs) for valid values.\n- `showDockIcon` (default false) - Configure the visibility of the application dock icon.\n- `showOnRightClick` (default false) - Show the window on 'right-click' event instead of regular 'click'\n\nSee the reference [API docs](./docs/interfaces/_types_.options.md).\n\n## Events\n\nThe `Menubar` class is an event emitter:\n\n- `ready` - when `menubar`'s tray icon has been created and initialized, i.e. when `menubar` is ready to be used. Note: this is different than Electron app's `ready` event, which happens much earlier in the process\n- `create-window` - the line before `new BrowserWindow()` is called\n- `before-load` - after create window, before loadUrl (can be used for `require(\"@electron/remote/main\").enable(webContents)`)\n- `after-create-window` - the line after all window init code is done and url was loaded\n- `show` - the line before `window.show()` is called\n- `after-show` - the line after `window.show()` is called\n- `hide` - the line before `window.hide()` is called (on window blur)\n- `after-hide` - the line after `window.hide()` is called\n- `after-close` - after the `.window` (BrowserWindow) property has been deleted\n- `focus-lost` - emitted if always-on-top option is set and the user clicks away\n\n## Compatibility with Electron\n\n| menubar  | Electron                   | Notes                                                                                                                      |\n| -------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------- |\n| 9.x.x    | >= 9.x.x <= 34.x.x |                                                                                                                            |\n| 8.x.x    | 8.x.xx                      |                                                                                                                            |\n| 7.x.x    | 7.x.xx                      |                                                                                                                            |\n| 6.x.x    | >= 4.x.x < 7.x.x   | Not recommended for [security reasons](https://electronjs.org/docs/tutorial/security#17-use-a-current-version-of-electron) |\n| <= 5.x.x | <= 3.x.x                   | Please, _please_ don't use these old versions                                                                              |\n\n## API Docs\n\nSee the reference [API docs](./docs/globals.md).\n\n## Tips\n\n- Use `mb.on('after-create-window', callback)` to run things after your app has loaded. For example you could run `mb.window.openDevTools()` to open the developer tools for debugging, or load a different URL with `mb.window.loadURL()`\n- Use `mb.on('focus-lost')` if you would like to perform some operation when using the option `browserWindow.alwaysOnTop: true`\n- To restore focus of previous window after menubar hide, use `mb.on('after-hide', () => { mb.app.hide() } )` or similar\n- To create a native menu, you can use `tray.setContextMenu(contextMenu)`, and pass this custom tray to menubar: `const mb = menubar({ tray });`. See [this example](https://github.com/maxogden/menubar/tree/master/examples/native-menu) for more information.\n- To avoid a flash when opening your menubar app, you can disable backgrounding the app using the following: `mb.app.commandLine.appendSwitch('disable-backgrounding-occluded-windows', 'true');`\n"
  },
  {
    "path": "WORKING_PLATFORMS.md",
    "content": "# Platforms where `menubar` is known to work\n\nThis document is still a work-in-progress. If you have tested `menubar` with a platform that is not listed under here, I would greatly appreciate a PR!\n\n## macOS\n\n| Version           | Working Status | Known Issues                                                                                                   |\n| ----------------- | -------------- | -------------------------------------------------------------------------------------------------------------- |\n| 14.15 Sonoma      | ✅ Good        |                                                                                                                |\n| 10.14 Mojave      | ✅ Good        | [#147](https://github.com/maxogden/menubar/issues/147), [#215](https://github.com/maxogden/menubar/issues/215) |\n| 10.13 High Sierra | ✅ Good        |                                                                                                                |\n\n## Windows\n\n| Version    | Working Status | Known Issues |\n| ---------- | -------------- | ------------ |\n| Windows 11 | ✅ Good        |              |\n| Windows 10 | ✅ Good        |              |\n| Windows 8  | ✅ Good        |              |\n\n## Linux\n\n| Distribution  | Desktop Environment | Working Status | Known Issues                                           |\n| ------------- | ------------------- | -------------- | ------------------------------------------------------ |\n| openSUSE 13.1 | Xfce 4.10.1         | ❌ Bad         | [#123](https://github.com/maxogden/menubar/issues/123) |\n| Ubuntu 18.04  | Unity               | ✅ Good        |                                                        |\n| Ubuntu 14.04  | Unity               | ❌ Bad         | [#68](https://github.com/maxogden/menubar/issues/68)   |\n"
  },
  {
    "path": "biome.json",
    "content": "{\n  \"$schema\": \"https://biomejs.dev/schemas/1.9.3/schema.json\",\n  \"organizeImports\": {\n    \"enabled\": true\n  },\n  \"linter\": {\n    \"enabled\": true,\n    \"rules\": {\n      \"recommended\": true,\n      \"style\": {\n        \"noParameterAssign\": \"warn\",\n        \"noNonNullAssertion\": \"warn\",\n        \"useNodejsImportProtocol\": \"warn\"\n      },\n      \"suspicious\": {\n        \"noAssignInExpressions\": \"warn\"\n      }\n    }\n  },\n  \"vcs\": {\n    \"enabled\": true,\n    \"clientKind\": \"git\",\n    \"useIgnoreFile\": true\n  },\n  \"formatter\": {\n    \"enabled\": true,\n    \"indentStyle\": \"space\",\n    \"indentWidth\": 2\n  },\n  \"javascript\": {\n    \"formatter\": {\n      \"quoteStyle\": \"single\",\n      \"jsxQuoteStyle\": \"double\"\n    }\n  },\n  \"json\": {\n    \"parser\": {\n      \"allowComments\": true\n    }\n  }\n}\n"
  },
  {
    "path": "docs/README.md",
    "content": "> **[menubar](README.md)**\n\n[Globals](globals.md) /\n\n[![Build Status](https://travis-ci.org/maxogden/menubar.svg?branch=master)](https://travis-ci.org/maxogden/menubar)\n[![npm (scoped)](https://img.shields.io/npm/v/menubar.svg)](https://www.npmjs.com/package/@maxogden/menubar)\n[![dependencies Status](https://david-dm.org/maxogden/menubar/status.svg)](https://david-dm.org/maxogden/menubar)\n![npm bundle size](https://img.shields.io/bundlephobia/minzip/menubar.svg)\n![npm bundle size](https://img.shields.io/bundlephobia/min/menubar.svg)\n\n<br /><br /><br />\n\n<h1 align=\"center\">➖ Menubar</h1>\n<h4 align=\"center\">High level way to create menubar desktop applications with Electron.</h4>\n\n<br /><br /><br />\n\nThis module provides boilerplate for setting up a menubar application using Electron. All you have to do is point it at your `index.html` and `menubar` will handle the rest.\n\n✅ Only one dependency, and one peer-dependency.\n\n✅ Works on macOS, Windows and most Linuxes. See [details](./WORKING_PLATFORMS.md).\n\n✅ 💥 [**3.6kB minified + gzipped**](https://bundlephobia.com/result?p=menubar) 💥\n\n| <img src=\"assets/screenshot-macos-dark.png\" height=\"250px\" /> | <img src=\"assets/screenshot-windows.png\" height=\"250px\" /> | <img src=\"assets/screenshot-linux.png\" height=\"250px\" /> |\n| :-----------------------------------------------------------: | :--------------------------------------------------------: | :------------------------------------------------------: |\n|                      macOS Mojave 10.14                       |                         Windows 10                         |                       Ubuntu 18.04                       |\n\n## Installation\n\n```bash\nyarn add menubar\n```\n\n## Usage\n\nStarting with your own new project, run these commands:\n\n```bash\n$ yarn add menubar\n$ touch myApp.js\n$ touch index.html\n```\n\nFill `index.html` with some HTML, and `myApp.js` like this:\n\n```javascript\nconst { menubar } = require('menubar');\n\nconst mb = menubar();\n\nmb.on('ready', () => {\n  console.log('app is ready');\n  // your app code here\n});\n```\n\nThen use `electron` to run the app:\n\n```bash\n$ electron myApp.js\n```\n\nAlternatively, see [`examples/hello-world`](/examples/hello-world) folder for a simple working example.\n\n## `Menubar` Class\n\nThe return value of `menubar()` is a `Menubar` class instance, which has these properties:\n\n- `app`: the [Electron App](https://electronjs.org/docs/api/app) instance,\n- `window`: the [Electron Browser Window](https://electronjs.org/docs/api/browser-window) instance,\n- `tray`: the [Electron Tray](https://electronjs.org/docs/api/tray) instance,\n- `positioner`: the [Electron Positioner](https://github.com/jenslind/electron-positioner) instance,\n- `setOption(option, value)`: change an option after menubar is created,\n- `getOption(option)`: get an menubar option,\n- `showWindow()`: show the menubar window,\n- `hideWindow()`: hide the menubar window\n\nSee the reference [API docs](./docs/classes/_menubar_.menubar.md).\n\n## `menubar()` Options\n\nYou can pass an optional options object into the `menubar({ ... })` function:\n\n- `dir` (default `process.cwd()`) - the app source directory\n- `index` (default `file:// + opts.dir + index.html`) - The URL to load the menubar's browserWindow with. The url can be a remote address (e.g. `http://`) or a path to a local HTML file using the `file://` protocol.\n- `browserWindow` - BrowserWindow options to be passed to the BrowserWindow constructor, see [Electron docs](https://electronjs.org/docs/api/browser-window#new-browserwindowoptions). Some interesting fields to passed down are:\n  - `x` (default `undefined`) - the x position of the window\n  - `y` (default `undefined`) - the y position of the window\n  - `width` (default 400) - window width\n  - `height` (default 400) - window height\n  - `alwaysOnTop` (default false) - if true, the window will not hide on blur\n- `icon` (default `opts.dir + IconTemplate.png`) - the png icon to use for the menubar. A good size to start with is 20x20. To support retina, supply a 2x sized image (e.g. 40x40) with `@2x` added to the end of the name, so `icon.png` and `icon@2x.png` and Electron will automatically use your `@2x` version on retina screens.\n- `tooltip` (default empty) - menubar tray icon tooltip text\n- `tray` (default created on-the-fly) - an electron `Tray` instance. if provided `opts.icon` will be ignored\n- `preloadWindow` (default false) - Create [BrowserWindow](https://electronjs.org/docs/api/browser-window#new-browserwindowoptions) instance before it is used -- increasing resource usage, but making the click on the menubar load faster.\n- `showOnAllWorkspaces` (default true) - Makes the window available on all OS X workspaces.\n- `windowPosition` (default trayCenter and trayBottomCenter on Windows) - Sets the window position (x and y will still override this), check [positioner docs](https://github.com/jenslind/electron-positioner#docs) for valid values.\n- `showDockIcon` (default false) - Configure the visibility of the application dock icon.\n- `showOnRightClick` (default false) - Show the window on 'right-click' event instead of regular 'click'\n\nSee the reference [API docs](./docs/interfaces/_types_.options.md).\n\n## Events\n\nThe `Menubar` class is an event emitter:\n\n- `ready` - when `menubar`'s tray icon has been created and initialized, i.e. when `menubar` is ready to be used. Note: this is different than Electron app's `ready` event, which happens much earlier in the process\n- `create-window` - the line before `new BrowserWindow()` is called\n- `after-create-window` - the line after all window init code is done\n- `show` - the line before `window.show()` is called\n- `after-show` - the line after `window.show()` is called\n- `hide` - the line before `window.hide()` is called (on window blur)\n- `after-hide` - the line after `window.hide()` is called\n- `after-close` - after the `.window` (BrowserWindow) property has been deleted\n- `focus-lost` - emitted if always-on-top option is set and the user clicks away\n\n## Compatibility with Electron\n\n| menubar  | Electron                | Notes                                                                                                                      |\n| -------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------- |\n| 7.x.x    | 7.x.x                   |\n| 6.x.x    | 4.x.x \\| 5.x.x \\| 6.x.x | Not recommended for [security reasons](https://electronjs.org/docs/tutorial/security#17-use-a-current-version-of-electron) |\n| <= 5.x.x | <= 3.x.x                | Please, _please_ don't use these old versions                                                                              |\n\n## API Docs\n\nSee the reference [API docs](./docs/globals.md).\n\n## Tips\n\n- Use `mb.on('after-create-window', callback)` to run things after your app has loaded. For example you could run `mb.window.openDevTools()` to open the developer tools for debugging, or load a different URL with `mb.window.loadUrl()`\n- Use `mb.on('focus-lost')` if you would like to perform some operation when using the option `browserWindow.alwaysOnTop: true`\n- To restore focus of previous window after menubar hide, use `mb.on('after-hide', () => { mb.app.hide() } )` or similar\n- To create a native menu, you can use `tray.setContextMenu(contextMenu)`, and pass this custom tray to menubar: `const mb = menubar({ tray });`. See [this example](https://github.com/maxogden/menubar/tree/master/examples/native-menu) for more information.\n- To avoid a flash when opening your menubar app, you can disable backgrounding the app using the following: `mb.app.commandLine.appendSwitch('disable-backgrounding-occluded-windows', 'true');`"
  },
  {
    "path": "docs/classes/_menubar_.menubar.md",
    "content": "> **[menubar](../README.md)**\n\n[Globals](../globals.md) / [\"Menubar\"](../modules/_menubar_.md) / [Menubar](_menubar_.menubar.md) /\n\n# Class: Menubar\n\n## Hierarchy\n\n* `EventEmitter`\n\n  * **Menubar**\n\n## Index\n\n### Constructors\n\n* [constructor](_menubar_.menubar.md#constructor)\n\n### Accessors\n\n* [app](_menubar_.menubar.md#app)\n* [positioner](_menubar_.menubar.md#positioner)\n* [tray](_menubar_.menubar.md#tray)\n* [window](_menubar_.menubar.md#window)\n\n### Methods\n\n* [getOption](_menubar_.menubar.md#getoption)\n* [hideWindow](_menubar_.menubar.md#hidewindow)\n* [setOption](_menubar_.menubar.md#setoption)\n* [showWindow](_menubar_.menubar.md#showwindow)\n\n## Constructors\n\n###  constructor\n\n\\+ **new Menubar**(`app`: `App`, `options?`: `Partial<Options>`): *[Menubar](_menubar_.menubar.md)*\n\n*Defined in [Menubar.ts:24](https://github.com/adam-lynch/menubar/blob/6b93752/src/Menubar.ts#L24)*\n\n**Parameters:**\n\nName | Type |\n------ | ------ |\n`app` | `App` |\n`options?` | `Partial<Options>` |\n\n**Returns:** *[Menubar](_menubar_.menubar.md)*\n\n## Accessors\n\n###  app\n\n• **app**:\n\n*Defined in [Menubar.ts:47](https://github.com/adam-lynch/menubar/blob/6b93752/src/Menubar.ts#L47)*\n\n___\n\n###  positioner\n\n• **positioner**:\n\n*Defined in [Menubar.ts:56](https://github.com/adam-lynch/menubar/blob/6b93752/src/Menubar.ts#L56)*\n\n___\n\n###  tray\n\n• **tray**:\n\n*Defined in [Menubar.ts:69](https://github.com/adam-lynch/menubar/blob/6b93752/src/Menubar.ts#L69)*\n\n___\n\n###  window\n\n• **window**:\n\n*Defined in [Menubar.ts:83](https://github.com/adam-lynch/menubar/blob/6b93752/src/Menubar.ts#L83)*\n\n## Methods\n\n###  getOption\n\n▸ **getOption**<**K**>(`key`: `K`): *`Options[K]`*\n\n*Defined in [Menubar.ts:92](https://github.com/adam-lynch/menubar/blob/6b93752/src/Menubar.ts#L92)*\n\n**Type parameters:**\n\n▪ **K**: *keyof Options*\n\n**Parameters:**\n\nName | Type | Description |\n------ | ------ | ------ |\n`key` | `K` | The option key to retrieve, see [Options](../interfaces/_types_.options.md).  |\n\n**Returns:** *`Options[K]`*\n\n___\n\n###  hideWindow\n\n▸ **hideWindow**(): *void*\n\n*Defined in [Menubar.ts:99](https://github.com/adam-lynch/menubar/blob/6b93752/src/Menubar.ts#L99)*\n\n**Returns:** *void*\n\n___\n\n###  setOption\n\n▸ **setOption**<**K**>(`key`: `K`, `value`: `Options[K]`): *void*\n\n*Defined in [Menubar.ts:115](https://github.com/adam-lynch/menubar/blob/6b93752/src/Menubar.ts#L115)*\n\n**Type parameters:**\n\n▪ **K**: *keyof Options*\n\n**Parameters:**\n\nName | Type | Description |\n------ | ------ | ------ |\n`key` | `K` | The option key to modify, see [Options](../interfaces/_types_.options.md). |\n`value` | `Options[K]` | The value to set.  |\n\n**Returns:** *void*\n\n___\n\n###  showWindow\n\n▸ **showWindow**(`trayPos?`: `Electron.Rectangle`): *`Promise<void>`*\n\n*Defined in [Menubar.ts:124](https://github.com/adam-lynch/menubar/blob/6b93752/src/Menubar.ts#L124)*\n\n**Parameters:**\n\nName | Type | Description |\n------ | ------ | ------ |\n`trayPos?` | `Electron.Rectangle` | The bounds to show the window in.  |\n\n**Returns:** *`Promise<void>`*"
  },
  {
    "path": "docs/globals.md",
    "content": "> **[menubar](README.md)**\n\n[Globals](globals.md) /\n\n# menubar\n\n## Index\n\n### External modules\n\n* [\"Menubar\"](modules/_menubar_.md)\n* [\"index\"](modules/_index_.md)\n* [\"types\"](modules/_types_.md)\n* [\"util/getWindowPosition\"](modules/_util_getwindowposition_.md)"
  },
  {
    "path": "docs/interfaces/_types_.options.md",
    "content": "> **[menubar](../README.md)**\n\n[Globals](../globals.md) / [\"types\"](../modules/_types_.md) / [Options](_types_.options.md) /\n\n# Interface: Options\n\n## Hierarchy\n\n* **Options**\n\n## Table of Contents\n\n### Properties\n\n* [browserWindow](_types_.options.md#browserwindow)\n* [dir](_types_.options.md#dir)\n* [icon](_types_.options.md#optional-icon)\n* [index](_types_.options.md#index)\n* [loadUrlOptions](_types_.options.md#optional-loadurloptions)\n* [preloadWindow](_types_.options.md#optional-preloadwindow)\n* [showDockIcon](_types_.options.md#optional-showdockicon)\n* [showOnAllWorkspaces](_types_.options.md#optional-showonallworkspaces)\n* [showOnRightClick](_types_.options.md#optional-showonrightclick)\n* [tooltip](_types_.options.md#tooltip)\n* [tray](_types_.options.md#optional-tray)\n* [windowPosition](_types_.options.md#optional-windowposition)\n\n## Properties\n\n###  browserWindow\n\n• **browserWindow**: *`BrowserWindowConstructorOptions`*\n\n*Defined in [types.ts:23](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L23)*\n\n___\n\n###  dir\n\n• **dir**: *string*\n\n*Defined in [types.ts:27](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L27)*\n\n___\n\n### `Optional` icon\n\n• **icon**? : *string | `NativeImage`*\n\n*Defined in [types.ts:34](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L34)*\n\n___\n\n###  index\n\n• **index**: *string | false*\n\n*Defined in [types.ts:43](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L43)*\n\n___\n\n### `Optional` loadUrlOptions\n\n• **loadUrlOptions**? : *`LoadURLOptions`*\n\n*Defined in [types.ts:51](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L51)*\n\n___\n\n### `Optional` preloadWindow\n\n• **preloadWindow**? : *undefined | false | true*\n\n*Defined in [types.ts:56](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L56)*\n\n___\n\n### `Optional` showDockIcon\n\n• **showDockIcon**? : *undefined | false | true*\n\n*Defined in [types.ts:61](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L61)*\n\n___\n\n### `Optional` showOnAllWorkspaces\n\n• **showOnAllWorkspaces**? : *undefined | false | true*\n\n*Defined in [types.ts:66](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L66)*\n\n___\n\n### `Optional` showOnRightClick\n\n• **showOnRightClick**? : *undefined | false | true*\n\n*Defined in [types.ts:70](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L70)*\n\n___\n\n###  tooltip\n\n• **tooltip**: *string*\n\n*Defined in [types.ts:74](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L74)*\n\n___\n\n### `Optional` tray\n\n• **tray**? : *`Tray`*\n\n*Defined in [types.ts:78](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L78)*\n\n___\n\n### `Optional` windowPosition\n\n• **windowPosition**? : *\"trayLeft\" | \"trayBottomLeft\" | \"trayRight\" | \"trayBottomRight\" | \"trayCenter\" | \"trayBottomCenter\" | \"topLeft\" | \"topRight\" | \"bottomLeft\" | \"bottomRight\" | \"topCenter\" | \"bottomCenter\" | \"leftCenter\" | \"rightCenter\" | \"center\"*\n\n*Defined in [types.ts:83](https://github.com/maxogden/menubar/blob/c7d6640/src/types.ts#L83)*\n"
  },
  {
    "path": "docs/modules/_index_.md",
    "content": "> **[menubar](../README.md)**\n\n[Globals](../globals.md) / [\"index\"](_index_.md) /\n\n# External module: \"index\"\n\n## Index\n\n### Functions\n\n* [menubar](_index_.md#menubar)\n\n## Functions\n\n###  menubar\n\n▸ **menubar**(`options?`: `Partial<Options>`): *[Menubar](../classes/_menubar_.menubar.md)*\n\n*Defined in [index.ts:25](https://github.com/adam-lynch/menubar/blob/6b93752/src/index.ts#L25)*\n\n**Parameters:**\n\nName | Type | Description |\n------ | ------ | ------ |\n`options?` | `Partial<Options>` | Options for creating a menubar application, see [Options](../interfaces/_types_.options.md)  |\n\n**Returns:** *[Menubar](../classes/_menubar_.menubar.md)*"
  },
  {
    "path": "docs/modules/_menubar_.md",
    "content": "> **[menubar](../README.md)**\n\n[Globals](../globals.md) / [\"Menubar\"](_menubar_.md) /\n\n# External module: \"Menubar\"\n\n## Index\n\n### Classes\n\n* [Menubar](../classes/_menubar_.menubar.md)"
  },
  {
    "path": "docs/modules/_types_.md",
    "content": "> **[menubar](../README.md)**\n\n[Globals](../globals.md) / [\"types\"](_types_.md) /\n\n# External module: \"types\"\n\n## Index\n\n### Interfaces\n\n* [Options](../interfaces/_types_.options.md)"
  },
  {
    "path": "docs/modules/_util_getwindowposition_.md",
    "content": "> **[menubar](../README.md)**\n\n[Globals](../globals.md) / [\"util/getWindowPosition\"](_util_getwindowposition_.md) /\n\n# External module: \"util/getWindowPosition\"\n\n## Index\n\n### Functions\n\n* [getWindowPosition](_util_getwindowposition_.md#getwindowposition)\n* [taskbarLocation](_util_getwindowposition_.md#taskbarlocation)\n\n## Functions\n\n###  getWindowPosition\n\n▸ **getWindowPosition**(`tray`: `Tray`): *`WindowPosition`*\n\n*Defined in [util/getWindowPosition.ts:52](https://github.com/adam-lynch/menubar/blob/6b93752/src/util/getWindowPosition.ts#L52)*\n\n**Parameters:**\n\nName | Type | Description |\n------ | ------ | ------ |\n`tray` | `Tray` | The Electron Tray instance.  |\n\n**Returns:** *`WindowPosition`*\n\n___\n\n###  taskbarLocation\n\n▸ **taskbarLocation**(`tray`: `Tray`): *`TaskbarLocation`*\n\n*Defined in [util/getWindowPosition.ts:18](https://github.com/adam-lynch/menubar/blob/6b93752/src/util/getWindowPosition.ts#L18)*\n\n**Parameters:**\n\nName | Type | Description |\n------ | ------ | ------ |\n`tray` | `Tray` | The Electron Tray instance.  |\n\n**Returns:** *`TaskbarLocation`*"
  },
  {
    "path": "examples/arrow/README.md",
    "content": "# example-menubar-arrow\n\n## Description\n\nA menubar app with an arrow on top, that gives the app a popover look.\n\nThanks @leilarrossi for this example, see https://github.com/maxogden/menubar/issues/78.\n\n## Screenshot\n\n![screenshot](./screenshot.png)\n\n## Instructions\n\n- Clone the repository.\n- Run `yarn install` from the root folder.\n- Run `yarn build` from the root folder.\n- `cd` into this directory.\n- Run `yarn install` to install this example's dependencies.\n- Run `yarn start` from this directory to run app.\n"
  },
  {
    "path": "examples/arrow/index.css",
    "content": ".myarrow {\n  position: relative;\n  padding: 12px 0;\n}\n\n.myarrow:before {\n  content: \"\";\n  height: 0;\n  width: 0;\n  border-width: 0 8px 12px 8px;\n  border-style: solid;\n  border-color: transparent transparent #eeeeee transparent;\n  position: absolute;\n  top: 0px;\n  left: 50%;\n  transform: translateX(-50%);\n}\n\n.page {\n  background: #eeeeee;\n  width: 340px;\n  height: 500px;\n  margin: 0 auto;\n}\n\n.darwin.page {\n  border-radius: 5px;\n  overflow: hidden;\n}\n"
  },
  {
    "path": "examples/arrow/index.html",
    "content": "<html>\n  <head>\n    <title>Example App</title>\n    <link rel=\"stylesheet\" href=\"index.css\" />\n  </head>\n  <body class=\"myarrow\">\n    <div class=\"page darwin\">Hello World.</div>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/arrow/main.js",
    "content": "const { menubar } = require('../..');\n\nconst mb = menubar({\n  browserWindow: {\n    transparent: true,\n    width: 350,\n    height: 550,\n  },\n});\n\nmb.on('ready', () => {\n  console.log('Menubar app is ready.');\n});\n"
  },
  {
    "path": "examples/arrow/package.json",
    "content": "{\n  \"name\": \"example-menubar-arrow\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Example menubar electron app\",\n  \"main\": \"main.js\",\n  \"private\": true,\n  \"scripts\": {\n    \"start\": \"electron .\"\n  }\n}\n"
  },
  {
    "path": "examples/hello-world/README.md",
    "content": "# example-menubar-hello-world\n\n## Description\n\nThis is a simple Hello World menubar app that will just open a window that says \"Hello World\".\n\n## Screenshot\n\n![screenshot](./screenshot.png)\n\n## Instructions\n\n- Clone the repository.\n- Run `yarn install` from the root folder.\n- Run `yarn build` from the root folder.\n- `cd` into this directory.\n- Run `yarn install` to install this example's dependencies.\n- Run `yarn start` from this directory to run app.\n"
  },
  {
    "path": "examples/hello-world/index.html",
    "content": "<html>\n  <head>\n    <title>Example App</title>\n  </head>\n  <body>\n    Hello World.\n  </body>\n</html>\n"
  },
  {
    "path": "examples/hello-world/main.js",
    "content": "const { menubar } = require('../..');\n\nconst mb = menubar();\n\nmb.on('ready', () => {\n  console.log('Menubar app is ready.');\n});\n"
  },
  {
    "path": "examples/hello-world/package.json",
    "content": "{\n  \"name\": \"example-menubar-hello-world\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Example menubar electron app\",\n  \"main\": \"main.js\",\n  \"private\": true,\n  \"scripts\": {\n    \"start\": \"electron .\"\n  }\n}\n"
  },
  {
    "path": "examples/icon-animation/index.html",
    "content": "<html>\n  <head>\n    <title>Example App</title>\n  </head>\n  <body>\n    Hello World.\n  </body>\n</html>\n"
  },
  {
    "path": "examples/icon-animation/main.js",
    "content": "const { menubar } = require('../..');\n\nconst mb = menubar();\n\nmb.on('ready', () => {\n  setOkIcon();\n  const trayAnimation = setInterval(frame, 1000);\n  // simulate data fetching\n  sleep(3000).then(() => {\n    clearInterval(trayAnimation);\n    setOkIcon();\n  });\n});\n\nfunction setOkIcon() {\n  mb.tray.setImage('state-ok-20.png');\n}\n\nfunction frame() {\n  setTimeout(() => mb.tray.setImage('state-sync-20.png'), 300);\n  setTimeout(() => mb.tray.setImage('state-sync-20-60.png'), 600);\n  setTimeout(() => mb.tray.setImage('state-sync-20-120.png'), 900);\n}\n\nfunction sleep(ms) {\n  return new Promise((resolve) => {\n    setTimeout(resolve, ms);\n  });\n}\n"
  },
  {
    "path": "examples/icon-animation/package.json",
    "content": "{\n  \"name\": \"example-menubar-icon-animation\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Example menubar electron app\",\n  \"main\": \"main.js\",\n  \"private\": true,\n  \"scripts\": {\n    \"start\": \"electron .\"\n  }\n}\n"
  },
  {
    "path": "examples/native-menu/README.md",
    "content": "# example-menubar-native-menu\n\n## Description\n\nThis will create a menubar app with a native menu.\n\nCourtesy of @tslater in https://github.com/maxogden/menubar/issues/178.\n\n## Screenshot\n\n![screenshot](./screenshot.png)\n\n## Instructions\n\n- Clone the repository.\n- Run `yarn install` from the root folder.\n- Run `yarn build` from the root folder.\n- `cd` into this directory.\n- Run `yarn install` to install this example's dependencies.\n- Run `yarn start` from this directory to run app.\n"
  },
  {
    "path": "examples/native-menu/main.js",
    "content": "const { app, Menu, Tray } = require('electron');\nconst path = require('path');\n\nconst { menubar } = require('../../');\n\nconst iconPath = path.join(__dirname, '..', '..', 'assets', 'IconTemplate.png');\n\napp.on('ready', () => {\n  const tray = new Tray(iconPath);\n  const contextMenu = Menu.buildFromTemplate([\n    { label: 'Item1', type: 'radio' },\n    { label: 'Item2', type: 'radio' },\n    { label: 'Item3', type: 'radio', checked: true },\n    { label: 'Item4', type: 'radio' },\n  ]);\n  tray.setContextMenu(contextMenu);\n\n  const mb = menubar({\n    tray,\n  });\n\n  mb.on('ready', () => {\n    // needed for macos to remove white screen\n    // ref: https://github.com/max-mapper/menubar/issues/345\n    tray.removeAllListeners();\n\n    console.log('Menubar app is ready.');\n    // your app code here\n  });\n});\n"
  },
  {
    "path": "examples/native-menu/package.json",
    "content": "{\n  \"name\": \"example-menubar-native-menu\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Example menubar electron app\",\n  \"main\": \"main.js\",\n  \"private\": true,\n  \"scripts\": {\n    \"start\": \"electron .\"\n  }\n}\n"
  },
  {
    "path": "examples/package.json",
    "content": "{\n  \"name\": \"example-menubar\",\n  \"version\": \"0.1.0\",\n  \"description\": \"Examples of menubar electron apps\",\n  \"private\": true,\n  \"workspaces\": [\"arrow\", \"hello-world\", \"icon-animation\", \"native-menu\"],\n  \"devDependencies\": {\n    \"electron\": \"^34.3.0\"\n  }\n}\n"
  },
  {
    "path": "jest.config.js",
    "content": "module.exports = {\n  collectCoverageFrom: ['**/*.{ts,tsx}', '!**/node_modules/**', '!**/*.d.ts'],\n  moduleFileExtensions: ['js', 'ts', 'tsx'],\n  rootDir: '.',\n  transform: {\n    '^.+\\\\.(ts|tsx)$': 'ts-jest',\n  },\n  testRegex: 'spec\\\\.(ts|tsx)$',\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"menubar\",\n  \"version\": \"9.5.2\",\n  \"author\": \"Max Ogden\",\n  \"bugs\": {\n    \"url\": \"https://github.com/maxogden/menubar/issues\"\n  },\n  \"description\": \"high level way to create menubar desktop applications with electron\",\n  \"files\": [\n    \"/assets\",\n    \"/lib\"\n  ],\n  \"homepage\": \"https://github.com/maxogden/menubar\",\n  \"keywords\": [\n    \"electron\",\n    \"shell\",\n    \"menubar\",\n    \"menu\",\n    \"taskbar\",\n    \"tray\",\n    \"traybar\",\n    \"mac\",\n    \"linux\",\n    \"windows\",\n    \"app\"\n  ],\n  \"license\": \"BSD-2-Clause\",\n  \"main\": \"lib/index.js\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/maxogden/menubar.git\"\n  },\n  \"scripts\": {\n    \"build\": \"rimraf lib/ && tsc\",\n    \"deploy\": \"yarn build && standard-version\",\n    \"docs\": \"typedoc\",\n    \"lint:check\": \"biome check\",\n    \"lint\": \"biome check --fix\",\n    \"test\": \"jest\"\n  },\n  \"types\": \"lib/index.d.ts\",\n  \"dependencies\": {\n    \"electron-positioner\": \"^4.1.0\"\n  },\n  \"devDependencies\": {\n    \"@biomejs/biome\": \"^1.9.3\",\n    \"@types/jest\": \"^25.2.3\",\n    \"electron\": \"^34.3.0\",\n    \"jest\": \"^26.0.1\",\n    \"rimraf\": \"^3.0.2\",\n    \"standard-version\": \"^8.0.0\",\n    \"ts-jest\": \"^26.0.0\",\n    \"typedoc\": \"^0.17.7\",\n    \"typedoc-plugin-markdown\": \"^2.2.17\",\n    \"typedoc-plugin-no-inherit\": \"^1.1.10\",\n    \"typescript\": \"^4.6.2\"\n  },\n  \"peerDependencies\": {\n    \"electron\": \">=9.0.0 <35.0.0\"\n  },\n  \"packageManager\": \"yarn@1.22.22\"\n}\n"
  },
  {
    "path": "src/Menubar.spec.ts",
    "content": "import { BrowserWindow, Tray, app } from 'electron';\n\nimport { Menubar } from './Menubar';\n\ndescribe('Menubar', () => {\n  let mb: Menubar | undefined;\n\n  beforeEach(() => {\n    mb = new Menubar(app, { preloadWindow: true });\n  });\n\n  it('should have property `app`', () => {\n    expect(mb!.app).toBeDefined();\n  });\n\n  it('should have property `positioner`', () => {\n    expect(() => mb!.positioner as unknown).toThrow();\n    return new Promise<void>((resolve) => {\n      mb!.on('after-create-window', () => {\n        expect(mb!.positioner).toBeDefined();\n        resolve();\n      });\n    });\n  });\n\n  it('should have property `tray`', () => {\n    expect(() => mb!.tray).toThrow();\n    return new Promise<void>((resolve) => {\n      mb!.on('ready', () => {\n        expect(mb!.tray).toBeInstanceOf(Tray);\n        resolve();\n      });\n    });\n  });\n\n  it('should have property `window`', () => {\n    expect(mb!.window).toBeUndefined();\n    return new Promise<void>((resolve) => {\n      mb!.on('ready', () => {\n        expect(mb!.window).toBeInstanceOf(BrowserWindow);\n        resolve();\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "src/Menubar.ts",
    "content": "import { EventEmitter } from 'events';\nimport fs from 'fs';\nimport path from 'path';\nimport { BrowserWindow, Tray } from 'electron';\nimport Positioner from 'electron-positioner';\n\nimport type { Options } from './types';\nimport { cleanOptions } from './util/cleanOptions';\nimport { getWindowPosition } from './util/getWindowPosition';\n\n/**\n * The main Menubar class.\n *\n * @noInheritDoc\n */\nexport class Menubar extends EventEmitter {\n  private _app: Electron.App;\n  private _browserWindow?: BrowserWindow;\n  private _blurTimeout: NodeJS.Timeout | null = null; // track blur events with timeout\n  private _isVisible: boolean; // track visibility\n  private _cachedBounds?: Electron.Rectangle; // _cachedBounds are needed for double-clicked event\n  private _options: Options;\n  private _positioner: Positioner | undefined;\n  private _tray?: Tray;\n\n  constructor(app: Electron.App, options?: Partial<Options>) {\n    super();\n    this._app = app;\n    this._options = cleanOptions(options);\n    this._isVisible = false;\n\n    if (app.isReady()) {\n      // See https://github.com/maxogden/menubar/pull/151\n      process.nextTick(() =>\n        this.appReady().catch((err) => console.error('menubar: ', err)),\n      );\n    } else {\n      app.on('ready', () => {\n        this.appReady().catch((err) => console.error('menubar: ', err));\n      });\n    }\n  }\n\n  /**\n   * The Electron [App](https://electronjs.org/docs/api/app)\n   * instance.\n   */\n  get app(): Electron.App {\n    return this._app;\n  }\n\n  /**\n   * The [electron-positioner](https://github.com/jenslind/electron-positioner)\n   * instance.\n   */\n  get positioner(): Positioner {\n    if (!this._positioner) {\n      throw new Error(\n        'Please access `this.positioner` after the `after-create-window` event has fired.',\n      );\n    }\n\n    return this._positioner;\n  }\n\n  /**\n   * The Electron [Tray](https://electronjs.org/docs/api/tray) instance.\n   */\n  get tray(): Tray {\n    if (!this._tray) {\n      throw new Error(\n        'Please access `this.tray` after the `ready` event has fired.',\n      );\n    }\n\n    return this._tray;\n  }\n\n  /**\n   * The Electron [BrowserWindow](https://electronjs.org/docs/api/browser-window)\n   * instance, if it's present.\n   */\n  get window(): BrowserWindow | undefined {\n    return this._browserWindow;\n  }\n\n  /**\n   * Retrieve a menubar option.\n   *\n   * @param key - The option key to retrieve, see {@link Options}.\n   */\n  getOption<K extends keyof Options>(key: K): Options[K] {\n    return this._options[key];\n  }\n\n  /**\n   * Hide the menubar window.\n   */\n  hideWindow(): void {\n    if (!this._browserWindow || !this._isVisible) {\n      return;\n    }\n    this.emit('hide');\n    this._browserWindow.hide();\n    this.emit('after-hide');\n    this._isVisible = false;\n    if (this._blurTimeout) {\n      clearTimeout(this._blurTimeout);\n      this._blurTimeout = null;\n    }\n  }\n\n  /**\n   * Change an option after menubar is created.\n   *\n   * @param key - The option key to modify, see {@link Options}.\n   * @param value - The value to set.\n   */\n  setOption<K extends keyof Options>(key: K, value: Options[K]): void {\n    this._options[key] = value;\n  }\n\n  /**\n   * Show the menubar window.\n   *\n   * @param trayPos - The bounds to show the window in.\n   */\n  async showWindow(trayPos?: Electron.Rectangle): Promise<void> {\n    if (!this.tray) {\n      throw new Error('Tray should have been instantiated by now');\n    }\n\n    if (!this._browserWindow) {\n      await this.createWindow();\n    }\n\n    // Use guard for TypeScript, to avoid ! everywhere\n    if (!this._browserWindow) {\n      throw new Error('Window has been initialized just above. qed.');\n    }\n\n    // 'Windows' taskbar: sync windows position each time before showing\n    // https://github.com/maxogden/menubar/issues/232\n    if (['win32', 'linux'].includes(process.platform)) {\n      // Fill in this._options.windowPosition when taskbar position is available\n      this._options.windowPosition = getWindowPosition(this.tray);\n    }\n\n    this.emit('show');\n\n    if (trayPos && trayPos.x !== 0) {\n      // Cache the bounds\n      this._cachedBounds = trayPos;\n    } else if (this._cachedBounds) {\n      // Cached value will be used if showWindow is called without bounds data\n      trayPos = this._cachedBounds;\n    } else if (this.tray.getBounds) {\n      // Get the current tray bounds\n      trayPos = this.tray.getBounds();\n    }\n\n    // Default the window to the right if `trayPos` bounds are undefined or null.\n    let noBoundsPosition = undefined;\n    if (\n      (trayPos === undefined || trayPos.x === 0) &&\n      this._options.windowPosition &&\n      this._options.windowPosition.startsWith('tray')\n    ) {\n      noBoundsPosition =\n        process.platform === 'win32' ? 'bottomRight' : 'topRight';\n    }\n\n    const position = this.positioner.calculate(\n      this._options.windowPosition || noBoundsPosition,\n      trayPos,\n    ) as { x: number; y: number };\n\n    // Not using `||` because x and y can be zero.\n    const x =\n      this._options.browserWindow.x !== undefined\n        ? this._options.browserWindow.x\n        : position.x;\n    const y =\n      this._options.browserWindow.y !== undefined\n        ? this._options.browserWindow.y\n        : position.y;\n\n    // `.setPosition` crashed on non-integers\n    // https://github.com/maxogden/menubar/issues/233\n    this._browserWindow.setPosition(Math.round(x), Math.round(y));\n    this._browserWindow.show();\n    this._isVisible = true;\n    this.emit('after-show');\n    return;\n  }\n\n  private async appReady(): Promise<void> {\n    if (this.app.dock && !this._options.showDockIcon) {\n      this.app.dock.hide();\n    }\n\n    if (this._options.activateWithApp) {\n      this.app.on('activate', (_event, hasVisibleWindows) => {\n        if (!hasVisibleWindows) {\n          this.showWindow().catch(console.error);\n        }\n      });\n    }\n\n    let trayImage =\n      this._options.icon || path.join(this._options.dir, 'IconTemplate.png');\n    if (typeof trayImage === 'string' && !fs.existsSync(trayImage)) {\n      trayImage = path.join(__dirname, '..', 'assets', 'IconTemplate.png'); // Default cat icon\n    }\n\n    const defaultClickEvent = this._options.showOnRightClick\n      ? 'right-click'\n      : 'click';\n\n    this._tray = this._options.tray || new Tray(trayImage);\n    // Type guards for TS not to complain\n    if (!this.tray) {\n      throw new Error('Tray has been initialized above');\n    }\n    this.tray.on(\n      defaultClickEvent as Parameters<Tray['on']>[0],\n      this.clicked.bind(this),\n    );\n    this.tray.on('double-click', this.clicked.bind(this));\n    this.tray.setToolTip(this._options.tooltip);\n\n    if (!this._options.windowPosition) {\n      this._options.windowPosition = getWindowPosition(this.tray);\n    }\n\n    if (this._options.preloadWindow) {\n      await this.createWindow();\n    }\n\n    this.emit('ready');\n  }\n\n  /**\n   * Callback on tray icon click or double-click.\n   *\n   * @param e\n   * @param bounds\n   */\n  private async clicked(\n    event?: Electron.KeyboardEvent,\n    bounds?: Electron.Rectangle,\n  ): Promise<void> {\n    if (event && (event.shiftKey || event.ctrlKey || event.metaKey)) {\n      return this.hideWindow();\n    }\n\n    // if blur was invoked clear timeout\n    if (this._blurTimeout) {\n      clearInterval(this._blurTimeout);\n    }\n\n    if (this._browserWindow && this._isVisible) {\n      return this.hideWindow();\n    }\n\n    this._cachedBounds = bounds || this._cachedBounds;\n    await this.showWindow(this._cachedBounds);\n  }\n\n  private async createWindow(): Promise<void> {\n    this.emit('create-window');\n\n    // We add some default behavior for menubar's browserWindow, to make it\n    // look like a menubar\n    const defaults = {\n      show: false, // Don't show it at first\n      frame: false, // Remove window frame\n    };\n\n    this._browserWindow = new BrowserWindow({\n      ...defaults,\n      ...this._options.browserWindow,\n    });\n\n    this._positioner = new Positioner(this._browserWindow);\n\n    this._browserWindow.on('blur', () => {\n      if (!this._browserWindow) {\n        return;\n      }\n\n      // hack to close if icon clicked when open\n      this._browserWindow.isAlwaysOnTop()\n        ? this.emit('focus-lost')\n        : (this._blurTimeout = setTimeout(() => {\n            this.hideWindow();\n          }, 100));\n    });\n\n    if (this._options.showOnAllWorkspaces !== false) {\n      // https://github.com/electron/electron/issues/37832#issuecomment-1497882944\n      this._browserWindow.setVisibleOnAllWorkspaces(true, {\n        skipTransformProcessType: true, // Avoid damaging the original visible state of app.dock\n      });\n    }\n\n    this._browserWindow.on('close', this.windowClear.bind(this));\n\n    this.emit('before-load');\n\n    // If the user explicity set options.index to false, we don't loadURL\n    // https://github.com/maxogden/menubar/issues/255\n    if (this._options.index !== false) {\n      await this._browserWindow.loadURL(\n        this._options.index,\n        this._options.loadUrlOptions,\n      );\n    }\n    this.emit('after-create-window');\n  }\n\n  private windowClear(): void {\n    this._browserWindow = undefined;\n    this.emit('after-close');\n  }\n}\n"
  },
  {
    "path": "src/__mocks__/electron.ts",
    "content": "// https://github.com/electron/electron/issues/3909#issuecomment-190990825\n\nexport const MOCK_APP_GETAPPPATH = 'mock.app.getAppPath';\n\nexport const app = {\n  getAppPath: jest.fn(() => MOCK_APP_GETAPPPATH),\n  isReady: (): Promise<void> => Promise.resolve(),\n  on: (): void => {\n    /* Do nothing */\n  },\n};\n\nexport class BrowserWindow {\n  loadURL(): void {\n    // Do nothing\n  }\n\n  on(): void {\n    // Do nothing\n  }\n\n  setVisibleOnAllWorkspaces(): void {\n    // Do nothing\n  }\n}\n\nexport class Tray {\n  on(): void {\n    // Do nothing\n  }\n\n  setToolTip(): void {\n    // Do nothing\n  }\n}\n"
  },
  {
    "path": "src/ambient.d.ts",
    "content": "// TODO https://github.com/jenslind/electron-positioner/issues/15\ndeclare module 'electron-positioner' {\n  export default class {\n    constructor(window: Electron.BrowserWindow);\n\n    calculate(\n      position?: string,\n      rectangle?: Electron.Rectangle,\n    ): { x: number; y: number };\n  }\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "/**\n * Entry point of menubar\n * @example\n * ```typescript\n * import { menubar } from 'menubar';\n * ```\n */\n\n/** */\n\nimport { app } from 'electron';\n\nimport { Menubar } from './Menubar';\nimport type { Options } from './types';\n\nexport * from './util/getWindowPosition';\nexport { Menubar };\n\n/**\n * Factory function to create a menubar application\n *\n * @param options - Options for creating a menubar application, see\n * {@link Options}\n */\nexport function menubar(options?: Partial<Options>): Menubar {\n  return new Menubar(app, options);\n}\n"
  },
  {
    "path": "src/types.ts",
    "content": "import type {\n  BrowserWindowConstructorOptions,\n  LoadURLOptions,\n  Tray,\n} from 'electron';\n\n/**\n * Options for creating a menubar application\n */\nexport interface Options {\n  /**\n   * Listen on `app.on('activate')` to open menubar when app is activated.\n   * @default `true`\n   */\n  activateWithApp?: boolean;\n  /**\n   * An Electron BrowserWindow instance, or an options object to be passed into\n   * the BrowserWindow constructor.\n   * @example\n   * ```typescript\n   * const options = { height: 640, width: 480 };\n   *\n   * const mb = new Menubar({\n   *   browserWindow: options\n   * });\n   * ```\n   */\n  browserWindow: BrowserWindowConstructorOptions;\n  /**\n   * The app source directory.\n   */\n  dir: string;\n  /**\n   * The png icon to use for the menubar. A good size to start with is 20x20.\n   * To support retina, supply a 2x sized image (e.g. 40x40) with @2x added to\n   * the end of the name, so icon.png and icon@2x.png and Electron will\n   * automatically use your @2x version on retina screens.\n   */\n  icon?: string | Electron.NativeImage;\n  /**\n   * The URL to load the menubar's browserWindow with. The url can be a remote\n   * address (e.g. `http://`) or a path to a local HTML file using the\n   * `file://` protocol. If false, then menubar won't call `loadURL` on\n   * start.\n   * @default `file:// + options.dir + index.html`\n   * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options\n   */\n  index: string | false;\n  /**\n   * The options passed when loading the index URL in the menubar's\n   * browserWindow. Everything browserWindow.loadURL supports is supported;\n   * this object is simply passed onto browserWindow.loadURL\n   * @default `{}`\n   * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options\n   */\n  loadUrlOptions?: LoadURLOptions;\n  /**\n   * Create BrowserWindow instance before it is used -- increasing resource\n   * usage, but making the click on the menubar load faster.\n   */\n  preloadWindow?: boolean;\n  /**\n   * Configure the visibility of the application dock icon, macOS only. Calls\n   * [`app.dock.hide`](https://electronjs.org/docs/api/app#appdockhide-macos).\n   */\n  showDockIcon?: boolean;\n  /**\n   * Makes the window available on all OS X workspaces. Calls\n   * [`setVisibleOnAllWorkspaces`](https://electronjs.org/docs/api/browser-window#winsetvisibleonallworkspacesvisible-options).\n   */\n  showOnAllWorkspaces?: boolean;\n  /**\n   * Show the window on 'right-click' event instead of regular 'click'.\n   */\n  showOnRightClick?: boolean;\n  /**\n   * Menubar tray icon tooltip text. Calls [`tray.setTooltip`](https://electronjs.org/docs/api/tray#traysettooltiptooltip).\n   */\n  tooltip: string;\n  /**\n   * An electron Tray instance. If provided, `options.icon` will be ignored.\n   */\n  tray?: Tray;\n  /**\n   * Sets the window position (x and y will still override this), check\n   * electron-positioner docs for valid values.\n   */\n  windowPosition?:\n    | 'trayLeft'\n    | 'trayBottomLeft'\n    | 'trayRight'\n    | 'trayBottomRight'\n    | 'trayCenter'\n    | 'trayBottomCenter'\n    | 'topLeft'\n    | 'topRight'\n    | 'bottomLeft'\n    | 'bottomRight'\n    | 'topCenter'\n    | 'bottomCenter'\n    | 'leftCenter'\n    | 'rightCenter'\n    | 'center';\n}\n"
  },
  {
    "path": "src/util/cleanOptions.spec.ts",
    "content": "import * as path from 'path';\n\nimport { MOCK_APP_GETAPPPATH } from '../__mocks__/electron';\nimport { cleanOptions } from './cleanOptions';\n\nconst DEFAULT_OPTIONS = {\n  activateWithApp: true,\n  browserWindow: {\n    height: 400,\n    width: 400,\n  },\n  dir: path.resolve(MOCK_APP_GETAPPPATH),\n  index: `file://${path.join(path.resolve(MOCK_APP_GETAPPPATH), 'index.html')}`,\n  loadUrlOptions: {},\n  tooltip: '',\n};\n\ndescribe('cleanOptions', () => {\n  it('should handle undefined', () => {\n    expect(cleanOptions(undefined)).toEqual(DEFAULT_OPTIONS);\n  });\n\n  it('should handle a dir string with relative path', () => {\n    expect(cleanOptions({ dir: 'MY_RELATIVE_PATH' })).toEqual({\n      ...DEFAULT_OPTIONS,\n      dir: path.resolve('MY_RELATIVE_PATH'),\n      index: `file://${path.join(\n        path.resolve('MY_RELATIVE_PATH'),\n        'index.html',\n      )}`,\n    });\n  });\n\n  it('should handle a dir string with absolute path', () => {\n    expect(cleanOptions({ dir: '/home/me/MY_ABSOLUTE_PATH' })).toEqual({\n      ...DEFAULT_OPTIONS,\n      dir: '/home/me/MY_ABSOLUTE_PATH',\n      index: 'file:///home/me/MY_ABSOLUTE_PATH/index.html',\n    });\n  });\n\n  it('should handle a false index', () => {\n    expect(cleanOptions({ index: false })).toEqual({\n      ...DEFAULT_OPTIONS,\n      index: false,\n    });\n  });\n\n  it('should handle an object with multiple fields', () => {\n    expect(\n      cleanOptions({\n        browserWindow: {\n          height: 100,\n        },\n        index: 'file:///home/abc/index.html',\n        showDockIcon: true,\n        windowPosition: 'trayCenter',\n      }),\n    ).toEqual({\n      ...DEFAULT_OPTIONS,\n      browserWindow: {\n        ...DEFAULT_OPTIONS.browserWindow,\n        height: 100,\n      },\n      index: 'file:///home/abc/index.html',\n      showDockIcon: true,\n      windowPosition: 'trayCenter',\n    });\n  });\n});\n"
  },
  {
    "path": "src/util/cleanOptions.ts",
    "content": "/**\n * @ignore\n */\n\n/** */\n\nimport path from 'path';\nimport url from 'url';\nimport { app } from 'electron';\n\nimport type { Options } from '../types';\n\nconst DEFAULT_WINDOW_HEIGHT = 400;\nconst DEFAULT_WINDOW_WIDTH = 400;\n\n/**\n * Take as input some options, and return a sanitized version of it.\n *\n * @param opts - The options to clean.\n * @ignore\n */\nexport function cleanOptions(opts?: Partial<Options>): Options {\n  const options: Partial<Options> = { ...opts };\n\n  if (options.activateWithApp === undefined) {\n    options.activateWithApp = true;\n  }\n  if (!options.dir) {\n    options.dir = app.getAppPath();\n  }\n  if (!path.isAbsolute(options.dir)) {\n    options.dir = path.resolve(options.dir);\n  }\n  // Note: options.index can be `false`\n  if (options.index === undefined) {\n    options.index = url.format({\n      pathname: path.join(options.dir, 'index.html'),\n      protocol: 'file:',\n      slashes: true,\n    });\n  }\n  options.loadUrlOptions = options.loadUrlOptions || {};\n\n  options.tooltip = options.tooltip || '';\n\n  // `icon`, `preloadWindow`, `showDockIcon`, `showOnAllWorkspaces`,\n  // `showOnRightClick` don't need any special treatment\n\n  // Now we take care of `browserWindow`\n  if (!options.browserWindow) {\n    options.browserWindow = {};\n  }\n\n  // Set width/height on options to be usable before the window is created\n  options.browserWindow.width =\n    // Note: not using `options.browserWindow.width || DEFAULT_WINDOW_WIDTH` so\n    // that users can put a 0 width\n    options.browserWindow.width !== undefined\n      ? options.browserWindow.width\n      : DEFAULT_WINDOW_WIDTH;\n  options.browserWindow.height =\n    options.browserWindow.height !== undefined\n      ? options.browserWindow.height\n      : DEFAULT_WINDOW_HEIGHT;\n\n  return options as Options;\n}\n"
  },
  {
    "path": "src/util/getWindowPosition.ts",
    "content": "/**\n * Utilities to get taskbar position and consequently menubar's position\n */\n\n/** */\n\nimport { type Rectangle, type Tray, screen as electronScreen } from 'electron';\n\nconst isLinux = process.platform === 'linux';\n\nconst trayToScreenRects = (tray: Tray): [Rectangle, Rectangle] => {\n  // There may be more than one screen, so we need to figure out on which screen our tray icon lives.\n  const { workArea, bounds: screenBounds } = electronScreen.getDisplayMatching(\n    tray.getBounds(),\n  );\n\n  workArea.x -= screenBounds.x;\n  workArea.y -= screenBounds.y;\n\n  return [screenBounds, workArea];\n};\n\ntype TaskbarLocation = 'top' | 'bottom' | 'left' | 'right';\n\n/**\n * Determine taskbard location: \"top\", \"bottom\", \"left\" or \"right\".\n *\n * Only tested on Windows for now, and only used in Windows.\n *\n * @param tray - The Electron Tray instance.\n */\nexport function taskbarLocation(tray: Tray): TaskbarLocation {\n  const [screenBounds, workArea] = trayToScreenRects(tray);\n\n  // TASKBAR LEFT\n  if (workArea.x > 0) {\n    // Most likely Ubuntu hence assuming the window should be on top\n    if (isLinux && workArea.y > 0) return 'top';\n    // The workspace starts more on the right\n    return 'left';\n  }\n\n  // TASKBAR TOP\n  if (workArea.y > 0) {\n    return 'top';\n  }\n\n  // TASKBAR RIGHT\n  // Here both workArea.y and workArea.x are 0 so we can no longer leverage them.\n  // We can use the workarea and display width though.\n  // Determine taskbar location\n  if (workArea.width < screenBounds.width) {\n    // The taskbar is either on the left or right, but since the LEFT case was handled above,\n    // we can be sure we're dealing with a right taskbar\n    return 'right';\n  }\n\n  // TASKBAR BOTTOM\n  // Since all the other cases were handled, we can be sure we're dealing with a bottom taskbar\n  return 'bottom';\n}\n\ntype WindowPosition =\n  | 'trayCenter'\n  | 'topRight'\n  | 'trayBottomCenter'\n  | 'bottomLeft'\n  | 'bottomRight';\n\n/**\n * Depending on where the taskbar is, determine where the window should be\n * positioned.\n *\n * @param tray - The Electron Tray instance.\n */\nexport function getWindowPosition(tray: Tray): WindowPosition {\n  switch (process.platform) {\n    // macOS\n    // Supports top taskbars\n    case 'darwin':\n      return 'trayCenter';\n    // Linux\n    // Windows\n    // Supports top/bottom/left/right taskbar\n    case 'linux':\n    case 'win32': {\n      const traySide = taskbarLocation(tray);\n\n      // Assign position for menubar\n      if (traySide === 'top') {\n        return isLinux ? 'topRight' : 'trayCenter';\n      }\n      if (traySide === 'bottom') {\n        return 'bottomRight';\n      }\n      if (traySide === 'left') {\n        return 'bottomLeft';\n      }\n      if (traySide === 'right') {\n        return 'bottomRight';\n      }\n    }\n  }\n\n  // When we really don't know, we just show the menubar on the top-right\n  return 'topRight';\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"module\": \"commonjs\",\n    \"esModuleInterop\": true,\n    \"strict\": true,\n    \"declaration\": true,\n    \"outDir\": \"./lib\",\n    \"skipLibCheck\": true,\n    \"target\": \"es5\"\n  }\n}\n"
  },
  {
    "path": "typedoc.js",
    "content": "module.exports = {\n  exclude: ['**/*spec.ts', '**/__mocks__/**'],\n  excludeExternals: true,\n  excludeNotExported: true,\n  excludePrivate: true,\n  excludeProtected: true,\n  hideGenerator: true,\n  includes: './src',\n  module: 'commonjs',\n  out: 'docs',\n  stripInternal: 'true',\n  theme: 'markdown',\n};\n"
  }
]