diff --git a/package-lock.json b/package-lock.json
index 260f9d94..bbef1433 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8749,6 +8749,11 @@
"integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=",
"dev": true
},
+ "elix": {
+ "version": "14.1.1",
+ "resolved": "https://registry.npmjs.org/elix/-/elix-14.1.1.tgz",
+ "integrity": "sha512-o+6YAp1qhn0Itz2LzEAQtzi9se43eiXdrdSVvXpTrj3bsp4p/c1bY6VVeYfdaJy9a8QRnMkH9WrLGdFbRcFsuA=="
+ },
"elliptic": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
diff --git a/package.json b/package.json
index 077db4d1..08605255 100644
--- a/package.json
+++ b/package.json
@@ -137,6 +137,7 @@
"@babel/polyfill": "^7.12.1",
"canvg": "^3.0.7",
"core-js": "^3.6.5",
+ "elix": "^14.1.1",
"jspdf": "^2.1.1",
"pathseg": "^1.2.0",
"regenerator-runtime": "^0.13.7",
diff --git a/src/editor/components/index.js b/src/editor/components/index.js
index 8fe64017..177494d9 100644
--- a/src/editor/components/index.js
+++ b/src/editor/components/index.js
@@ -1,2 +1,3 @@
import './seButton.js';
import './seFlyingButton.js';
+import './seExplorerButton.js';
diff --git a/src/editor/components/seExplorerButton.js b/src/editor/components/seExplorerButton.js
new file mode 100644
index 00000000..9b5a5cfc
--- /dev/null
+++ b/src/editor/components/seExplorerButton.js
@@ -0,0 +1,248 @@
+const template = document.createElement('template');
+template.innerHTML = `
+
+
+
+
+
+
+
+`;
+/**
+ * @class ExplorerButton
+ */
+export class ExplorerButton extends HTMLElement {
+ /**
+ * @function constructor
+ */
+ constructor () {
+ super();
+ // create the shadowDom and insert the template
+ this._shadowRoot = this.attachShadow({mode: 'open'});
+ this._shadowRoot.appendChild(template.content.cloneNode(true));
+ // locate the component
+ this.$button = this._shadowRoot.querySelector('.menu-button');
+ this.$overall = this._shadowRoot.querySelector('.overall');
+ this.$img = this._shadowRoot.querySelector('img');
+ this.$menu = this._shadowRoot.querySelector('.menu');
+ }
+ /**
+ * @function observedAttributes
+ * @returns {any} observed
+ */
+ static get observedAttributes () {
+ return ['title', 'pressed', 'disabled'];
+ }
+ /**
+ * @function attributeChangedCallback
+ * @param {string} name
+ * @param {string} oldValue
+ * @param {string} newValue
+ * @returns {void}
+ */
+ attributeChangedCallback (name, oldValue, newValue) {
+ if (oldValue === newValue) return;
+ switch (name) {
+ case 'title':
+ {
+ const shortcut = this.getAttribute('shortcut');
+ this.$button.setAttribute('title', `${newValue} [${shortcut}]`);
+ }
+ break;
+ case 'pressed':
+ if (newValue) {
+ this.$overall.classList.add('pressed');
+ } else {
+ this.$overall.classList.remove('pressed');
+ }
+ break;
+ case 'disabled':
+ if (newValue) {
+ this.$div.classList.add('disabled');
+ } else {
+ this.$div.classList.remove('disabled');
+ }
+ break;
+ default:
+ // eslint-disable-next-line no-console
+ console.error(`unknown attribute: ${name}`);
+ break;
+ }
+ }
+ /**
+ * @function get
+ * @returns {any}
+ */
+ get title () {
+ return this.getAttribute('title');
+ }
+
+ /**
+ * @function set
+ * @returns {void}
+ */
+ set title (value) {
+ this.setAttribute('title', value);
+ }
+ /**
+ * @function get
+ * @returns {any}
+ */
+ get pressed () {
+ return this.hasAttribute('pressed');
+ }
+
+ /**
+ * @function set
+ * @returns {void}
+ */
+ set pressed (value) {
+ // boolean value => existence = true
+ if (value) {
+ this.setAttribute('pressed', 'true');
+ } else {
+ this.removeAttribute('pressed', '');
+ }
+ }
+ /**
+ * @function get
+ * @returns {any}
+ */
+ get disabled () {
+ return this.hasAttribute('disabled');
+ }
+
+ /**
+ * @function set
+ * @returns {void}
+ */
+ set disabled (value) {
+ // boolean value => existence = true
+ if (value) {
+ this.setAttribute('disabled', 'true');
+ } else {
+ this.removeAttribute('disabled', '');
+ }
+ }
+ /**
+ * @function connectedCallback
+ * @returns {void}
+ */
+ connectedCallback () {
+ // capture click event on the button to manage the logic
+ const onClickHandler = (ev) => {
+ console.log(ev);
+ switch (ev.target.nodeName) {
+ case 'SE-EXPLORERBUTTON':
+ this.$menu.classList.add('open');
+ break;
+ case 'SE-BUTTON':
+ // change to the current action
+ this.$img.setAttribute('src', ev.target.getAttribute('src'));
+ this.currentAction = ev.target;
+ this.setAttribute('pressed', 'pressed');
+ // and close the menu
+ this.$menu.classList.remove('open');
+ break;
+ default:
+ // eslint-disable-next-line no-console
+ console.error('unkonw nodeName for:', ev.target, ev.target.className);
+ }
+ };
+ // capture event from slots
+ this.addEventListener('click', onClickHandler);
+ }
+}
+
+// Register
+customElements.define('se-explorerbutton', ExplorerButton);
diff --git a/src/editor/components/seFlyingButton.js b/src/editor/components/seFlyingButton.js
index 4d3ee83a..8f20edbe 100644
--- a/src/editor/components/seFlyingButton.js
+++ b/src/editor/components/seFlyingButton.js
@@ -239,17 +239,3 @@ export class FlyingButton extends HTMLElement {
// Register
customElements.define('se-flyingbutton', FlyingButton);
-/*
-
-
-
-
- */
diff --git a/src/editor/index.html b/src/editor/index.html
index 8a8c2aed..82a665cf 100644
--- a/src/editor/index.html
+++ b/src/editor/index.html
@@ -400,7 +400,7 @@
-
+