[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\n\nA clear and concise description of what the bug is.\n\n**To Reproduce**\n\nSteps to reproduce the behavior:\n\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\n\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\n\nIf applicable, add screenshots to help explain your problem.\n\n**Desktop (please complete the following information):**\n\n- OS: [e.g. Mac Big Sur 11.2.3]\n- Browser [e.g. chrome, safari]\n- @trodi/electron-splashscreen version [e.g. 1.0.0]\n- Electron version: [e.g., 8.1.1]\n\n**Additional context**\n\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n*.js\n*.d.ts\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"node\"\nscript: npm run build\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to electron-splashscreen\n\n- Have an issue? Open an issue. PRs welcome.\n- Have a feature request? Open an issue to see if the feature is in scope of the project.\n\n*Please avoid publishing forked versions of this project instead of contributing to it directly!*\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Troy McKinnon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<img src=\"https://raw.githubusercontent.com/trodi/electron-splashscreen/master/icon.svg?sanitize=true\" width=\"200\" height=\"200\" align=\"right\" />\n\n# electron-splashscreen [![Build Status](https://travis-ci.org/trodi/electron-splashscreen.svg)](https://travis-ci.org/trodi/electron-splashscreen)\n\n> *Simple splashscreen for [Electron](http://electron.atom.io) applications.*\n\nIdeally, your application loads instantaneously. However, some applications are larger and/or may be running on a slower machine, causing the load to take longer. If the application is taking a bit to load, `electron-splashscreen` will appear so the user knows the application is loading, but can't interact with a partially loaded application.\n\n`electron-splashscreen` is simple to incorporate, while allowing you the freedom to customize with any look, feel, and functionality.\n\n*No external dependencies.*\n\n<p align=\"center\"><img src=\"https://raw.githubusercontent.com/trodi/electron-splashscreen/master/demo.gif\" width=\"400\"></p>\n\n## Install\n\n```shell\nnpm install @trodi/electron-splashscreen\n```\n\n## Usage\n\n### Typescript Usage (javascript would be similar)\n\n*Example of your Electron browser process.*\n\n```typescript\n// import the module\nimport * as Splashscreen from \"@trodi/electron-splashscreen\";\nconst mainOpts: Electron.BrowserWindowConstructorOptions = ...\n// configure the splashscreen\nconst config: Splashscreen.Config = {\n    windowOpts: mainOpts;\n    templateUrl: `${__dirname}/splash-screen.html`;\n    splashScreenOpts: {\n        width: 425,\n        height: 325,\n    },\n};\n// initialize the splashscreen handling\nconst main: BrowserWindow = Splashscreen.initSplashScreen(config);\n// load your browser window per usual\nmain.loadURL(`file://index.html`);\n```\n\nYou can run examples via `npm run example` and `npm run example-dynamic`.\n\n## API\n\n[API Documentation](https://github.com/trodi/electron-splashscreen/blob/master/api-doc/README.md)\n\n## Build\n\n`npm run build`\n\n## Publish\n\n* `npm version <patch|minor|major>`\n* `npm publish`\n* Commit and push changes to git\n\n## License\n\n[MIT License](LICENSE)\n"
  },
  {
    "path": "api-doc/README.md",
    "content": "[@trodi/electron-splashscreen - v1.0.0](README.md)\n\n# @trodi/electron-splashscreen - v1.0.0\n\n## Index\n\n### Interfaces\n\n* [Config](interfaces/config.md)\n* [DynamicSplashScreen](interfaces/dynamicsplashscreen.md)\n\n### Functions\n\n* [initDynamicSplashScreen](README.md#const-initdynamicsplashscreen)\n* [initSplashScreen](README.md#const-initsplashscreen)\n\n## Functions\n\n### `Const` initDynamicSplashScreen\n\n▸ **initDynamicSplashScreen**(`config`: [Config](interfaces/config.md)): *[DynamicSplashScreen](interfaces/dynamicsplashscreen.md)*\n\nInitializes a splashscreen that will show/hide smartly (and handle show/hiding of main window).\nUse this function if you need to send/receive info to the splashscreen (e.g., you want to send\nIPC messages to the splashscreen to inform the user of the app's loading state).\n\n**Parameters:**\n\nName | Type | Description |\n------ | ------ | ------ |\n`config` | [Config](interfaces/config.md) | Configures splashscren |\n\n**Returns:** *[DynamicSplashScreen](interfaces/dynamicsplashscreen.md)*\n\nthe main browser window and the created splashscreen\n\n___\n\n### `Const` initSplashScreen\n\n▸ **initSplashScreen**(`config`: [Config](interfaces/config.md)): *BrowserWindow*\n\nInitializes a splashscreen that will show/hide smartly (and handle show/hiding of main window).\n\n**Parameters:**\n\nName | Type | Description |\n------ | ------ | ------ |\n`config` | [Config](interfaces/config.md) | Configures splashscren |\n\n**Returns:** *BrowserWindow*\n\nthe main browser window ready for loading\n"
  },
  {
    "path": "api-doc/interfaces/config.md",
    "content": "[@trodi/electron-splashscreen - v1.0.0](../README.md) › [Config](config.md)\n\n# Interface: Config\n\n`electron-splashscreen` config object.\n\n## Hierarchy\n\n* **Config**\n\n## Index\n\n### Properties\n\n* [closeWindow](config.md#optional-closewindow)\n* [delay](config.md#optional-delay)\n* [minVisible](config.md#optional-minvisible)\n* [splashScreenOpts](config.md#splashscreenopts)\n* [templateUrl](config.md#templateurl)\n* [windowOpts](config.md#windowopts)\n\n## Properties\n\n### `Optional` closeWindow\n\n• **closeWindow**? : *undefined | false | true*\n\nClose window that is loading if splashscreen is closed by user (default: true).\n\n___\n\n### `Optional` delay\n\n• **delay**? : *undefined | number*\n\nNumber of ms the window will load before splashscreen appears (default: 500ms).\n\n___\n\n### `Optional` minVisible\n\n• **minVisible**? : *undefined | number*\n\nMinimum ms the splashscreen will be visible (default: 500ms).\n\n___\n\n###  splashScreenOpts\n\n• **splashScreenOpts**: *BrowserWindowConstructorOptions*\n\nFull set of browser window options for the splashscreen. We override key attributes to\nmake it look & feel like a splashscreen; the rest is up to you!\n\n___\n\n###  templateUrl\n\n• **templateUrl**: *string*\n\nURL to the splashscreen template. This is the path to an `HTML` or `SVG` file.\nIf you want to simply show a `PNG`, wrap it in an `HTML` file.\n\n___\n\n###  windowOpts\n\n• **windowOpts**: *BrowserWindowConstructorOptions*\n\nOptions for the window that is loading and having a splashscreen tied to.\n"
  },
  {
    "path": "api-doc/interfaces/dynamicsplashscreen.md",
    "content": "[@trodi/electron-splashscreen - v1.0.0](../README.md) › [DynamicSplashScreen](dynamicsplashscreen.md)\n\n# Interface: DynamicSplashScreen\n\nReturn object for `initDynamicSplashScreen()`.\n\n## Hierarchy\n\n* **DynamicSplashScreen**\n\n## Index\n\n### Properties\n\n* [main](dynamicsplashscreen.md#main)\n* [splashScreen](dynamicsplashscreen.md#splashscreen)\n\n## Properties\n\n###  main\n\n• **main**: *BrowserWindow*\n\nThe main browser window ready for loading\n\n___\n\n###  splashScreen\n\n• **splashScreen**: *BrowserWindow*\n\nThe splashscreen browser window so you can communicate with splashscreen in more complex use cases.\n"
  },
  {
    "path": "examples/example-app.html",
    "content": "<!DOCTYPE html>\n<meta charset=\"utf-8\">\n<html>\n    <head></head>\n    <body>\n        <center>\n            <img src=\"../icon.svg\" height=\"300\" width=\"300\"></img>\n        </center>\n        <center>\n            App loaded!\n        </center>\n    </body>\n</html>\n"
  },
  {
    "path": "examples/example-dynamic-splashscreen.html",
    "content": "<!DOCTYPE html>\n<meta charset=\"utf-8\">\n<html>\n    <head></head>\n    <body>\n        <center>\n            <img src=\"../icon.svg\" width=\"200\" height=\"200\"></img>\n        </center>\n        <center>\n            Loading...<span id=\"status\"></span>\n        </center>\n    </body>\n    <script>\n        // Listen for data from browser process and update splashscreen\n        var ipcRenderer = require(\"electron\").ipcRenderer;\n        ipcRenderer.on(\"update\", function(event, status) {\n            document.getElementById(\"status\").innerText = status;\n        })\n    </script>\n</html>\n"
  },
  {
    "path": "examples/example-dynamic.ts",
    "content": "import { app, BrowserWindow } from \"electron\";\nimport * as path from \"path\";\nimport * as url from \"url\";\nimport * as Splashscreen from \"../index\";\n\nlet window: BrowserWindow;\napp.on(\"ready\", () => {\n    const windowOptions = {\n        width: 500,\n        height: 375,\n        show: false,\n    };\n    const ret: Splashscreen.DynamicSplashScreen = Splashscreen.initDynamicSplashScreen({\n        windowOpts: windowOptions,\n        templateUrl: path.join(__dirname, \"example-dynamic-splashscreen.html\"),\n        delay: 0, // force show immediately to better illustrate example\n        splashScreenOpts: {\n            height: 500,\n            width: 500,\n            backgroundColor: \"white\",\n            webPreferences: {\n                nodeIntegration: true,\n            },\n        },\n    });\n    window = ret.main;\n    /** Send information to the splashscreen. */\n    const update = (i: number): void => {\n        ret.splashScreen.webContents.send(\"update\", i);\n        if (i > 0) {\n            setTimeout(() => update(i - 1), 500);\n        } else {\n            // Done sending updates to mock progress while loading window, so\n            // go ahead and load the main window.\n            window.loadURL(`file://${path.join(__dirname, \"example-app.html\")}`);\n        }\n    };\n    update(5);\n});\napp.on(\"window-all-closed\", () => {\n    app.quit();\n});\n"
  },
  {
    "path": "examples/example.ts",
    "content": "import { app, BrowserWindow } from \"electron\";\nimport * as path from \"path\";\nimport * as url from \"url\";\nimport * as Splashscreen from \"../index\";\n\nlet window: BrowserWindow;\napp.on(\"ready\", () => {\n    const windowOptions = {\n        width: 500,\n        height: 375,\n        show: false,\n    };\n    window = Splashscreen.initSplashScreen({\n        windowOpts: windowOptions,\n        templateUrl: path.join(__dirname, \"..\", \"icon.svg\"),\n        delay: 0, // force show immediately since example will load fast\n        minVisible: 1500, // show for 1.5s so example is obvious\n        splashScreenOpts: {\n            height: 500,\n            width: 500,\n            transparent: true,\n        },\n    });\n    window.loadURL(`file://${path.join(__dirname, \"example-app.html\")}`);\n});\napp.on(\"window-all-closed\", () => {\n    app.quit();\n});\n"
  },
  {
    "path": "index.ts",
    "content": "/**\n * Module handles configurable splashscreen to show while app is loading.\n */\n\nimport { BrowserWindow } from \"electron\";\n\n/**\n * When splashscreen was shown.\n * @ignore\n */\nlet splashScreenTimestamp: number = 0;\n/**\n * Splashscreen is loaded and ready to show.\n * @ignore\n */\nlet splashScreenReady = false;\n/**\n * Main window has been loading for a min amount of time.\n * @ignore\n */\nlet slowStartup = false;\n/**\n * True when expected work is complete and we've closed splashscreen, else user prematurely closed splashscreen.\n * @ignore\n */\nlet done = false;\n/**\n * Show splashscreen if criteria are met.\n * @ignore\n */\nconst showSplash = () => {\n    if (splashScreen && splashScreenReady && slowStartup) {\n        splashScreen.show();\n        splashScreenTimestamp = Date.now();\n    }\n};\n/**\n * Close splashscreen / show main screen. Ensure screen is visible for a min amount of time.\n * @ignore\n */\nconst closeSplashScreen = (main: Electron.BrowserWindow, min: number): void => {\n    if (splashScreen) {\n        const timeout = min - (Date.now() - splashScreenTimestamp);\n        setTimeout(() => {\n            done = true;\n            if (splashScreen) {\n                splashScreen.isDestroyed() || splashScreen.close(); // Avoid `Error: Object has been destroyed` (#19)\n                splashScreen = null;\n            }\n            main.show();\n        }, timeout);\n    }\n};\n/** `electron-splashscreen` config object. */\nexport interface Config {\n    /** Options for the window that is loading and having a splashscreen tied to. */\n    windowOpts: Electron.BrowserWindowConstructorOptions;\n    /**\n     * URL to the splashscreen template. This is the path to an `HTML` or `SVG` file.\n     * If you want to simply show a `PNG`, wrap it in an `HTML` file.\n     */\n    templateUrl: string;\n    /**\n     * Full set of browser window options for the splashscreen. We override key attributes to\n     * make it look & feel like a splashscreen; the rest is up to you!\n     */\n    splashScreenOpts: Electron.BrowserWindowConstructorOptions;\n    /** Number of ms the window will load before splashscreen appears (default: 500ms). */\n    delay?: number;\n    /** Minimum ms the splashscreen will be visible (default: 500ms). */\n    minVisible?: number;\n    /** Close window that is loading if splashscreen is closed by user (default: true). */\n    closeWindow?: boolean;\n}\n/**\n * The actual splashscreen browser window.\n * @ignore\n */\nlet splashScreen: Electron.BrowserWindow | null;\n/**\n * Initializes a splashscreen that will show/hide smartly (and handle show/hiding of main window).\n * @param config - Configures splashscreen\n * @returns {BrowserWindow} the main browser window ready for loading\n */\nexport const initSplashScreen = (config: Config): BrowserWindow => {\n    const xConfig: Required<Config> = {\n        windowOpts: config.windowOpts,\n        templateUrl: config.templateUrl,\n        splashScreenOpts: config.splashScreenOpts,\n        delay: config.delay ?? 500,\n        minVisible: config.minVisible ?? 500,\n        closeWindow: config.closeWindow ?? true,\n    };\n    xConfig.splashScreenOpts.frame = false;\n    xConfig.splashScreenOpts.center = true;\n    xConfig.splashScreenOpts.show = false;\n    xConfig.windowOpts.show = false;\n    const window = new BrowserWindow(xConfig.windowOpts);\n    splashScreen = new BrowserWindow(xConfig.splashScreenOpts);\n    splashScreen.loadURL(`file://${xConfig.templateUrl}`);\n    xConfig.closeWindow && splashScreen.on(\"close\", () => {\n        if (window) {\n            done || window.isDestroyed() || window.close(); // Avoid `Error: Object has been destroyed` (#25)\n        }\n    });\n    // Splashscreen is fully loaded and ready to view.\n    splashScreen.webContents.on(\"did-finish-load\", () => {\n        splashScreenReady = true;\n        showSplash();\n    });\n    // Startup is taking enough time to show a splashscreen.\n    setTimeout(() => {\n        slowStartup = true;\n        showSplash();\n    }, xConfig.delay);\n    window.webContents.on(\"did-finish-load\", (): void => {\n        closeSplashScreen(window, xConfig.minVisible);\n    });\n    return window;\n};\n/** Return object for `initDynamicSplashScreen()`. */\nexport interface DynamicSplashScreen {\n    /** The main browser window ready for loading */\n    main: BrowserWindow;\n    /** The splashscreen browser window so you can communicate with splashscreen in more complex use cases. */\n    splashScreen: Electron.BrowserWindow;\n}\n/**\n * Initializes a splashscreen that will show/hide smartly (and handle show/hiding of main window).\n * Use this function if you need to send/receive info to the splashscreen (e.g., you want to send\n * IPC messages to the splashscreen to inform the user of the app's loading state).\n * @param config - Configures splashscreen\n * @returns {DynamicSplashScreen} the main browser window and the created splashscreen\n */\nexport const initDynamicSplashScreen = (config: Config): DynamicSplashScreen => {\n    return {\n        main: initSplashScreen(config),\n        // initSplashScreen initializes splashscreen so this is a safe cast.\n        splashScreen: splashScreen as Electron.BrowserWindow,\n    };\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@trodi/electron-splashscreen\",\n  \"version\": \"1.0.2\",\n  \"description\": \"Simple splashscreen for electron applications\",\n  \"main\": \"index.js\",\n  \"types\": \"index.d.ts\",\n  \"scripts\": {\n    \"generate-api-doc\": \"typedoc --readme none --mode file --theme markdown --hideSources --excludePrivate --out api-doc/ index.ts\",\n    \"prebuild\": \"tslint --config tslint.json *.ts\",\n    \"build\": \"tsc\",\n    \"prepublish\": \"npm run build && npm run generate-api-doc\",\n    \"preexample\": \"npm run build\",\n    \"example\": \"electron examples/example.js\",\n    \"preexample-dynamic\": \"npm run build\",\n    \"example-dynamic\": \"electron examples/example-dynamic.js\"\n  },\n  \"files\": [\n    \"index.js\",\n    \"index.d.ts\"\n  ],\n  \"repository\": \"trodi/electron-splashscreen\",\n  \"keywords\": [\n    \"electron\",\n    \"splashscreen\",\n    \"splash-screen\",\n    \"loading-screen\"\n  ],\n  \"author\": \"Troy McKinnon\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/trodi/electron-splashscreen/issues\"\n  },\n  \"homepage\": \"https://github.com/trodi/electron-splashscreen#readme\",\n  \"devDependencies\": {\n    \"electron\": \"^11.0.1\",\n    \"tslint\": \"^5.7.0\",\n    \"typedoc\": \"^0.15.6\",\n    \"typedoc-plugin-markdown\": \"^2.2.16\",\n    \"typescript\": \"^3.7.4\"\n  }\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    /* Basic Options */\n    \"target\": \"es5\",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */\n    \"module\": \"commonjs\",                     /* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */\n    // \"lib\": [],                             /* Specify library files to be included in the compilation:  */\n    // \"allowJs\": true,                       /* Allow javascript files to be compiled. */\n    // \"checkJs\": true,                       /* Report errors in .js files. */\n    // \"jsx\": \"preserve\",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */\n    \"declaration\": true,                   /* Generates corresponding '.d.ts' file. */\n    // \"sourceMap\": true,                     /* Generates corresponding '.map' file. */\n    // \"outFile\": \"./\",                       /* Concatenate and emit output to single file. */\n    // \"outDir\": \"./\",                        /* Redirect output structure to the directory. */\n    // \"rootDir\": \"./\",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */\n    // \"removeComments\": true,                /* Do not emit comments to output. */\n    // \"noEmit\": true,                        /* Do not emit outputs. */\n    // \"importHelpers\": true,                 /* Import emit helpers from 'tslib'. */\n    // \"downlevelIteration\": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */\n    // \"isolatedModules\": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */\n\n    /* Strict Type-Checking Options */\n    \"strict\": true                            /* Enable all strict type-checking options. */\n    // \"noImplicitAny\": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */\n    // \"strictNullChecks\": true,              /* Enable strict null checks. */\n    // \"noImplicitThis\": true,                /* Raise error on 'this' expressions with an implied 'any' type. */\n    // \"alwaysStrict\": true,                  /* Parse in strict mode and emit \"use strict\" for each source file. */\n\n    /* Additional Checks */\n    // \"noUnusedLocals\": true,                /* Report errors on unused locals. */\n    // \"noUnusedParameters\": true,            /* Report errors on unused parameters. */\n    // \"noImplicitReturns\": true,             /* Report error when not all code paths in function return a value. */\n    // \"noFallthroughCasesInSwitch\": true,    /* Report errors for fallthrough cases in switch statement. */\n\n    /* Module Resolution Options */\n    // \"moduleResolution\": \"node\",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */\n    // \"baseUrl\": \"./\",                       /* Base directory to resolve non-absolute module names. */\n    // \"paths\": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */\n    // \"rootDirs\": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */\n    // \"typeRoots\": [],                       /* List of folders to include type definitions from. */\n    // \"types\": [],                           /* Type declaration files to be included in compilation. */\n    // \"allowSyntheticDefaultImports\": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */\n    // \"preserveSymlinks\": true,              /* Do not resolve the real path of symlinks. */\n\n    /* Source Map Options */\n    // \"sourceRoot\": \"./\",                    /* Specify the location where debugger should locate TypeScript files instead of source locations. */\n    // \"mapRoot\": \"./\",                       /* Specify the location where debugger should locate map files instead of generated locations. */\n    // \"inlineSourceMap\": true,               /* Emit a single file with source maps instead of having a separate file. */\n    // \"inlineSources\": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */\n\n    /* Experimental Options */\n    // \"experimentalDecorators\": true,        /* Enables experimental support for ES7 decorators. */\n    // \"emitDecoratorMetadata\": true,         /* Enables experimental support for emitting type metadata for decorators. */\n  }\n}"
  },
  {
    "path": "tslint.json",
    "content": "{\n    \"defaultSeverity\": \"error\",\n    \"extends\": [\n        \"tslint:recommended\"\n    ],\n    \"jsRules\": {},\n    \"rules\": {\n        \"object-literal-sort-keys\": false,\n        \"interface-name\": false,\n        \"no-unused-expression\": false\n    },\n    \"rulesDirectory\": []\n}"
  }
]