diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..2193baf
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,32 @@
+{
+ "root": true,
+ "env": {
+ "browser": true,
+ "es2021": true
+ },
+ "extends": "eslint:recommended",
+ "parserOptions": {
+ "sourceType": "module",
+ "ecmaVersion": 12
+ },
+ "rules": {
+ "indent": [
+ "error",
+ 2
+ ],
+ "no-unused-vars": [
+ "error",
+ {
+ "args": "none"
+ }
+ ],
+ "quotes": [
+ "error",
+ "double"
+ ],
+ "semi": [
+ "error",
+ "always"
+ ]
+ }
+}
diff --git a/.gitignore b/.gitignore
index 5148e52..99f2ed6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,3 +35,6 @@ jspm_packages
# Optional REPL history
.node_repl_history
+
+# Parcel
+.parcel-cache
diff --git a/.jshintrc b/.jshintrc
deleted file mode 100644
index 91f833d..0000000
--- a/.jshintrc
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "undef": true,
- "unused": "vars",
- "browser": true,
- "node": true,
- "eqnull": true,
- "esnext": true,
- "indent": 4
-}
diff --git a/README.md b/README.md
index bf400af..604b590 100644
--- a/README.md
+++ b/README.md
@@ -4,104 +4,114 @@
![Electron Tab Demo](screenshot.jpg)
+## Features
+
+* :electron: Compatible with Electron ≥ 17.
+* :lock: Compliant with [Electron security recommendations](https://www.electronjs.org/docs/latest/tutorial/security) (works without `nodeIntegration: true`).
+* :toolbox: Written with TypeScript and Web Components.
+* :hand: Supports drag and drop out of the box.
+* :art: Easily customizable.
+
## Installation
-```
-$ npm install --save electron-tabs
+```bash
+npm install --save electron-tabs
```
-## Demo
+## Getting started
-```
-$ npm run demo
-```
-
-## Usage
-
-Electron-tabs uses webviews, so you first need to use the following `webPreferences` options in the main process:
+Define the following `webPreferences` options in the main process:
```js
const mainWindow = new electron.BrowserWindow({
webPreferences: {
- nodeIntegration: true,
- contextIsolation: false, // needed for Electron >= 12.x
webviewTag: true
}
});
```
-Then add the following elements to the app page:
+Then add the following markup where you want the tabs to display:
```html
-
-
-
-
-
+
+
+
```
-And call the module in the renderer process:
+## Options
-```javascript
-const TabGroup = require("electron-tabs");
-```
-
-Now you can initialize a tab group and add tabs to it:
-
-```javascript
-let tabGroup = new TabGroup();
-let tab = tabGroup.addTab({
- title: "Electron",
- src: "http://electron.atom.io",
- visible: true
-});
-```
-
-If you don't want to write your own styles, you can also insert the sample electron-tabs stylesheet in the page header:
+You can add options by setting `` element attributes:
```html
-
+
```
-### Note
+The following attributes are supported:
-Please note, there is a known issue in some versions of Electron that prevents the process to completely shut down and it remains hanging in Background Processes (Windows 10). If you encounter that issue please use the workaround provided at https://github.com/electron/electron/issues/13939
+* `close-button-text` (string): text of the tabs "Close" button.
+* `new-tab-button` (boolean): set it to true to display the "New Tab" button.
+* `new-tab-button-text` (string): text of the "New Tab" button.
+* `sortable` (boolean): set it to true to make the tabs sortable by drag and drop.
+* `visibility-threshold` (number): the minimum number of tabs necessary for the tab bar to be displayed. 0 (default) means that it will always remain visible.
-## API
+## Methods
-### Tab Group
+Use `TabGroup` methods and manipulate tabs in a script after calling `electron-tabs.js`.
-Represents the main tab container.
+```html
+
-#### `new TabGroup(options)`
+
-`options` must be an object. The following options are available:
+
+```
+
+### TabGroup
#### `tabGroup.addTab(options)`
-Add a new tab to the tab group and returns a `Tab` instance.
+Add a new tab and returns the related `Tab` instance.
* `title`: tab title.
* `src`: URL to the page which will be loaded into the view. This is actually the same than `options.webview.src`.
-* `badge`: optional text to put into a badge, badge will be hidden if it's falsey
+* `badge`: optional text to put into a badge, badge will be hidden if false.
* `iconURL`: optional URL to the tab icon.
* `icon`: optional code for a tab icon. Can be used with symbol libraries (example with Font Awesome: `icon: 'fa fa-icon-name'`). This attribute is ignored if an `iconURL` was given.
* `closable` (default: `true`): if set to `true` the close button won't be displayed and the user won't be able to close the tab. See also `tab.close()`.
-* `webviewAttributes`: attributes to add to the webview tag. See [webview documentation](http://electron.atom.io/docs/api/web-view-tag/#tag-attributes).
* `visible` (default: `true`): set this to `false` if you don't want to display the tab once it is loaded. If set to `false` then you will need to call `tab.show()` to display the tab.
* `active` (default: `false`): set this to `true` if you want to activate the tab once it is loaded. Otherwise you will need to call `tab.activate()`.
* `ready`: a callback function to call once the tab is ready. The `Tab` instance is passed as the only parameter.
+* `webviewAttributes`: attributes to add to the webview tag. See [webview documentation](http://electron.atom.io/docs/api/web-view-tag/#tag-attributes).
+
+### `tabGroup.setDefaultTab(options)`
+
+Define default options to use for creating the tab when the "New Tab" button is clicked or when calling `tabGroup.addTab()` with no parameter.
+
+```javascript
+tabGroup.setDefaultTab({
+ title: "New Page",
+ src: "path/to/new-page.html",
+ active: true
+});
+```
#### `tabGroup.getTab(id)`
@@ -123,17 +133,17 @@ To get the tab in the rightmost position:
tabGroup.getTabByPosition(-1);
```
-> Note: Position 0 does not contain a tab.
-
#### `tabGroup.getTabByRelPosition(position)`
Retrieve an instance of `Tab` from this `position` relative to the active tab (return `null` if not found).
+
`tabGroup.getNextTab()` is an alias to `tabGroup.getTabByRelPosition(1)`.
+
`tabGroup.getPreviousTab()` is an alias to `tabGroup.getTabByRelPosition(-1)`.
#### `tabGroup.getActiveTab()`
-Return the currently active tab (otherwise return `null`).
+Return the active tab (return `null` if none).
#### `tabGroup.getTabs()`
@@ -179,7 +189,7 @@ Get current tab icon URL / icon.
#### `tab.setPosition(newPosition)`
-Move tab to the specified position. If `position` is 0 then `null` is returned and nothing happens. See [`tabGroup.getTabByPosition`](#tabgroupgettabbypositionposition) for information about positions.
+Move tab to the specified position. See [`tabGroup.getTabByPosition`](#tabgroupgettabbypositionposition) for information about positions.
#### `tab.getPosition(fromRight)`
@@ -193,30 +203,17 @@ Activate this tab. The class "active" is added to the active tab.
Toggle the "visible" class on the tab. `tab.hide()` is an alias to `tab.show(false)`.
-#### `tab.flash(flag)`
-
-Toggle the "flash" class on the tab. `tab.unflash()` is an alias to `tab.flash(false)`.
-
#### `tab.hasClass(classname)`
-Return `true` if the tab element has the specified classname. Useful for checking if a tab is "active", "visible" of "flash".
+Return `true` if the tab element has the specified classname. Useful for checking if a tab is "active" or "visible".
#### `tab.close(force)`
Close the tab (and activate another tab if relevant). When `force` is set to `true` the tab will be closed even if it is not `closable`.
-### Access webview element
+## Events
-You can access the webview element and use its methods with through the `Tab.webview` attribute. See [webview documentation](https://electronjs.org/docs/api/webview-tag#methods).
-
-```javascript
-let webview = tab.webview;
-webview.loadURL("file://path/to/new/page.html");
-```
-
-### Events
-
-The following events are available:
+The following events are emitted:
* `tabGroup.on("tab-added", (tab, tabGroup) => { ... });`
* `tabGroup.on("tab-removed", (tab, tabGroup) => { ... });`
@@ -230,8 +227,6 @@ The following events are available:
* `tab.on("inactive", (tab) => { ... });`
* `tab.on("visible", (tab) => { ... });`
* `tab.on("hidden", (tab) => { ... });`
-* `tab.on("flash", (tab) => { ... });`
-* `tab.on("unflash", (tab) => { ... });`
* `tab.on("close", (tab) => { ... });`
* `tab.on("closing", (tab, abort) => { ... });` (Use `abort()` function to cancel closing)
@@ -240,37 +235,100 @@ You can also use `tab.once` to automatically remove the listener when invoked:
* `tab.once("webview-ready", (tab) => { ... });`
* `tab.once("webview-dom-ready", (tab) => { ... });`
-## Drag and drop support
+## Access Electron webview element
-Electron-tabs is compatible with [Dragula](https://github.com/bevacqua/dragula) so you can easily make your tabs draggable.
-
-Install Dragula:
-
-```
-npm install dragula --save
-```
-
-Don't forget to add a link to its stylesheet in the header:
-
-```html
-
-```
-
-Then call Dragula in your script once tabGroup is ready:
+You can access the webview element and use its methods with through the `Tab.webview` attribute. See [webview documentation](https://electronjs.org/docs/api/webview-tag#methods).
```javascript
-const TabGroup = require("electron-tabs");
-const dragula = require("dragula");
+let webview = tab.webview;
+webview.loadURL("file://path/to/new/page.html");
+```
-var tabGroup = new TabGroup({
- ready: function (tabGroup) {
- dragula([tabGroup.tabContainer], {
- direction: "horizontal"
- });
- }
-});
+## Custom styles
+
+To customize tab-group styles, set new values to [electron-tabs CSS variables](https://github.com/brrd/electron-tabs/blob/master/src/style.css) in your application stylesheet.
+
+Since `TabGroup` is a Web Component you won't be able to change its styles directly from your app stylesheet. If you need more control over it then you can add a `
+
+```
+
+This method is particularly useful when you need to define custom badges or tab styles:
+
+```html
+
+
+
+
+
+
+
+```
+
+## Development
+
+`electron-tabs` uses TypeScript and Parcel under the hood.
+
+### Requirements
+
+Git and Node 12+.
+
+### Build
+
+```bash
+# Clone this repo
+git clone git@github.com:brrd/electron-tabs.git
+cd electron-tabs
+
+# Install dependencies
+npm install
+
+# Build
+npm run build
+
+# ...or watch
+npm run watch
+```
+
+### Demo
+
+```bash
+npm run demo
```
## License
-The MIT License (MIT) - Copyright (c) 2016 Thomas Brouard
+The MIT License (MIT) - Copyright (c) 2022 Thomas Brouard
diff --git a/declarations.d.ts b/declarations.d.ts
new file mode 100644
index 0000000..cbe652d
--- /dev/null
+++ b/declarations.d.ts
@@ -0,0 +1 @@
+declare module "*.css";
diff --git a/demo/app.js b/demo/app.js
index d9763cb..575222f 100644
--- a/demo/app.js
+++ b/demo/app.js
@@ -1,16 +1,14 @@
-const electron = require('electron');
+const electron = require("electron");
const app = electron.app;
-app.on('ready', function () {
+app.on("ready", function () {
const mainWindow = new electron.BrowserWindow({
webPreferences: {
- nodeIntegration: true,
- contextIsolation: false,
webviewTag: true
}
});
- mainWindow.loadURL('file://' + __dirname + '/electron-tabs.html');
- mainWindow.on('ready-to-show', function () {
+ mainWindow.loadURL("file://" + __dirname + "/electron-tabs.html");
+ mainWindow.on("ready-to-show", function () {
mainWindow.show();
mainWindow.focus();
});
diff --git a/demo/electron-tabs.html b/demo/electron-tabs.html
index 5a4944a..ec9c68f 100644
--- a/demo/electron-tabs.html
+++ b/demo/electron-tabs.html
@@ -3,39 +3,58 @@
electron-tabs-demo
-
-