134 lines
3.9 KiB
JavaScript
134 lines
3.9 KiB
JavaScript
|
import App from /**/"./App.js";
|
||
|
import Component from /**/"./Component.js";
|
||
|
import Group from /**/"./Group.js";
|
||
|
import MenuBar from /**/"./MenuBar.js";
|
||
|
import MenuItem from /**/"./MenuItem.js";
|
||
|
|
||
|
// Pseudo environment context
|
||
|
let _package = {};
|
||
|
|
||
|
// GUI widget toolkit root
|
||
|
class Toolkit {
|
||
|
|
||
|
//////////////////////////////// Constants ////////////////////////////////
|
||
|
|
||
|
// Event keys
|
||
|
static group = Symbol(); // Events emitted by Toolkit.Group
|
||
|
static target = Symbol(); // Event target as a Toolkit.Component
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////// Initialization Methods //////////////////////////
|
||
|
|
||
|
Toolkit() { throw new Error("Cannot be instantiated."); }
|
||
|
|
||
|
static {
|
||
|
|
||
|
// Environment members
|
||
|
Object.assign(_package, {
|
||
|
componentKey: Symbol("Toolkit component"),
|
||
|
darkQuery : window.matchMedia("(prefers-color-scheme:dark)"),
|
||
|
nextId : 0n,
|
||
|
override : this.#override,
|
||
|
underride : this.#underride
|
||
|
});
|
||
|
|
||
|
// Register package classes with the Toolkit namespace
|
||
|
_package.register = ()=>{
|
||
|
this.Component = Component(this, _package);
|
||
|
this.App = App (this, _package);
|
||
|
this.Group = Group (this, _package);
|
||
|
this.MenuBar = MenuBar (this, _package);
|
||
|
this.MenuItem = MenuItem (this, _package);
|
||
|
Object.freeze(this);
|
||
|
Object.seal (this);
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////// Static Methods //////////////////////////////
|
||
|
|
||
|
// Resolve the Toolkit.Component for an HTML element
|
||
|
static component(element) {
|
||
|
return element[_package.componentKey] ?? null;
|
||
|
}
|
||
|
|
||
|
// Terminate an event
|
||
|
static consume(event) {
|
||
|
event.preventDefault();
|
||
|
event.stopPropagation();
|
||
|
}
|
||
|
|
||
|
// Generate a unique element ID
|
||
|
static id() {
|
||
|
return "tk-" + _package.nextId++;
|
||
|
}
|
||
|
|
||
|
// Determine whether the user dark mode preference is active
|
||
|
static isDark() {
|
||
|
return _package.darkQuery.matches;
|
||
|
}
|
||
|
|
||
|
// Determine whether an element is fully visible
|
||
|
static isVisible(element, cache = null) {
|
||
|
cache ??= new Map();
|
||
|
for (let e = element; e instanceof Element; e = e.parentNode) {
|
||
|
let style;
|
||
|
if (!cache.has(e))
|
||
|
cache.set(e, style = getComputedStyle(e));
|
||
|
else style = cache.get(e);
|
||
|
if (style.display == "none" || style.visibility == "hidden")
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Generate a list of focusable descendant elements
|
||
|
static listFocusable(element) {
|
||
|
let cache = new Map();
|
||
|
return Array.from(element.querySelectorAll(
|
||
|
"*:is(a[href],area,button,details,input,textarea,select," +
|
||
|
"[tabindex='0']):not([disabled])"
|
||
|
)).filter(e=>this.isVisible(e, cache));
|
||
|
}
|
||
|
|
||
|
static stylesheet(url) {
|
||
|
let style = document.createElement("link");
|
||
|
style.rel = "stylesheet";
|
||
|
style.href = url;
|
||
|
return style;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////// Package Methods /////////////////////////////
|
||
|
|
||
|
// Process overrides for Toolkit.Component initialization
|
||
|
static #override(fromCaller, fromSelf) {
|
||
|
fromCaller = Object.assign({}, fromCaller ?? {});
|
||
|
fromSelf = Object.assign({}, fromSelf ?? {});
|
||
|
fromSelf.style = Object.assign(
|
||
|
fromSelf.style ?? {}, fromCaller.style ?? {});
|
||
|
delete fromCaller.style;
|
||
|
Object.assign(fromSelf, fromCaller);
|
||
|
return fromSelf;
|
||
|
}
|
||
|
|
||
|
// Extract override properties for later processing
|
||
|
static #underride(overrides, underrides) {
|
||
|
let ret = {};
|
||
|
for (let entry of Object.entries(underrides)) {
|
||
|
ret[entry[0]] = overrides[entry[0]] ?? underrides[entry[1]];
|
||
|
delete overrides[entry[0]];
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
_package.register();
|
||
|
|
||
|
export default Toolkit;
|