yy-menu
Version:
A traditional menu system for web apps inspired by Electron
1,737 lines (1,487 loc) • 51.6 kB
JavaScript
// modules are defined as an array
// [ module function, map of requires ]
//
// map of requires is short require name -> numeric require
//
// anything defined in a previous bundle is accessed via the
// orig method which is the require for previous bundles
parcelRequire = (function (modules, cache, entry, globalName) {
// Save the require from previous bundle to this closure if any
var previousRequire = typeof parcelRequire === 'function' && parcelRequire;
var nodeRequire = typeof require === 'function' && require;
function newRequire(name, jumped) {
if (!cache[name]) {
if (!modules[name]) {
// if we cannot find the module within our internal map or
// cache jump to the current global require ie. the last bundle
// that was added to the page.
var currentRequire = typeof parcelRequire === 'function' && parcelRequire;
if (!jumped && currentRequire) {
return currentRequire(name, true);
}
// If there are other bundles on this page the require from the
// previous one is saved to 'previousRequire'. Repeat this as
// many times as there are bundles until the module is found or
// we exhaust the require chain.
if (previousRequire) {
return previousRequire(name, true);
}
// Try the node require function if it exists.
if (nodeRequire && typeof name === 'string') {
return nodeRequire(name);
}
var err = new Error('Cannot find module \'' + name + '\'');
err.code = 'MODULE_NOT_FOUND';
throw err;
}
localRequire.resolve = resolve;
localRequire.cache = {};
var module = cache[name] = new newRequire.Module(name);
modules[name][0].call(module.exports, localRequire, module, module.exports, this);
}
return cache[name].exports;
function localRequire(x){
return newRequire(localRequire.resolve(x));
}
function resolve(x){
return modules[name][1][x] || x;
}
}
function Module(moduleName) {
this.id = moduleName;
this.bundle = newRequire;
this.exports = {};
}
newRequire.isParcelRequire = true;
newRequire.Module = Module;
newRequire.modules = modules;
newRequire.cache = cache;
newRequire.parent = previousRequire;
newRequire.register = function (id, exports) {
modules[id] = [function (require, module) {
module.exports = exports;
}, {}];
};
var error;
for (var i = 0; i < entry.length; i++) {
try {
newRequire(entry[i]);
} catch (e) {
// Save first error but execute all entries
if (!error) {
error = e;
}
}
}
if (entry.length) {
// Expose entry point to Node, AMD or browser globals
// Based on https://github.com/ForbesLindesay/umd/blob/master/template.js
var mainExports = newRequire(entry[entry.length - 1]);
// CommonJS
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = mainExports;
// RequireJS
} else if (typeof define === "function" && define.amd) {
define(function () {
return mainExports;
});
// <script>
} else if (globalName) {
this[globalName] = mainExports;
}
}
// Override the current require with this new one
parcelRequire = newRequire;
if (error) {
// throw error from earlier, _after updating parcelRequire_
throw error;
}
return newRequire;
})({"../src/config.js":[function(require,module,exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.config = void 0;
var config = {
/**
* application menu container styles
* @type {object}
*/
ApplicationContainerStyle: {
'z-index': 999999,
'position': 'absolute',
'top': 0,
'left': 0,
'user-select': 'none',
'font-size': '0.85em'
},
/**
* application menu-bar styles
* @type {object}
*/
ApplicationMenuStyle: {
'display': 'flex',
'position': 'relative',
'flex-direction': 'row',
'color': 'black',
'backgroundColor': 'rgb(230,230,230)',
'width': '100vw',
'border': 'none',
'box-shadow': 'unset',
'outline': 'none'
},
/**
* application menu entry styles
* @type {object}
*/
ApplicationMenuRowStyle: {
'padding': '0.25em 0.5em',
'margin': 0,
'line-height': '1em'
},
/**
* lower-level menu window styles
* @type {object}
*/
MenuStyle: {
'flex-direction': 'column',
'position': 'absolute',
'user-select': 'none',
'color': 'black',
'z-index': 999999,
'backgroundColor': 'white',
'border': '1px solid rgba(0,0,0,0.5)',
'boxShadow': '1px 3px 3px rgba(0,0,0,0.25)'
},
/**
* lower-level menu row styles
* @type {object}
*/
RowStyle: {
'display': 'flex',
'padding': '0.25em 1.5em 0.25em',
'line-height': '1.5em'
},
/**
* lower-level menu accelerator styles
* @type {object}
*/
AcceleratorStyle: {
'opacity': 0.5
},
/**
* lower-level menu separator styles
* @type {object}
*/
SeparatorStyle: {
'border-bottom': '1px solid rgba(0,0,0,0.1)',
'margin': '0.5em 0'
},
/**
* accelerator key styles
* NOTE: accelerator keys must use text-decoration as its used as a toggle in the code
* @type {object}
*/
AcceleratorKeyStyle: {
'text-decoration': 'underline',
'text-decoration-color': 'rgba(0,0,0,0.5)'
},
/**
* minimum column width in pixels for checked and arrow in the lower-level menus
* @type {number}
*/
MinimumColumnWidth: 20,
/**
* CSS background style for selected MenuItems
* NOTE: unselected have 'transparent' style
* @type {string}
*/
SelectedBackgroundStyle: 'rgba(0,0,0,0.1)',
/**
* number of pixels to overlap child menus
* @type {number}
*/
Overlap: 5,
/**
* time in milliseconds to wait for submenu to open when mouse hovers
* @param {number}
*/
SubmenuOpenDelay: 500
};
exports.config = config;
},{}],"../src/html.js":[function(require,module,exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.html = html;
function html(options) {
options = options || {};
var object = document.createElement(options.type || 'div');
if (options.parent) {
options.parent.appendChild(object);
}
if (options.styles) {
for (var style in options.styles) {
object.style[style] = options.styles[style];
}
}
if (options.html) {
object.innerHTML = options.html;
}
return object;
}
},{}],"../src/localAccelerator.js":[function(require,module,exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.localAccelerator = void 0;
function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
/**
* Handles all keyboard input for the menu and user-registered keys
*/
var localAccelerator = {
init: function init() {
if (!localAccelerator.menuKeys) {
localAccelerator.menuKeys = {};
localAccelerator.keys = {};
document.body.addEventListener('keydown', function (e) {
return localAccelerator.keydown(localAccelerator, e);
});
document.body.addEventListener('keyup', function (e) {
return localAccelerator.keyup(localAccelerator, e);
});
}
},
/**
* clear all user-registered keys
*/
clearKeys: function clearKeys() {
localAccelerator.keys = {};
},
/**
* Register a shortcut key for use by an open menu
* @param {KeyCodes} letter
* @param {MenuItem} menuItem
* @param {boolean} applicationMenu
* @private
*/
registerMenuShortcut: function registerMenuShortcut(letter, menuItem) {
if (letter) {
var keyCode = (menuItem.menu.applicationMenu ? 'alt+' : '') + letter;
localAccelerator.menuKeys[localAccelerator.prepareKey(keyCode)] = function (e) {
menuItem.handleClick(e);
e.stopPropagation();
e.preventDefault();
};
}
},
/**
* Register special shortcut keys for menu
* @param {MenuItem} menuItem
* @private
*/
registerMenuSpecial: function registerMenuSpecial(menu) {
localAccelerator.menuKeys['escape'] = function () {
return menu.closeAll();
};
localAccelerator.menuKeys['enter'] = function (e) {
return menu.enter(e);
};
localAccelerator.menuKeys['space'] = function (e) {
return menu.enter(e);
};
localAccelerator.menuKeys['arrowright'] = function (e) {
return menu.move(e, 'right');
};
localAccelerator.menuKeys['arrowleft'] = function (e) {
return menu.move(e, 'left');
};
localAccelerator.menuKeys['arrowup'] = function (e) {
return menu.move(e, 'up');
};
localAccelerator.menuKeys['arrowdown'] = function (e) {
return menu.move(e, 'down');
};
},
/**
* special key registration for alt
* @param {function} pressed
* @param {function} released
* @private
*/
registerAlt: function registerAlt(pressed, released) {
localAccelerator.alt = {
pressed: pressed,
released: released
};
},
/**
* Removes menu shortcuts
* @private
*/
unregisterMenuShortcuts: function unregisterMenuShortcuts() {
localAccelerator.menuKeys = {};
},
/**
* Keycodes definition. In the form of modifier[+modifier...]+key
* <p>For example: ctrl+shift+e</p>
* <p>KeyCodes are case insensitive (i.e., shift+a is the same as Shift+A). And spaces are removed</p>
* <p>You can assign more than one key to the same shortcut by using a | between the keys (e.g., 'shift+a | ctrl+a')</p>
* <pre>
* Modifiers:
* ctrl, alt, shift, meta, (ctrl aliases: command, control, commandorcontrol)
* </pre>
* <pre>
* Keys:
* escape, 0-9, minus, equal, backspace, tab, a-z, backetleft, bracketright, semicolon, quote,
* backquote, backslash, comma, period, slash, numpadmultiply, space, capslock, f1-f24, pause,
* scrolllock, printscreen, home, arrowup, arrowleft, arrowright, arrowdown, pageup, pagedown,
* end, insert, delete, enter, shiftleft, shiftright, ctrlleft, ctrlright, altleft, altright, shiftleft,
* shiftright, numlock, numpad...
* </pre>
* For OS-specific codes and a more detailed explanation see {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code}. Also note that 'Digit' and 'Key' are removed from the code to make it easier to type.
*
* @typedef {string} localAccelerator~KeyCodes
*/
/**
* translate a user-provided keycode
* @param {KeyCodes} keyCode
* @return {KeyCodes} formatted and sorted keyCode
* @private
*/
prepareKey: function prepareKey(keyCode) {
var keys = [];
var split;
keyCode += '';
if (keyCode.length > 1 && keyCode.indexOf('|') !== -1) {
split = keyCode.split('|');
} else {
split = [keyCode];
}
var _iterator = _createForOfIteratorHelper(split),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var code = _step.value;
var key = '';
var modifiers = [];
code = code.toLowerCase().replace(' ', '');
if (code.indexOf('+') !== -1) {
var _split = code.split('+');
for (var i = 0; i < _split.length - 1; i++) {
var modifier = _split[i];
modifier = modifier.replace('commandorcontrol', 'ctrl');
modifier = modifier.replace('command', 'ctrl');
modifier = modifier.replace('control', 'ctrl');
modifiers.push(modifier);
}
modifiers = modifiers.sort(function (a, b) {
return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0;
});
var _iterator2 = _createForOfIteratorHelper(modifiers),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var part = _step2.value;
key += part + '+';
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
key += _split[_split.length - 1];
} else {
key = code;
}
keys.push(key);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return keys;
},
/**
* Make the KeyCode pretty for printing on the menu
* @param {KeyCode} keyCode
* @return {string}
* @private
*/
prettifyKey: function prettifyKey(keyCode) {
var key = '';
var codes = localAccelerator.prepareKey(keyCode);
for (var i = 0; i < codes.length; i++) {
var _keyCode = codes[i];
if (_keyCode.indexOf('+') !== -1) {
var split = _keyCode.toLowerCase().split('+');
for (var _i = 0; _i < split.length - 1; _i++) {
var modifier = split[_i];
key += modifier[0].toUpperCase() + modifier.substr(1) + '+';
}
key += split[split.length - 1].toUpperCase();
} else {
key = _keyCode.toUpperCase();
}
if (i !== codes.length - 1) {
key += ' or ';
}
}
return key;
},
/**
* register a key as a global accelerator
* @param {KeyCodes} keyCode (e.g., Ctrl+shift+E)
* @param {function} callback
*/
register: function register(keyCode, callback) {
var keys = localAccelerator.prepareKey(keyCode);
var _iterator3 = _createForOfIteratorHelper(keys),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var key = _step3.value;
localAccelerator.keys[key] = function (e) {
callback(e);
e.preventDefault();
e.stopPropagation();
};
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
},
keyup: function keyup(accelerator, e) {
if (localAccelerator.alt && (e.code === 'AltLeft' || e.code === 'AltRight')) {
localAccelerator.alt.released();
localAccelerator.alt.isPressed = false;
}
},
keydown: function keydown(accelerator, e) {
if (localAccelerator.alt && !localAccelerator.alt.isPressed && (e.code === 'AltLeft' || e.code === 'AltRight')) {
localAccelerator.alt.pressed();
localAccelerator.alt.isPressed = true;
e.preventDefault();
}
var modifiers = [];
if (e.altKey) {
modifiers.push('alt');
}
if (e.ctrlKey) {
modifiers.push('ctrl');
}
if (e.metaKey) {
modifiers.push('meta');
}
if (e.shiftKey) {
modifiers.push('shift');
}
var keyCode = '';
for (var _i2 = 0, _modifiers = modifiers; _i2 < _modifiers.length; _i2++) {
var modifier = _modifiers[_i2];
keyCode += modifier + '+';
}
var translate = e.code.toLowerCase();
translate = translate.replace('digit', '');
translate = translate.replace('key', '');
keyCode += translate;
if (localAccelerator.menuKeys[keyCode]) {
localAccelerator.menuKeys[keyCode](e, localAccelerator);
} else if (localAccelerator.keys[keyCode]) {
localAccelerator.keys[keyCode](e, localAccelerator);
}
}
};
exports.localAccelerator = localAccelerator;
},{}],"../src/MenuItem.js":[function(require,module,exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MenuItem = void 0;
var _html = require("./html");
var _config = require("./config");
var _localAccelerator = require("./localAccelerator");
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var MenuItem = /*#__PURE__*/function () {
/**
* @param {object} options
* @param {string} [options.label] label for menu entry may include accelerator by placing & before letter)
* @param {string} [options.type] separator, checkbox, or undefined
* @param {object} [options.styles] additional CSS styles to apply to this MenuItem
* @param {string} [options.accelerator] see Accelerator for inputs (e.g., ctrl+shift+A)
* @param {MenuItem} [options.submenu] attaches a submenu (and changes type to submenu)
* @param {boolean} [options.checked] check the checkbox
*/
function MenuItem(options) {
var _this = this;
_classCallCheck(this, MenuItem);
_localAccelerator.localAccelerator.init();
options = options || {};
this.styles = options.styles;
this.div = (0, _html.html)();
this.type = options.type;
this.click = options.click;
if (this.type === 'separator') {
this.applyConfig(_config.config.SeparatorStyle);
} else {
this._checked = options.checked;
this.createChecked(options.checked);
this.text = options.label || ' ';
this.createShortcut();
this.createAccelerator(options.accelerator);
this.createSubmenu(options.submenu);
if (options.submenu) {
this.submenu = options.submenu;
this.submenu.applyConfig(_config.config.MenuStyle);
}
this.applyConfig(_config.config.RowStyle);
this.div.addEventListener('mousedown', function (e) {
return _this.handleClick(e);
});
this.div.addEventListener('touchstart', function (e) {
return _this.handleClick(e);
});
this.div.addEventListener('mouseenter', function () {
return _this.mouseenter();
});
this.div.addEventListener('mouseleave', function () {
return _this.mouseleave();
});
}
}
/**
* The click callback
* @callback MenuItem~ClickCallback
* @param {InputEvent} e
*/
_createClass(MenuItem, [{
key: "mouseenter",
value: function mouseenter() {
var _this2 = this;
if (!this.submenu || this.menu.showing !== this) {
this.div.style.backgroundColor = _config.config.SelectedBackgroundStyle;
if (this.submenu && (!this.menu.applicationMenu || this.menu.showing)) {
this.submenuTimeout = setTimeout(function () {
_this2.submenuTimeout = null;
_this2.submenu.show(_this2);
}, this.menu.applicationMenu ? 0 : _config.config.SubmenuOpenDelay);
}
}
}
}, {
key: "mouseleave",
value: function mouseleave() {
if (!this.submenu || this.menu.showing !== this) {
if (this.submenuTimeout) {
clearTimeout(this.submenuTimeout);
this.submenuTimeout = null;
}
this.div.style.backgroundColor = 'transparent';
}
}
}, {
key: "applyConfig",
value: function applyConfig(base) {
var styles = {};
for (var style in base) {
styles[style] = base[style];
}
if (this.styles) {
for (var _style in this.styles) {
styles[_style] = this.styles[_style];
}
}
for (var _style2 in styles) {
this.div.style[_style2] = styles[_style2];
}
}
}, {
key: "createChecked",
value: function createChecked(checked) {
this.check = (0, _html.html)({
parent: this.div,
html: checked ? '✔' : ''
});
}
}, {
key: "createShortcut",
value: function createShortcut() {
if (this.type !== 'separator') {
var text = this.text;
this.label = (0, _html.html)({
parent: this.div
});
var current = (0, _html.html)({
parent: this.label,
type: 'span'
});
if (text.indexOf('&') !== -1) {
var i = 0;
do {
var letter = text[i];
if (letter === '&') {
i++;
this.shortcutSpan = (0, _html.html)({
parent: this.label,
type: 'span',
html: text[i],
styles: _config.config.AcceleratorKeyStyle
});
current = (0, _html.html)({
parent: this.label,
type: 'span'
});
} else {
current.innerHTML += letter;
}
i++;
} while (i < text.length);
} else {
this.label.innerHTML = text;
}
}
}
}, {
key: "showShortcut",
value: function showShortcut() {
if (this.shortcutSpan) {
this.shortcutSpan.style.textDecoration = 'underline';
}
}
}, {
key: "hideShortcut",
value: function hideShortcut() {
if (this.shortcutSpan) {
this.shortcutSpan.style.textDecoration = 'none';
}
}
}, {
key: "createAccelerator",
value: function createAccelerator(accelerator) {
var _this3 = this;
this.accelerator = (0, _html.html)({
parent: this.div,
html: accelerator ? _localAccelerator.localAccelerator.prettifyKey(accelerator) : '',
styles: _config.config.AcceleratorStyle
});
if (accelerator) {
_localAccelerator.localAccelerator.register(accelerator, function (e) {
return _this3.click(e);
});
}
}
}, {
key: "createSubmenu",
value: function createSubmenu(submenu) {
this.arrow = (0, _html.html)({
parent: this.div,
html: submenu ? '►' : ''
});
}
}, {
key: "closeAll",
value: function closeAll() {
var menu = this.menu;
_localAccelerator.localAccelerator.unregisterMenuShortcuts();
while (menu && !menu.applicationMenu) {
if (menu.showing) {
menu.showing.div.style.backgroundColor = 'transparent';
menu.showing = null;
}
menu.div.remove();
menu = menu.menu;
}
if (menu.showing) {
menu.showing.div.style.background = 'transparent';
menu.showing = null;
menu.hideAccelerators();
}
}
}, {
key: "handleClick",
value: function handleClick(e) {
if (this.submenu) {
if (this.submenuTimeout) {
clearTimeout(this.submenuTimeout);
this.submenuTimeout = null;
}
this.submenu.show(this);
this.div.style.backgroundColor = _config.config.SelectedBackgroundStyle;
if (typeof e !== 'undefined' && this.menu.applicationMenu && document.activeElement !== this.menu.div) {
this.menu.div.focus();
}
if (e) {
e.preventDefault();
}
} else if (this.type === 'checkbox') {
this.checked = !this.checked;
this.closeAll();
} else {
this.closeAll();
}
if (this.click) {
this.click(e, this);
}
}
}, {
key: "checked",
get: function get() {
return this._checked;
},
set: function set(value) {
this._checked = value;
this.check.innerHTML = this._checked ? '✔' : '';
}
}]);
return MenuItem;
}();
exports.MenuItem = MenuItem;
},{"./html":"../src/html.js","./config":"../src/config.js","./localAccelerator":"../src/localAccelerator.js"}],"../src/Menu.js":[function(require,module,exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Menu = void 0;
var _config = require("./config");
var _MenuItem = require("./MenuItem");
var _localAccelerator = require("./localAccelerator");
var _html = require("./html");
function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var _application;
var Menu = /*#__PURE__*/function () {
/**
* creates a menu bar
* @param {object} [options]
* @param {object} [options.styles] additional CSS styles for menu
*/
function Menu(options) {
_classCallCheck(this, Menu);
options = options || {};
this.div = document.createElement('div');
this.styles = options.styles;
this.children = [];
this.applyConfig(_config.config.MenuStyle);
this.div.tabIndex = -1;
}
/**
* append a MenuItem to the Menu
* @param {MenuItem} menuItem
*/
_createClass(Menu, [{
key: "append",
value: function append(menuItem) {
if (menuItem.submenu) {
menuItem.submenu.menu = this;
}
menuItem.menu = this;
this.div.appendChild(menuItem.div);
if (menuItem.type !== 'separator') {
this.children.push(menuItem);
}
}
/**
* inserts a MenuItem into the Menu
* @param {number} pos
* @param {MenuItem} menuItem
*/
}, {
key: "insert",
value: function insert(pos, menuItem) {
if (pos >= this.div.childNodes.length) {
this.append(menuItem);
} else {
if (menuItem.submenu) {
menuItem.submenu.menu = this;
}
menuItem.menu = this;
this.div.insertBefore(menuItem.div, this.div.childNodes[pos]);
if (menuItem.type !== 'separator') {
this.children.splice(pos, 0, menuItem);
}
}
}
}, {
key: "hide",
value: function hide() {
var current = this.menu.showing;
while (current && current.submenu) {
current.div.style.backgroundColor = 'transparent';
current.submenu.div.remove();
var next = current.submenu.showing;
if (next) {
current.submenu.showing.div.style.backgroundColor = 'transparent';
current.submenu.showing = null;
}
current = next;
}
}
}, {
key: "show",
value: function show(menuItem) {
_localAccelerator.localAccelerator.unregisterMenuShortcuts();
if (this.menu && this.menu.showing === menuItem) {
this.hide();
this.menu.showing = null;
this.div.remove();
this.menu.showAccelerators();
} else {
if (this.menu) {
if (this.menu.showing && this.menu.children.indexOf(menuItem) !== -1) {
this.hide();
}
this.menu.showing = menuItem;
this.menu.hideAccelerators();
}
var div = menuItem.div;
var parent = this.menu.div;
if (this.menu.applicationMenu) {
this.div.style.left = div.offsetLeft + 'px';
this.div.style.top = div.offsetTop + div.offsetHeight + 'px';
} else {
this.div.style.left = parent.offsetLeft + parent.offsetWidth - _config.config.Overlap + 'px';
this.div.style.top = parent.offsetTop + div.offsetTop - _config.config.Overlap + 'px';
}
this.attached = menuItem;
this.showAccelerators();
this.getApplicationDiv().appendChild(this.div);
var label = 0,
accelerator = 0,
arrow = 0,
checked = 0;
var _iterator = _createForOfIteratorHelper(this.children),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var child = _step.value;
child.check.style.width = 'auto';
child.label.style.width = 'auto';
child.accelerator.style.width = 'auto';
child.arrow.style.width = 'auto';
if (child.type === 'checkbox') {
checked = _config.config.MinimumColumnWidth;
}
if (child.submenu) {
arrow = _config.config.MinimumColumnWidth;
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
var _iterator2 = _createForOfIteratorHelper(this.children),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var _child = _step2.value;
var childLabel = _child.label.offsetWidth * 2;
label = childLabel > label ? childLabel : label;
var childAccelerator = _child.accelerator.offsetWidth;
accelerator = childAccelerator > accelerator ? childAccelerator : accelerator;
if (_child.submenu) {
arrow = _child.arrow.offsetWidth;
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
var _iterator3 = _createForOfIteratorHelper(this.children),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var _child2 = _step3.value;
_child2.check.style.width = checked + 'px';
_child2.label.style.width = label + 'px';
_child2.accelerator.style.width = accelerator + 'px';
_child2.arrow.style.width = arrow + 'px';
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
if (this.div.offsetLeft + this.div.offsetWidth > window.innerWidth) {
this.div.style.left = window.innerWidth - this.div.offsetWidth + 'px';
}
if (this.div.offsetTop + this.div.offsetHeight > window.innerHeight) {
this.div.style.top = window.innerHeight - this.div.offsetHeight + 'px';
}
_application.menu.div.focus();
}
}
}, {
key: "applyConfig",
value: function applyConfig(base) {
var styles = {};
for (var style in base) {
styles[style] = base[style];
}
if (this.styles) {
for (var _style in this.styles) {
styles[_style] = this.styles[_style];
}
}
for (var _style2 in styles) {
this.div.style[_style2] = styles[_style2];
}
}
}, {
key: "showAccelerators",
value: function showAccelerators() {
var _iterator4 = _createForOfIteratorHelper(this.children),
_step4;
try {
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
var child = _step4.value;
child.showShortcut();
if (child.type !== 'separator') {
var index = child.text.indexOf('&');
if (index !== -1) {
_localAccelerator.localAccelerator.registerMenuShortcut(child.text[index + 1], child);
}
}
}
} catch (err) {
_iterator4.e(err);
} finally {
_iterator4.f();
}
if (!this.applicationMenu) {
_localAccelerator.localAccelerator.registerMenuSpecial(this);
}
}
}, {
key: "hideAccelerators",
value: function hideAccelerators() {
var _iterator5 = _createForOfIteratorHelper(this.children),
_step5;
try {
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
var child = _step5.value;
child.hideShortcut();
}
} catch (err) {
_iterator5.e(err);
} finally {
_iterator5.f();
}
}
}, {
key: "closeAll",
value: function closeAll() {
_localAccelerator.localAccelerator.unregisterMenuShortcuts();
var application = _application.menu;
if (application.showing) {
var menu = application;
while (menu.showing) {
menu = menu.showing.submenu;
}
while (menu && !menu.applicationMenu) {
if (menu.showing) {
menu.showing.div.style.backgroundColor = 'transparent';
menu.showing = null;
}
menu.div.remove();
menu = menu.menu;
}
if (menu) {
menu.showing.div.style.background = 'transparent';
menu.showing = null;
menu.hideAccelerators();
}
}
}
}, {
key: "getApplicationDiv",
value: function getApplicationDiv() {
return _application;
}
/**
* move selector to the next child pane
* @param {string} direction (left or right)
* @private
*/
}, {
key: "moveChild",
value: function moveChild(direction) {
var index;
if (direction === 'left') {
var parent = this.selector.menu.menu;
index = parent.children.indexOf(parent.showing);
index--;
index = index < 0 ? parent.children.length - 1 : index;
parent.children[index].handleClick();
} else {
var _parent = this.selector.menu.menu;
var selector = _parent.showing;
while (!_parent.applicationMenu) {
selector.handleClick();
selector.div.style.backgroundColor = 'transparent';
_parent = _parent.menu;
selector = _parent.showing;
}
index = _parent.children.indexOf(selector);
index++;
index = index === _parent.children.length ? 0 : index;
_parent.children[index].handleClick();
}
this.selector = null;
}
/**
* move selector right and left
* @param {MouseEvent} e
* @param {string} direction
* @private
*/
}, {
key: "horizontalSelector",
value: function horizontalSelector(e, direction) {
if (direction === 'right') {
if (this.selector.submenu) {
this.selector.handleClick(e);
this.selector.submenu.selector = this.selector.submenu.children[0];
this.selector.submenu.selector.div.style.backgroundColor = _config.config.SelectedBackgroundStyle;
this.selector = null;
} else {
this.moveChild(direction);
}
} else if (direction === 'left') {
if (!this.selector.menu.menu.applicationMenu) {
this.selector.menu.attached.handleClick(e);
this.selector.menu.menu.selector = this.selector.menu.attached;
this.selector = null;
} else {
this.moveChild(direction);
}
}
e.stopPropagation();
e.preventDefault();
}
/**
* move the selector in the menu
* @param {KeyboardEvent} e
* @param {string} direction (left, right, up, down)
* @private
*/
}, {
key: "move",
value: function move(e, direction) {
if (this.selector) {
this.selector.div.style.backgroundColor = 'transparent';
var index = this.children.indexOf(this.selector);
if (direction === 'down') {
index++;
index = index === this.children.length ? 0 : index;
} else if (direction === 'up') {
index--;
index = index < 0 ? this.children.length - 1 : index;
} else {
return this.horizontalSelector(e, direction);
}
this.selector = this.children[index];
} else {
if (direction === 'up') {
this.selector = this.children[this.children.length - 1];
} else {
this.selector = this.children[0];
}
}
this.selector.div.style.backgroundColor = _config.config.SelectedBackgroundStyle;
e.preventDefault();
e.stopPropagation();
}
/**
* click the selector with keyboard
* @private
*/
}, {
key: "enter",
value: function enter(e) {
if (this.selector) {
this.selector.handleClick(e);
e.preventDefault();
e.stopPropagation();
}
}
/**
* array containing the menu's items
* @property {MenuItems[]} items
* @readonly
*/
}, {
key: "showApplicationAccelerators",
/**
* show application menu accelerators when alt is pressed
* @private
*/
value: function showApplicationAccelerators() {
var _this = this;
this.hideAccelerators();
_localAccelerator.localAccelerator.registerAlt(function () {
if (!_this.showing) {
_this.showAccelerators();
}
}, function () {
_this.hideAccelerators();
});
}
/**
* sets active application Menu (and removes any existing application menus)
* @param {Menu} menu
* @param {HTMLElement} [parent=document.body]
*/
}, {
key: "items",
get: function get() {
return this.children;
}
}], [{
key: "setApplicationMenu",
value: function setApplicationMenu(menu) {
var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document.body;
_localAccelerator.localAccelerator.init();
if (_application) {
_application.remove();
}
_application = (0, _html.html)({
parent: parent,
styles: _config.config.ApplicationContainerStyle
});
_application.menu = menu;
menu.applyConfig(_config.config.ApplicationMenuStyle);
var _iterator6 = _createForOfIteratorHelper(menu.children),
_step6;
try {
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
var child = _step6.value;
child.applyConfig(_config.config.ApplicationMenuRowStyle);
if (child.arrow) {
child.arrow.style.display = 'none';
}
menu.div.appendChild(child.div);
}
} catch (err) {
_iterator6.e(err);
} finally {
_iterator6.f();
}
_application.appendChild(menu.div);
menu.applicationMenu = true;
menu.div.tabIndex = -1; // don't let menu bar focus unless windows are open (this fixes a focus bug)
menu.div.addEventListener('focus', function () {
if (!menu.showing) {
menu.div.blur();
}
}); // close all windows if menu is no longer the focus
menu.div.addEventListener('blur', function () {
if (menu.showing) {
menu.closeAll();
}
});
menu.showApplicationAccelerators();
}
/**
* use this to change the default config settings across all menus
* @type {config}
*/
}, {
key: "config",
get: function get() {
return _config.config;
}
/**
* MenuItem definition
* @type {MenuItem}
*/
}, {
key: "MenuItem",
get: function get() {
return _MenuItem.MenuItem;
}
}]);
return Menu;
}();
exports.Menu = Menu;
},{"./config":"../src/config.js","./MenuItem":"../src/MenuItem.js","./localAccelerator":"../src/localAccelerator.js","./html":"../src/html.js"}],"../src/index.js":[function(require,module,exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "Menu", {
enumerable: true,
get: function () {
return _Menu.Menu;
}
});
Object.defineProperty(exports, "MenuItem", {
enumerable: true,
get: function () {
return _MenuItem.MenuItem;
}
});
Object.defineProperty(exports, "localAccelerator", {
enumerable: true,
get: function () {
return _localAccelerator.localAccelerator;
}
});
var _Menu = require("./Menu");
var _MenuItem = require("./MenuItem");
var _localAccelerator = require("./localAccelerator");
},{"./Menu":"../src/Menu.js","./MenuItem":"../src/MenuItem.js","./localAccelerator":"../src/localAccelerator.js"}],"code.js":[function(require,module,exports) {
"use strict";
var _src = require("../src");
function test() {
// change a Menu setting
_src.Menu.config.SubmenuOpenDelay = 300;
var menu = new _src.Menu();
var file = new _src.Menu();
file.append(new _src.MenuItem({
label: '&New...',
accelerator: 'CommandOrControl+N',
click: function click() {
return console.log('new dialog open');
}
}));
file.append(new _src.MenuItem({
label: '&Save...',
accelerator: 'CommandOrControl+S'
}));
file.insert(1, new _src.MenuItem({
label: '&Open...',
accelerator: 'CommandOrControl+O',
click: function click() {
return console.log('open pressed');
}
}));
file.append(new _src.MenuItem({
type: 'separator'
}));
var autosave = new _src.MenuItem({
label: '&Autosave',
type: 'checkbox',
checked: false
});
file.append(autosave);
file.append(new _src.MenuItem({
type: 'separator'
}));
file.append(new _src.MenuItem({
label: 'E&xit'
}));
menu.append(new _src.MenuItem({
label: '&File',
submenu: file
}));
var submenu = new _src.Menu();
submenu.append(new _src.MenuItem({
label: 'first',
accelerator: 'ctrl+a | ctrl+b',
click: function click() {
return console.log('first pressed');
}
}));
submenu.append(new _src.MenuItem({
label: 'second'
}));
submenu.append(new _src.MenuItem({
label: 'third'
}));
submenu.append(new _src.MenuItem({
label: 'fourth'
}));
var subsubmenu = new _src.Menu();
subsubmenu.append(new _src.MenuItem({
label: 'first'
}));
subsubmenu.append(new _src.MenuItem({
label: 'second'
}));
submenu.append(new _src.MenuItem({
label: 'sub-submenu',
submenu: subsubmenu
}));
var submenu2 = new _src.Menu();
submenu2.append(new _src.MenuItem({
label: 'first'
}));
submenu2.append(new _src.MenuItem({
label: 'second'
}));
submenu2.append(new _src.MenuItem({
label: 'third'
}));
submenu2.append(new _src.MenuItem({
label: 'fourth'
}));
var view = new _src.Menu();
view.append(new _src.MenuItem({
label: 'submenu &1',
submenu: submenu
}));
view.append(new _src.MenuItem({
label: 'zoom &in',
accelerator: 'CommandOrControl+='
}));
view.append(new _src.MenuItem({
label: 'zoom &out',
accelerator: 'CommandOrControl+-'
}));
view.append(new _src.MenuItem({
type: 'separator'
}));
view.append(new _src.MenuItem({
label: 'submenu &2',
submenu: submenu2
}));
menu.append(new _src.MenuItem({
label: '&View',
submenu: view
}));
var help = new _src.Menu();
help.append(new _src.MenuItem({
label: 'About'
}));
menu.append(new _src.MenuItem({
label: '&Help',
submenu: help
}));
_src.Menu.setApplicationMenu(menu);
_src.localAccelerator.register('a', function () {
return console.log('hi');
}); // test checked change
autosave.checked = true;
}
window.onload = function () {
test(); // require('fork-me-github')()
// require('./highlight')()
};
},{"../src":"../src/index.js"}],"../node_modules/parcel/src/builtins/hmr-runtime.js":[function(require,module,exports) {
var global = arguments[3];
var OVERLAY_ID = '__parcel__error__overlay__';
var OldModule = module.bundle.Module;
function Module(moduleName) {
OldModule.call(this, moduleName);
this.hot = {
data: module.bundle.hotData,
_acceptCallbacks: [],
_disposeCallbacks: [],
accept: function (fn) {
this._acceptCallbacks.push(fn || function () {});
},
dispose: function (fn) {
this._disposeCallbacks.push(fn);
}
};
module.bundle.hotData = null;
}
module.bundle.Module = Module;
var checkedAssets, assetsToAccept;
var parent = module.bundle.parent;
if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') {
var hostname = "" || location.hostname;
var protocol = location.protocol === 'https:' ? 'wss' : 'ws';
var ws = new WebSocket(protocol + '://' + hostname + ':' + "46307" + '/');
ws.onmessage = function (event) {
checkedAssets = {};
assetsToAccept = [];
var data = JSON.parse(event.data);
if (data.type === 'update') {
var handled = false;
data.assets.forEach(function (asset) {
if (!asset.isNew) {
var didAccept = hmrAcceptCheck(global.parcelRequire, asset.id);
if (didAccept) {
handled = true;
}
}
}); // Enable HMR for CSS by default.
handled = handled || data.assets.every(function (asset) {
return asset.type === 'css' && asset.generated.js;
});
if (handled) {
console.clear();
data.assets.forEach(function (asset) {
hmrApply(global.parcelRequire, asset);
});
assetsToAccept.forEach(function (v) {
hmrAcceptRun(v[0], v[1]);
});
} else if (location.reload) {
// `location` global exists in a web worker context but lacks `.reload()` function.
location.reload();
}
}
if (data.type === 'reload') {
ws.close();
ws.onclose = function () {
location.reload();
};
}
if (data.type === 'error-resolved') {
console.log('[parcel] ✨ Error resolved');
removeErrorOverlay();
}
if (data.type === 'error') {
console.error('[parcel] 🚨 ' + data.error.message + '\n' + data.error.stack);
removeErrorOverlay();
var overlay = createErrorOverlay(data);
document.body.appendChild(overlay);
}
};
}
function removeErrorOverlay() {
var overlay = document.getElementById(OVERLAY_ID);
if (overlay) {
overlay.remove();
}
}
function createErrorOverlay(data) {
var overlay = document.createElement('div');
overlay.id = OVERLAY_ID; // html encode message and stack trace
var message = document.createElement('div');
var stackTrace = document.createElement('pre');
message.innerText = data.error.message;
stackTrace.innerText = data.error.stack;
overlay.innerHTML = '<div style="background: black; font-size: 16px; color: white; position: fixed; height: 100%; width: 100%; top: 0px; left: 0px; padding: 30px; opacity: 0.85; font-family: Menlo, Consolas, monospace; z-index: 9999;">' + '<span style="background: red; padding: 2px 4px; border-radius: 2px;">ERROR</span>' + '<span style="top: 2px; margin-left: 5px; position: relative;">🚨</span>' + '<div style="font-size: 18px; font-weight: bold; margin-top: 20px;">' + message.innerHTML + '</div>' + '<pre>' + stackTrace.innerHTML + '</pre>' + '</div>';
return overlay;
}
function getParents(bundle, id) {
var modules = bundle.modules;
if (!modules) {
return [];
}
var parents = [];
var k, d, dep;
for (k in modules) {
for (d in modules[k][1]) {
dep = modules[k][1][d];
if (dep === id || Array.isArray(dep) && dep[dep.length - 1] === id) {
parents.push(k);
}
}
}
if (bundle.parent) {
parents = parents.concat(getParents(bundle.parent, id));
}
return parents;
}
function hmrApply(bund