mirror of
https://github.com/jaandrle/deka-dom-el
synced 2025-04-06 21:47:06 +02:00
⚡ scope.signal
This commit is contained in:
parent
08316892d0
commit
afd09a25db
4
dist/esm-with-signals.d.ts
vendored
4
dist/esm-with-signals.d.ts
vendored
@ -203,6 +203,10 @@ export const scope: {
|
|||||||
* — `scope.host(on.connected(console.log))`.
|
* — `scope.host(on.connected(console.log))`.
|
||||||
* */
|
* */
|
||||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||||
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
signal: AbortSignal;
|
||||||
state: Scope[];
|
state: Scope[];
|
||||||
/** Adds new child scope. All attributes are inherited by default. */
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||||
|
438
dist/esm-with-signals.js
vendored
438
dist/esm-with-signals.js
vendored
@ -111,6 +111,215 @@ var evc = "dde:connected";
|
|||||||
var evd = "dde:disconnected";
|
var evd = "dde:disconnected";
|
||||||
var eva = "dde:attributeChanged";
|
var eva = "dde:attributeChanged";
|
||||||
|
|
||||||
|
// src/events-observer.js
|
||||||
|
var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
|
||||||
|
get() {
|
||||||
|
return () => {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function connectionsChangesObserverConstructor() {
|
||||||
|
const store = /* @__PURE__ */ new Map();
|
||||||
|
let is_observing = false;
|
||||||
|
const observerListener = (stop2) => function(mutations) {
|
||||||
|
for (const mutation of mutations) {
|
||||||
|
if (mutation.type !== "childList") continue;
|
||||||
|
if (observerAdded(mutation.addedNodes, true)) {
|
||||||
|
stop2();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (observerRemoved(mutation.removedNodes, true))
|
||||||
|
stop2();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const observer = new enviroment.M(observerListener(stop));
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Creates an observer for a specific element
|
||||||
|
* @param {Element} element - Element to observe
|
||||||
|
* @returns {Function} Cleanup function
|
||||||
|
*/
|
||||||
|
observe(element) {
|
||||||
|
const o = new enviroment.M(observerListener(() => {
|
||||||
|
}));
|
||||||
|
o.observe(element, { childList: true, subtree: true });
|
||||||
|
return () => o.disconnect();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Register a connection listener for an element
|
||||||
|
* @param {Element} element - Element to watch
|
||||||
|
* @param {Function} listener - Callback for connection event
|
||||||
|
*/
|
||||||
|
onConnected(element, listener) {
|
||||||
|
start();
|
||||||
|
const listeners = getElementStore(element);
|
||||||
|
if (listeners.connected.has(listener)) return;
|
||||||
|
listeners.connected.add(listener);
|
||||||
|
listeners.length_c += 1;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Unregister a connection listener
|
||||||
|
* @param {Element} element - Element being watched
|
||||||
|
* @param {Function} listener - Callback to remove
|
||||||
|
*/
|
||||||
|
offConnected(element, listener) {
|
||||||
|
if (!store.has(element)) return;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.connected.has(listener)) return;
|
||||||
|
ls.connected.delete(listener);
|
||||||
|
ls.length_c -= 1;
|
||||||
|
cleanWhenOff(element, ls);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Register a disconnection listener for an element
|
||||||
|
* @param {Element} element - Element to watch
|
||||||
|
* @param {Function} listener - Callback for disconnection event
|
||||||
|
*/
|
||||||
|
onDisconnected(element, listener) {
|
||||||
|
start();
|
||||||
|
const listeners = getElementStore(element);
|
||||||
|
if (listeners.disconnected.has(listener)) return;
|
||||||
|
listeners.disconnected.add(listener);
|
||||||
|
listeners.length_d += 1;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Unregister a disconnection listener
|
||||||
|
* @param {Element} element - Element being watched
|
||||||
|
* @param {Function} listener - Callback to remove
|
||||||
|
*/
|
||||||
|
offDisconnected(element, listener) {
|
||||||
|
if (!store.has(element)) return;
|
||||||
|
const ls = store.get(element);
|
||||||
|
ls.disconnected.delete(listener);
|
||||||
|
ls.length_d -= 1;
|
||||||
|
cleanWhenOff(element, ls);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function cleanWhenOff(element, ls) {
|
||||||
|
if (ls.length_c || ls.length_d)
|
||||||
|
return;
|
||||||
|
store.delete(element);
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
function getElementStore(element) {
|
||||||
|
if (store.has(element)) return store.get(element);
|
||||||
|
const out = {
|
||||||
|
connected: /* @__PURE__ */ new WeakSet(),
|
||||||
|
length_c: 0,
|
||||||
|
disconnected: /* @__PURE__ */ new WeakSet(),
|
||||||
|
length_d: 0
|
||||||
|
};
|
||||||
|
store.set(element, out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function start() {
|
||||||
|
if (is_observing) return;
|
||||||
|
is_observing = true;
|
||||||
|
observer.observe(enviroment.D.body, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
function stop() {
|
||||||
|
if (!is_observing || store.size) return;
|
||||||
|
is_observing = false;
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
function requestIdle() {
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
(requestIdleCallback || requestAnimationFrame)(resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function collectChildren(element) {
|
||||||
|
if (store.size > 30)
|
||||||
|
await requestIdle();
|
||||||
|
const out = [];
|
||||||
|
if (!isInstance(element, Node)) return out;
|
||||||
|
for (const el of store.keys()) {
|
||||||
|
if (el === element || !isInstance(el, Node)) continue;
|
||||||
|
if (element.contains(el))
|
||||||
|
out.push(el);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function observerAdded(addedNodes, is_root) {
|
||||||
|
let out = false;
|
||||||
|
for (const element of addedNodes) {
|
||||||
|
if (is_root) collectChildren(element).then(observerAdded);
|
||||||
|
if (!store.has(element)) continue;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.length_c) continue;
|
||||||
|
element.dispatchEvent(new Event(evc));
|
||||||
|
ls.connected = /* @__PURE__ */ new WeakSet();
|
||||||
|
ls.length_c = 0;
|
||||||
|
if (!ls.length_d) store.delete(element);
|
||||||
|
out = true;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function observerRemoved(removedNodes, is_root) {
|
||||||
|
let out = false;
|
||||||
|
for (const element of removedNodes) {
|
||||||
|
if (is_root) collectChildren(element).then(observerRemoved);
|
||||||
|
if (!store.has(element)) continue;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.length_d) continue;
|
||||||
|
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));
|
||||||
|
out = true;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function dispatchRemove(element) {
|
||||||
|
return () => {
|
||||||
|
if (element.isConnected) return;
|
||||||
|
element.dispatchEvent(new Event(evd));
|
||||||
|
store.delete(element);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/events.js
|
||||||
|
function dispatchEvent(name, options, host) {
|
||||||
|
if (typeof options === "function") {
|
||||||
|
host = options;
|
||||||
|
options = null;
|
||||||
|
}
|
||||||
|
if (!options) options = {};
|
||||||
|
return function dispatch(element, ...d) {
|
||||||
|
if (host) {
|
||||||
|
d.unshift(element);
|
||||||
|
element = typeof host === "function" ? host() : host;
|
||||||
|
}
|
||||||
|
const event = d.length ? new CustomEvent(name, oAssign({ detail: d[0] }, options)) : new Event(name, options);
|
||||||
|
return element.dispatchEvent(event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function on(event, listener, options) {
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(event, listener, options);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var lifeOptions = (obj) => oAssign({}, typeof obj === "object" ? obj : null, { once: true });
|
||||||
|
on.connected = function(listener, options) {
|
||||||
|
options = lifeOptions(options);
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(evc, listener, options);
|
||||||
|
if (element[keyLTE]) return element;
|
||||||
|
if (element.isConnected) return element.dispatchEvent(new Event(evc)), element;
|
||||||
|
const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener));
|
||||||
|
if (c) c_ch_o.onConnected(element, listener);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
on.disconnected = function(listener, options) {
|
||||||
|
options = lifeOptions(options);
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(evd, listener, options);
|
||||||
|
if (element[keyLTE]) return element;
|
||||||
|
const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener));
|
||||||
|
if (c) c_ch_o.onDisconnected(element, listener);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// src/dom.js
|
// src/dom.js
|
||||||
function queue(promise) {
|
function queue(promise) {
|
||||||
return enviroment.q(promise);
|
return enviroment.q(promise);
|
||||||
@ -122,6 +331,7 @@ var scopes = [{
|
|||||||
host: (c) => c ? c(enviroment.D.body) : enviroment.D.body,
|
host: (c) => c ? c(enviroment.D.body) : enviroment.D.body,
|
||||||
prevent: true
|
prevent: true
|
||||||
}];
|
}];
|
||||||
|
var store_abort = /* @__PURE__ */ new WeakMap();
|
||||||
var scope = {
|
var scope = {
|
||||||
/**
|
/**
|
||||||
* Gets the current scope
|
* Gets the current scope
|
||||||
@ -138,6 +348,17 @@ var scope = {
|
|||||||
return this.current.host;
|
return this.current.host;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
get signal() {
|
||||||
|
const { host } = this;
|
||||||
|
if (store_abort.has(host)) return store_abort.get(host);
|
||||||
|
const a = new AbortController();
|
||||||
|
store_abort.set(host, a);
|
||||||
|
host(on.disconnected(() => a.abort()));
|
||||||
|
return a.signal;
|
||||||
|
},
|
||||||
|
/**
|
||||||
* Prevents default behavior in the current scope
|
* Prevents default behavior in the current scope
|
||||||
* @returns {Object} Current scope context
|
* @returns {Object} Current scope context
|
||||||
*/
|
*/
|
||||||
@ -380,170 +601,6 @@ function setDelete(obj, key, val) {
|
|||||||
return Reflect.deleteProperty(obj, key);
|
return Reflect.deleteProperty(obj, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/events-observer.js
|
|
||||||
var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
|
|
||||||
get() {
|
|
||||||
return () => {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
function connectionsChangesObserverConstructor() {
|
|
||||||
const store = /* @__PURE__ */ new Map();
|
|
||||||
let is_observing = false;
|
|
||||||
const observerListener = (stop2) => function(mutations) {
|
|
||||||
for (const mutation of mutations) {
|
|
||||||
if (mutation.type !== "childList") continue;
|
|
||||||
if (observerAdded(mutation.addedNodes, true)) {
|
|
||||||
stop2();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (observerRemoved(mutation.removedNodes, true))
|
|
||||||
stop2();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const observer = new enviroment.M(observerListener(stop));
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Creates an observer for a specific element
|
|
||||||
* @param {Element} element - Element to observe
|
|
||||||
* @returns {Function} Cleanup function
|
|
||||||
*/
|
|
||||||
observe(element) {
|
|
||||||
const o = new enviroment.M(observerListener(() => {
|
|
||||||
}));
|
|
||||||
o.observe(element, { childList: true, subtree: true });
|
|
||||||
return () => o.disconnect();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Register a connection listener for an element
|
|
||||||
* @param {Element} element - Element to watch
|
|
||||||
* @param {Function} listener - Callback for connection event
|
|
||||||
*/
|
|
||||||
onConnected(element, listener) {
|
|
||||||
start();
|
|
||||||
const listeners = getElementStore(element);
|
|
||||||
if (listeners.connected.has(listener)) return;
|
|
||||||
listeners.connected.add(listener);
|
|
||||||
listeners.length_c += 1;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Unregister a connection listener
|
|
||||||
* @param {Element} element - Element being watched
|
|
||||||
* @param {Function} listener - Callback to remove
|
|
||||||
*/
|
|
||||||
offConnected(element, listener) {
|
|
||||||
if (!store.has(element)) return;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.connected.has(listener)) return;
|
|
||||||
ls.connected.delete(listener);
|
|
||||||
ls.length_c -= 1;
|
|
||||||
cleanWhenOff(element, ls);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Register a disconnection listener for an element
|
|
||||||
* @param {Element} element - Element to watch
|
|
||||||
* @param {Function} listener - Callback for disconnection event
|
|
||||||
*/
|
|
||||||
onDisconnected(element, listener) {
|
|
||||||
start();
|
|
||||||
const listeners = getElementStore(element);
|
|
||||||
if (listeners.disconnected.has(listener)) return;
|
|
||||||
listeners.disconnected.add(listener);
|
|
||||||
listeners.length_d += 1;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Unregister a disconnection listener
|
|
||||||
* @param {Element} element - Element being watched
|
|
||||||
* @param {Function} listener - Callback to remove
|
|
||||||
*/
|
|
||||||
offDisconnected(element, listener) {
|
|
||||||
if (!store.has(element)) return;
|
|
||||||
const ls = store.get(element);
|
|
||||||
ls.disconnected.delete(listener);
|
|
||||||
ls.length_d -= 1;
|
|
||||||
cleanWhenOff(element, ls);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
function cleanWhenOff(element, ls) {
|
|
||||||
if (ls.length_c || ls.length_d)
|
|
||||||
return;
|
|
||||||
store.delete(element);
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
function getElementStore(element) {
|
|
||||||
if (store.has(element)) return store.get(element);
|
|
||||||
const out = {
|
|
||||||
connected: /* @__PURE__ */ new WeakSet(),
|
|
||||||
length_c: 0,
|
|
||||||
disconnected: /* @__PURE__ */ new WeakSet(),
|
|
||||||
length_d: 0
|
|
||||||
};
|
|
||||||
store.set(element, out);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function start() {
|
|
||||||
if (is_observing) return;
|
|
||||||
is_observing = true;
|
|
||||||
observer.observe(enviroment.D.body, { childList: true, subtree: true });
|
|
||||||
}
|
|
||||||
function stop() {
|
|
||||||
if (!is_observing || store.size) return;
|
|
||||||
is_observing = false;
|
|
||||||
observer.disconnect();
|
|
||||||
}
|
|
||||||
function requestIdle() {
|
|
||||||
return new Promise(function(resolve) {
|
|
||||||
(requestIdleCallback || requestAnimationFrame)(resolve);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async function collectChildren(element) {
|
|
||||||
if (store.size > 30)
|
|
||||||
await requestIdle();
|
|
||||||
const out = [];
|
|
||||||
if (!isInstance(element, Node)) return out;
|
|
||||||
for (const el of store.keys()) {
|
|
||||||
if (el === element || !isInstance(el, Node)) continue;
|
|
||||||
if (element.contains(el))
|
|
||||||
out.push(el);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function observerAdded(addedNodes, is_root) {
|
|
||||||
let out = false;
|
|
||||||
for (const element of addedNodes) {
|
|
||||||
if (is_root) collectChildren(element).then(observerAdded);
|
|
||||||
if (!store.has(element)) continue;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.length_c) continue;
|
|
||||||
element.dispatchEvent(new Event(evc));
|
|
||||||
ls.connected = /* @__PURE__ */ new WeakSet();
|
|
||||||
ls.length_c = 0;
|
|
||||||
if (!ls.length_d) store.delete(element);
|
|
||||||
out = true;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function observerRemoved(removedNodes, is_root) {
|
|
||||||
let out = false;
|
|
||||||
for (const element of removedNodes) {
|
|
||||||
if (is_root) collectChildren(element).then(observerRemoved);
|
|
||||||
if (!store.has(element)) continue;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.length_d) continue;
|
|
||||||
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));
|
|
||||||
out = true;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function dispatchRemove(element) {
|
|
||||||
return () => {
|
|
||||||
if (element.isConnected) return;
|
|
||||||
element.dispatchEvent(new Event(evd));
|
|
||||||
store.delete(element);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// src/customElement.js
|
// src/customElement.js
|
||||||
function customElementRender(target, render, props = {}) {
|
function customElementRender(target, render, props = {}) {
|
||||||
const custom_element = target.host || target;
|
const custom_element = target.host || target;
|
||||||
@ -587,59 +644,6 @@ function wrapMethod(obj, method, apply) {
|
|||||||
}), { apply });
|
}), { apply });
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/events.js
|
|
||||||
function dispatchEvent(name, options, host) {
|
|
||||||
if (typeof options === "function") {
|
|
||||||
host = options;
|
|
||||||
options = null;
|
|
||||||
}
|
|
||||||
if (!options) options = {};
|
|
||||||
return function dispatch(element, ...d) {
|
|
||||||
if (host) {
|
|
||||||
d.unshift(element);
|
|
||||||
element = typeof host === "function" ? host() : host;
|
|
||||||
}
|
|
||||||
const event = d.length ? new CustomEvent(name, oAssign({ detail: d[0] }, options)) : new Event(name, options);
|
|
||||||
return element.dispatchEvent(event);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function on(event, listener, options) {
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(event, listener, options);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var lifeOptions = (obj) => oAssign({}, typeof obj === "object" ? obj : null, { once: true });
|
|
||||||
on.connected = function(listener, options) {
|
|
||||||
options = lifeOptions(options);
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(evc, listener, options);
|
|
||||||
if (element[keyLTE]) return element;
|
|
||||||
if (element.isConnected) return element.dispatchEvent(new Event(evc)), element;
|
|
||||||
const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener));
|
|
||||||
if (c) c_ch_o.onConnected(element, listener);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
on.disconnected = function(listener, options) {
|
|
||||||
options = lifeOptions(options);
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(evd, listener, options);
|
|
||||||
if (element[keyLTE]) return element;
|
|
||||||
const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener));
|
|
||||||
if (c) c_ch_o.onDisconnected(element, listener);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
var store_abort = /* @__PURE__ */ new WeakMap();
|
|
||||||
on.disconnectedAsAbort = function(host) {
|
|
||||||
if (store_abort.has(host)) return store_abort.get(host);
|
|
||||||
const a = new AbortController();
|
|
||||||
store_abort.set(host, a);
|
|
||||||
host(on.disconnected(() => a.abort()));
|
|
||||||
return a.signal;
|
|
||||||
};
|
|
||||||
|
|
||||||
// src/signals-lib/helpers.js
|
// src/signals-lib/helpers.js
|
||||||
var mark = "__dde_signal";
|
var mark = "__dde_signal";
|
||||||
var queueSignalWrite = /* @__PURE__ */ (() => {
|
var queueSignalWrite = /* @__PURE__ */ (() => {
|
||||||
|
4
dist/esm-with-signals.min.d.ts
vendored
4
dist/esm-with-signals.min.d.ts
vendored
@ -203,6 +203,10 @@ export const scope: {
|
|||||||
* — `scope.host(on.connected(console.log))`.
|
* — `scope.host(on.connected(console.log))`.
|
||||||
* */
|
* */
|
||||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||||
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
signal: AbortSignal;
|
||||||
state: Scope[];
|
state: Scope[];
|
||||||
/** Adds new child scope. All attributes are inherited by default. */
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||||
|
6
dist/esm-with-signals.min.js
vendored
6
dist/esm-with-signals.min.js
vendored
File diff suppressed because one or more lines are too long
4
dist/esm.d.ts
vendored
4
dist/esm.d.ts
vendored
@ -202,6 +202,10 @@ export const scope: {
|
|||||||
* — `scope.host(on.connected(console.log))`.
|
* — `scope.host(on.connected(console.log))`.
|
||||||
* */
|
* */
|
||||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||||
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
signal: AbortSignal;
|
||||||
state: Scope[];
|
state: Scope[];
|
||||||
/** Adds new child scope. All attributes are inherited by default. */
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||||
|
438
dist/esm.js
vendored
438
dist/esm.js
vendored
@ -78,6 +78,215 @@ var evc = "dde:connected";
|
|||||||
var evd = "dde:disconnected";
|
var evd = "dde:disconnected";
|
||||||
var eva = "dde:attributeChanged";
|
var eva = "dde:attributeChanged";
|
||||||
|
|
||||||
|
// src/events-observer.js
|
||||||
|
var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
|
||||||
|
get() {
|
||||||
|
return () => {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function connectionsChangesObserverConstructor() {
|
||||||
|
const store = /* @__PURE__ */ new Map();
|
||||||
|
let is_observing = false;
|
||||||
|
const observerListener = (stop2) => function(mutations) {
|
||||||
|
for (const mutation of mutations) {
|
||||||
|
if (mutation.type !== "childList") continue;
|
||||||
|
if (observerAdded(mutation.addedNodes, true)) {
|
||||||
|
stop2();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (observerRemoved(mutation.removedNodes, true))
|
||||||
|
stop2();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const observer = new enviroment.M(observerListener(stop));
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Creates an observer for a specific element
|
||||||
|
* @param {Element} element - Element to observe
|
||||||
|
* @returns {Function} Cleanup function
|
||||||
|
*/
|
||||||
|
observe(element) {
|
||||||
|
const o = new enviroment.M(observerListener(() => {
|
||||||
|
}));
|
||||||
|
o.observe(element, { childList: true, subtree: true });
|
||||||
|
return () => o.disconnect();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Register a connection listener for an element
|
||||||
|
* @param {Element} element - Element to watch
|
||||||
|
* @param {Function} listener - Callback for connection event
|
||||||
|
*/
|
||||||
|
onConnected(element, listener) {
|
||||||
|
start();
|
||||||
|
const listeners = getElementStore(element);
|
||||||
|
if (listeners.connected.has(listener)) return;
|
||||||
|
listeners.connected.add(listener);
|
||||||
|
listeners.length_c += 1;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Unregister a connection listener
|
||||||
|
* @param {Element} element - Element being watched
|
||||||
|
* @param {Function} listener - Callback to remove
|
||||||
|
*/
|
||||||
|
offConnected(element, listener) {
|
||||||
|
if (!store.has(element)) return;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.connected.has(listener)) return;
|
||||||
|
ls.connected.delete(listener);
|
||||||
|
ls.length_c -= 1;
|
||||||
|
cleanWhenOff(element, ls);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Register a disconnection listener for an element
|
||||||
|
* @param {Element} element - Element to watch
|
||||||
|
* @param {Function} listener - Callback for disconnection event
|
||||||
|
*/
|
||||||
|
onDisconnected(element, listener) {
|
||||||
|
start();
|
||||||
|
const listeners = getElementStore(element);
|
||||||
|
if (listeners.disconnected.has(listener)) return;
|
||||||
|
listeners.disconnected.add(listener);
|
||||||
|
listeners.length_d += 1;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Unregister a disconnection listener
|
||||||
|
* @param {Element} element - Element being watched
|
||||||
|
* @param {Function} listener - Callback to remove
|
||||||
|
*/
|
||||||
|
offDisconnected(element, listener) {
|
||||||
|
if (!store.has(element)) return;
|
||||||
|
const ls = store.get(element);
|
||||||
|
ls.disconnected.delete(listener);
|
||||||
|
ls.length_d -= 1;
|
||||||
|
cleanWhenOff(element, ls);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function cleanWhenOff(element, ls) {
|
||||||
|
if (ls.length_c || ls.length_d)
|
||||||
|
return;
|
||||||
|
store.delete(element);
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
function getElementStore(element) {
|
||||||
|
if (store.has(element)) return store.get(element);
|
||||||
|
const out = {
|
||||||
|
connected: /* @__PURE__ */ new WeakSet(),
|
||||||
|
length_c: 0,
|
||||||
|
disconnected: /* @__PURE__ */ new WeakSet(),
|
||||||
|
length_d: 0
|
||||||
|
};
|
||||||
|
store.set(element, out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function start() {
|
||||||
|
if (is_observing) return;
|
||||||
|
is_observing = true;
|
||||||
|
observer.observe(enviroment.D.body, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
function stop() {
|
||||||
|
if (!is_observing || store.size) return;
|
||||||
|
is_observing = false;
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
function requestIdle() {
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
(requestIdleCallback || requestAnimationFrame)(resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function collectChildren(element) {
|
||||||
|
if (store.size > 30)
|
||||||
|
await requestIdle();
|
||||||
|
const out = [];
|
||||||
|
if (!isInstance(element, Node)) return out;
|
||||||
|
for (const el of store.keys()) {
|
||||||
|
if (el === element || !isInstance(el, Node)) continue;
|
||||||
|
if (element.contains(el))
|
||||||
|
out.push(el);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function observerAdded(addedNodes, is_root) {
|
||||||
|
let out = false;
|
||||||
|
for (const element of addedNodes) {
|
||||||
|
if (is_root) collectChildren(element).then(observerAdded);
|
||||||
|
if (!store.has(element)) continue;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.length_c) continue;
|
||||||
|
element.dispatchEvent(new Event(evc));
|
||||||
|
ls.connected = /* @__PURE__ */ new WeakSet();
|
||||||
|
ls.length_c = 0;
|
||||||
|
if (!ls.length_d) store.delete(element);
|
||||||
|
out = true;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function observerRemoved(removedNodes, is_root) {
|
||||||
|
let out = false;
|
||||||
|
for (const element of removedNodes) {
|
||||||
|
if (is_root) collectChildren(element).then(observerRemoved);
|
||||||
|
if (!store.has(element)) continue;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.length_d) continue;
|
||||||
|
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));
|
||||||
|
out = true;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function dispatchRemove(element) {
|
||||||
|
return () => {
|
||||||
|
if (element.isConnected) return;
|
||||||
|
element.dispatchEvent(new Event(evd));
|
||||||
|
store.delete(element);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/events.js
|
||||||
|
function dispatchEvent(name, options, host) {
|
||||||
|
if (typeof options === "function") {
|
||||||
|
host = options;
|
||||||
|
options = null;
|
||||||
|
}
|
||||||
|
if (!options) options = {};
|
||||||
|
return function dispatch(element, ...d) {
|
||||||
|
if (host) {
|
||||||
|
d.unshift(element);
|
||||||
|
element = typeof host === "function" ? host() : host;
|
||||||
|
}
|
||||||
|
const event = d.length ? new CustomEvent(name, oAssign({ detail: d[0] }, options)) : new Event(name, options);
|
||||||
|
return element.dispatchEvent(event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function on(event, listener, options) {
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(event, listener, options);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var lifeOptions = (obj) => oAssign({}, typeof obj === "object" ? obj : null, { once: true });
|
||||||
|
on.connected = function(listener, options) {
|
||||||
|
options = lifeOptions(options);
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(evc, listener, options);
|
||||||
|
if (element[keyLTE]) return element;
|
||||||
|
if (element.isConnected) return element.dispatchEvent(new Event(evc)), element;
|
||||||
|
const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener));
|
||||||
|
if (c) c_ch_o.onConnected(element, listener);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
on.disconnected = function(listener, options) {
|
||||||
|
options = lifeOptions(options);
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(evd, listener, options);
|
||||||
|
if (element[keyLTE]) return element;
|
||||||
|
const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener));
|
||||||
|
if (c) c_ch_o.onDisconnected(element, listener);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// src/dom.js
|
// src/dom.js
|
||||||
function queue(promise) {
|
function queue(promise) {
|
||||||
return enviroment.q(promise);
|
return enviroment.q(promise);
|
||||||
@ -89,6 +298,7 @@ var scopes = [{
|
|||||||
host: (c) => c ? c(enviroment.D.body) : enviroment.D.body,
|
host: (c) => c ? c(enviroment.D.body) : enviroment.D.body,
|
||||||
prevent: true
|
prevent: true
|
||||||
}];
|
}];
|
||||||
|
var store_abort = /* @__PURE__ */ new WeakMap();
|
||||||
var scope = {
|
var scope = {
|
||||||
/**
|
/**
|
||||||
* Gets the current scope
|
* Gets the current scope
|
||||||
@ -105,6 +315,17 @@ var scope = {
|
|||||||
return this.current.host;
|
return this.current.host;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
get signal() {
|
||||||
|
const { host } = this;
|
||||||
|
if (store_abort.has(host)) return store_abort.get(host);
|
||||||
|
const a = new AbortController();
|
||||||
|
store_abort.set(host, a);
|
||||||
|
host(on.disconnected(() => a.abort()));
|
||||||
|
return a.signal;
|
||||||
|
},
|
||||||
|
/**
|
||||||
* Prevents default behavior in the current scope
|
* Prevents default behavior in the current scope
|
||||||
* @returns {Object} Current scope context
|
* @returns {Object} Current scope context
|
||||||
*/
|
*/
|
||||||
@ -347,170 +568,6 @@ function setDelete(obj, key, val) {
|
|||||||
return Reflect.deleteProperty(obj, key);
|
return Reflect.deleteProperty(obj, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/events-observer.js
|
|
||||||
var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
|
|
||||||
get() {
|
|
||||||
return () => {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
function connectionsChangesObserverConstructor() {
|
|
||||||
const store = /* @__PURE__ */ new Map();
|
|
||||||
let is_observing = false;
|
|
||||||
const observerListener = (stop2) => function(mutations) {
|
|
||||||
for (const mutation of mutations) {
|
|
||||||
if (mutation.type !== "childList") continue;
|
|
||||||
if (observerAdded(mutation.addedNodes, true)) {
|
|
||||||
stop2();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (observerRemoved(mutation.removedNodes, true))
|
|
||||||
stop2();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const observer = new enviroment.M(observerListener(stop));
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Creates an observer for a specific element
|
|
||||||
* @param {Element} element - Element to observe
|
|
||||||
* @returns {Function} Cleanup function
|
|
||||||
*/
|
|
||||||
observe(element) {
|
|
||||||
const o = new enviroment.M(observerListener(() => {
|
|
||||||
}));
|
|
||||||
o.observe(element, { childList: true, subtree: true });
|
|
||||||
return () => o.disconnect();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Register a connection listener for an element
|
|
||||||
* @param {Element} element - Element to watch
|
|
||||||
* @param {Function} listener - Callback for connection event
|
|
||||||
*/
|
|
||||||
onConnected(element, listener) {
|
|
||||||
start();
|
|
||||||
const listeners = getElementStore(element);
|
|
||||||
if (listeners.connected.has(listener)) return;
|
|
||||||
listeners.connected.add(listener);
|
|
||||||
listeners.length_c += 1;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Unregister a connection listener
|
|
||||||
* @param {Element} element - Element being watched
|
|
||||||
* @param {Function} listener - Callback to remove
|
|
||||||
*/
|
|
||||||
offConnected(element, listener) {
|
|
||||||
if (!store.has(element)) return;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.connected.has(listener)) return;
|
|
||||||
ls.connected.delete(listener);
|
|
||||||
ls.length_c -= 1;
|
|
||||||
cleanWhenOff(element, ls);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Register a disconnection listener for an element
|
|
||||||
* @param {Element} element - Element to watch
|
|
||||||
* @param {Function} listener - Callback for disconnection event
|
|
||||||
*/
|
|
||||||
onDisconnected(element, listener) {
|
|
||||||
start();
|
|
||||||
const listeners = getElementStore(element);
|
|
||||||
if (listeners.disconnected.has(listener)) return;
|
|
||||||
listeners.disconnected.add(listener);
|
|
||||||
listeners.length_d += 1;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Unregister a disconnection listener
|
|
||||||
* @param {Element} element - Element being watched
|
|
||||||
* @param {Function} listener - Callback to remove
|
|
||||||
*/
|
|
||||||
offDisconnected(element, listener) {
|
|
||||||
if (!store.has(element)) return;
|
|
||||||
const ls = store.get(element);
|
|
||||||
ls.disconnected.delete(listener);
|
|
||||||
ls.length_d -= 1;
|
|
||||||
cleanWhenOff(element, ls);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
function cleanWhenOff(element, ls) {
|
|
||||||
if (ls.length_c || ls.length_d)
|
|
||||||
return;
|
|
||||||
store.delete(element);
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
function getElementStore(element) {
|
|
||||||
if (store.has(element)) return store.get(element);
|
|
||||||
const out = {
|
|
||||||
connected: /* @__PURE__ */ new WeakSet(),
|
|
||||||
length_c: 0,
|
|
||||||
disconnected: /* @__PURE__ */ new WeakSet(),
|
|
||||||
length_d: 0
|
|
||||||
};
|
|
||||||
store.set(element, out);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function start() {
|
|
||||||
if (is_observing) return;
|
|
||||||
is_observing = true;
|
|
||||||
observer.observe(enviroment.D.body, { childList: true, subtree: true });
|
|
||||||
}
|
|
||||||
function stop() {
|
|
||||||
if (!is_observing || store.size) return;
|
|
||||||
is_observing = false;
|
|
||||||
observer.disconnect();
|
|
||||||
}
|
|
||||||
function requestIdle() {
|
|
||||||
return new Promise(function(resolve) {
|
|
||||||
(requestIdleCallback || requestAnimationFrame)(resolve);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async function collectChildren(element) {
|
|
||||||
if (store.size > 30)
|
|
||||||
await requestIdle();
|
|
||||||
const out = [];
|
|
||||||
if (!isInstance(element, Node)) return out;
|
|
||||||
for (const el of store.keys()) {
|
|
||||||
if (el === element || !isInstance(el, Node)) continue;
|
|
||||||
if (element.contains(el))
|
|
||||||
out.push(el);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function observerAdded(addedNodes, is_root) {
|
|
||||||
let out = false;
|
|
||||||
for (const element of addedNodes) {
|
|
||||||
if (is_root) collectChildren(element).then(observerAdded);
|
|
||||||
if (!store.has(element)) continue;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.length_c) continue;
|
|
||||||
element.dispatchEvent(new Event(evc));
|
|
||||||
ls.connected = /* @__PURE__ */ new WeakSet();
|
|
||||||
ls.length_c = 0;
|
|
||||||
if (!ls.length_d) store.delete(element);
|
|
||||||
out = true;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function observerRemoved(removedNodes, is_root) {
|
|
||||||
let out = false;
|
|
||||||
for (const element of removedNodes) {
|
|
||||||
if (is_root) collectChildren(element).then(observerRemoved);
|
|
||||||
if (!store.has(element)) continue;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.length_d) continue;
|
|
||||||
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));
|
|
||||||
out = true;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function dispatchRemove(element) {
|
|
||||||
return () => {
|
|
||||||
if (element.isConnected) return;
|
|
||||||
element.dispatchEvent(new Event(evd));
|
|
||||||
store.delete(element);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// src/customElement.js
|
// src/customElement.js
|
||||||
function customElementRender(target, render, props = {}) {
|
function customElementRender(target, render, props = {}) {
|
||||||
const custom_element = target.host || target;
|
const custom_element = target.host || target;
|
||||||
@ -553,59 +610,6 @@ function wrapMethod(obj, method, apply) {
|
|||||||
obj[method] = new Proxy(obj[method] || (() => {
|
obj[method] = new Proxy(obj[method] || (() => {
|
||||||
}), { apply });
|
}), { apply });
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/events.js
|
|
||||||
function dispatchEvent(name, options, host) {
|
|
||||||
if (typeof options === "function") {
|
|
||||||
host = options;
|
|
||||||
options = null;
|
|
||||||
}
|
|
||||||
if (!options) options = {};
|
|
||||||
return function dispatch(element, ...d) {
|
|
||||||
if (host) {
|
|
||||||
d.unshift(element);
|
|
||||||
element = typeof host === "function" ? host() : host;
|
|
||||||
}
|
|
||||||
const event = d.length ? new CustomEvent(name, oAssign({ detail: d[0] }, options)) : new Event(name, options);
|
|
||||||
return element.dispatchEvent(event);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function on(event, listener, options) {
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(event, listener, options);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var lifeOptions = (obj) => oAssign({}, typeof obj === "object" ? obj : null, { once: true });
|
|
||||||
on.connected = function(listener, options) {
|
|
||||||
options = lifeOptions(options);
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(evc, listener, options);
|
|
||||||
if (element[keyLTE]) return element;
|
|
||||||
if (element.isConnected) return element.dispatchEvent(new Event(evc)), element;
|
|
||||||
const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener));
|
|
||||||
if (c) c_ch_o.onConnected(element, listener);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
on.disconnected = function(listener, options) {
|
|
||||||
options = lifeOptions(options);
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(evd, listener, options);
|
|
||||||
if (element[keyLTE]) return element;
|
|
||||||
const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener));
|
|
||||||
if (c) c_ch_o.onDisconnected(element, listener);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
var store_abort = /* @__PURE__ */ new WeakMap();
|
|
||||||
on.disconnectedAsAbort = function(host) {
|
|
||||||
if (store_abort.has(host)) return store_abort.get(host);
|
|
||||||
const a = new AbortController();
|
|
||||||
store_abort.set(host, a);
|
|
||||||
host(on.disconnected(() => a.abort()));
|
|
||||||
return a.signal;
|
|
||||||
};
|
|
||||||
export {
|
export {
|
||||||
assign,
|
assign,
|
||||||
assignAttribute,
|
assignAttribute,
|
||||||
|
4
dist/esm.min.d.ts
vendored
4
dist/esm.min.d.ts
vendored
@ -202,6 +202,10 @@ export const scope: {
|
|||||||
* — `scope.host(on.connected(console.log))`.
|
* — `scope.host(on.connected(console.log))`.
|
||||||
* */
|
* */
|
||||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||||
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
signal: AbortSignal;
|
||||||
state: Scope[];
|
state: Scope[];
|
||||||
/** Adds new child scope. All attributes are inherited by default. */
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||||
|
2
dist/esm.min.js
vendored
2
dist/esm.min.js
vendored
File diff suppressed because one or more lines are too long
4
dist/iife-with-signals.d.ts
vendored
4
dist/iife-with-signals.d.ts
vendored
@ -203,6 +203,10 @@ export const scope: {
|
|||||||
* — `scope.host(on.connected(console.log))`.
|
* — `scope.host(on.connected(console.log))`.
|
||||||
* */
|
* */
|
||||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||||
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
signal: AbortSignal;
|
||||||
state: Scope[];
|
state: Scope[];
|
||||||
/** Adds new child scope. All attributes are inherited by default. */
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||||
|
438
dist/iife-with-signals.js
vendored
438
dist/iife-with-signals.js
vendored
@ -156,6 +156,215 @@ var DDE = (() => {
|
|||||||
var evd = "dde:disconnected";
|
var evd = "dde:disconnected";
|
||||||
var eva = "dde:attributeChanged";
|
var eva = "dde:attributeChanged";
|
||||||
|
|
||||||
|
// src/events-observer.js
|
||||||
|
var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
|
||||||
|
get() {
|
||||||
|
return () => {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function connectionsChangesObserverConstructor() {
|
||||||
|
const store = /* @__PURE__ */ new Map();
|
||||||
|
let is_observing = false;
|
||||||
|
const observerListener = (stop2) => function(mutations) {
|
||||||
|
for (const mutation of mutations) {
|
||||||
|
if (mutation.type !== "childList") continue;
|
||||||
|
if (observerAdded(mutation.addedNodes, true)) {
|
||||||
|
stop2();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (observerRemoved(mutation.removedNodes, true))
|
||||||
|
stop2();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const observer = new enviroment.M(observerListener(stop));
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Creates an observer for a specific element
|
||||||
|
* @param {Element} element - Element to observe
|
||||||
|
* @returns {Function} Cleanup function
|
||||||
|
*/
|
||||||
|
observe(element) {
|
||||||
|
const o = new enviroment.M(observerListener(() => {
|
||||||
|
}));
|
||||||
|
o.observe(element, { childList: true, subtree: true });
|
||||||
|
return () => o.disconnect();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Register a connection listener for an element
|
||||||
|
* @param {Element} element - Element to watch
|
||||||
|
* @param {Function} listener - Callback for connection event
|
||||||
|
*/
|
||||||
|
onConnected(element, listener) {
|
||||||
|
start();
|
||||||
|
const listeners = getElementStore(element);
|
||||||
|
if (listeners.connected.has(listener)) return;
|
||||||
|
listeners.connected.add(listener);
|
||||||
|
listeners.length_c += 1;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Unregister a connection listener
|
||||||
|
* @param {Element} element - Element being watched
|
||||||
|
* @param {Function} listener - Callback to remove
|
||||||
|
*/
|
||||||
|
offConnected(element, listener) {
|
||||||
|
if (!store.has(element)) return;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.connected.has(listener)) return;
|
||||||
|
ls.connected.delete(listener);
|
||||||
|
ls.length_c -= 1;
|
||||||
|
cleanWhenOff(element, ls);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Register a disconnection listener for an element
|
||||||
|
* @param {Element} element - Element to watch
|
||||||
|
* @param {Function} listener - Callback for disconnection event
|
||||||
|
*/
|
||||||
|
onDisconnected(element, listener) {
|
||||||
|
start();
|
||||||
|
const listeners = getElementStore(element);
|
||||||
|
if (listeners.disconnected.has(listener)) return;
|
||||||
|
listeners.disconnected.add(listener);
|
||||||
|
listeners.length_d += 1;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Unregister a disconnection listener
|
||||||
|
* @param {Element} element - Element being watched
|
||||||
|
* @param {Function} listener - Callback to remove
|
||||||
|
*/
|
||||||
|
offDisconnected(element, listener) {
|
||||||
|
if (!store.has(element)) return;
|
||||||
|
const ls = store.get(element);
|
||||||
|
ls.disconnected.delete(listener);
|
||||||
|
ls.length_d -= 1;
|
||||||
|
cleanWhenOff(element, ls);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function cleanWhenOff(element, ls) {
|
||||||
|
if (ls.length_c || ls.length_d)
|
||||||
|
return;
|
||||||
|
store.delete(element);
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
function getElementStore(element) {
|
||||||
|
if (store.has(element)) return store.get(element);
|
||||||
|
const out = {
|
||||||
|
connected: /* @__PURE__ */ new WeakSet(),
|
||||||
|
length_c: 0,
|
||||||
|
disconnected: /* @__PURE__ */ new WeakSet(),
|
||||||
|
length_d: 0
|
||||||
|
};
|
||||||
|
store.set(element, out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function start() {
|
||||||
|
if (is_observing) return;
|
||||||
|
is_observing = true;
|
||||||
|
observer.observe(enviroment.D.body, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
function stop() {
|
||||||
|
if (!is_observing || store.size) return;
|
||||||
|
is_observing = false;
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
function requestIdle() {
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
(requestIdleCallback || requestAnimationFrame)(resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function collectChildren(element) {
|
||||||
|
if (store.size > 30)
|
||||||
|
await requestIdle();
|
||||||
|
const out = [];
|
||||||
|
if (!isInstance(element, Node)) return out;
|
||||||
|
for (const el of store.keys()) {
|
||||||
|
if (el === element || !isInstance(el, Node)) continue;
|
||||||
|
if (element.contains(el))
|
||||||
|
out.push(el);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function observerAdded(addedNodes, is_root) {
|
||||||
|
let out = false;
|
||||||
|
for (const element of addedNodes) {
|
||||||
|
if (is_root) collectChildren(element).then(observerAdded);
|
||||||
|
if (!store.has(element)) continue;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.length_c) continue;
|
||||||
|
element.dispatchEvent(new Event(evc));
|
||||||
|
ls.connected = /* @__PURE__ */ new WeakSet();
|
||||||
|
ls.length_c = 0;
|
||||||
|
if (!ls.length_d) store.delete(element);
|
||||||
|
out = true;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function observerRemoved(removedNodes, is_root) {
|
||||||
|
let out = false;
|
||||||
|
for (const element of removedNodes) {
|
||||||
|
if (is_root) collectChildren(element).then(observerRemoved);
|
||||||
|
if (!store.has(element)) continue;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.length_d) continue;
|
||||||
|
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));
|
||||||
|
out = true;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function dispatchRemove(element) {
|
||||||
|
return () => {
|
||||||
|
if (element.isConnected) return;
|
||||||
|
element.dispatchEvent(new Event(evd));
|
||||||
|
store.delete(element);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/events.js
|
||||||
|
function dispatchEvent(name, options, host) {
|
||||||
|
if (typeof options === "function") {
|
||||||
|
host = options;
|
||||||
|
options = null;
|
||||||
|
}
|
||||||
|
if (!options) options = {};
|
||||||
|
return function dispatch(element, ...d) {
|
||||||
|
if (host) {
|
||||||
|
d.unshift(element);
|
||||||
|
element = typeof host === "function" ? host() : host;
|
||||||
|
}
|
||||||
|
const event = d.length ? new CustomEvent(name, oAssign({ detail: d[0] }, options)) : new Event(name, options);
|
||||||
|
return element.dispatchEvent(event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function on(event, listener, options) {
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(event, listener, options);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var lifeOptions = (obj) => oAssign({}, typeof obj === "object" ? obj : null, { once: true });
|
||||||
|
on.connected = function(listener, options) {
|
||||||
|
options = lifeOptions(options);
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(evc, listener, options);
|
||||||
|
if (element[keyLTE]) return element;
|
||||||
|
if (element.isConnected) return element.dispatchEvent(new Event(evc)), element;
|
||||||
|
const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener));
|
||||||
|
if (c) c_ch_o.onConnected(element, listener);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
on.disconnected = function(listener, options) {
|
||||||
|
options = lifeOptions(options);
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(evd, listener, options);
|
||||||
|
if (element[keyLTE]) return element;
|
||||||
|
const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener));
|
||||||
|
if (c) c_ch_o.onDisconnected(element, listener);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// src/dom.js
|
// src/dom.js
|
||||||
function queue(promise) {
|
function queue(promise) {
|
||||||
return enviroment.q(promise);
|
return enviroment.q(promise);
|
||||||
@ -167,6 +376,7 @@ var DDE = (() => {
|
|||||||
host: (c) => c ? c(enviroment.D.body) : enviroment.D.body,
|
host: (c) => c ? c(enviroment.D.body) : enviroment.D.body,
|
||||||
prevent: true
|
prevent: true
|
||||||
}];
|
}];
|
||||||
|
var store_abort = /* @__PURE__ */ new WeakMap();
|
||||||
var scope = {
|
var scope = {
|
||||||
/**
|
/**
|
||||||
* Gets the current scope
|
* Gets the current scope
|
||||||
@ -183,6 +393,17 @@ var DDE = (() => {
|
|||||||
return this.current.host;
|
return this.current.host;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
get signal() {
|
||||||
|
const { host } = this;
|
||||||
|
if (store_abort.has(host)) return store_abort.get(host);
|
||||||
|
const a = new AbortController();
|
||||||
|
store_abort.set(host, a);
|
||||||
|
host(on.disconnected(() => a.abort()));
|
||||||
|
return a.signal;
|
||||||
|
},
|
||||||
|
/**
|
||||||
* Prevents default behavior in the current scope
|
* Prevents default behavior in the current scope
|
||||||
* @returns {Object} Current scope context
|
* @returns {Object} Current scope context
|
||||||
*/
|
*/
|
||||||
@ -425,170 +646,6 @@ var DDE = (() => {
|
|||||||
return Reflect.deleteProperty(obj, key);
|
return Reflect.deleteProperty(obj, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/events-observer.js
|
|
||||||
var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
|
|
||||||
get() {
|
|
||||||
return () => {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
function connectionsChangesObserverConstructor() {
|
|
||||||
const store = /* @__PURE__ */ new Map();
|
|
||||||
let is_observing = false;
|
|
||||||
const observerListener = (stop2) => function(mutations) {
|
|
||||||
for (const mutation of mutations) {
|
|
||||||
if (mutation.type !== "childList") continue;
|
|
||||||
if (observerAdded(mutation.addedNodes, true)) {
|
|
||||||
stop2();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (observerRemoved(mutation.removedNodes, true))
|
|
||||||
stop2();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const observer = new enviroment.M(observerListener(stop));
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Creates an observer for a specific element
|
|
||||||
* @param {Element} element - Element to observe
|
|
||||||
* @returns {Function} Cleanup function
|
|
||||||
*/
|
|
||||||
observe(element) {
|
|
||||||
const o = new enviroment.M(observerListener(() => {
|
|
||||||
}));
|
|
||||||
o.observe(element, { childList: true, subtree: true });
|
|
||||||
return () => o.disconnect();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Register a connection listener for an element
|
|
||||||
* @param {Element} element - Element to watch
|
|
||||||
* @param {Function} listener - Callback for connection event
|
|
||||||
*/
|
|
||||||
onConnected(element, listener) {
|
|
||||||
start();
|
|
||||||
const listeners = getElementStore(element);
|
|
||||||
if (listeners.connected.has(listener)) return;
|
|
||||||
listeners.connected.add(listener);
|
|
||||||
listeners.length_c += 1;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Unregister a connection listener
|
|
||||||
* @param {Element} element - Element being watched
|
|
||||||
* @param {Function} listener - Callback to remove
|
|
||||||
*/
|
|
||||||
offConnected(element, listener) {
|
|
||||||
if (!store.has(element)) return;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.connected.has(listener)) return;
|
|
||||||
ls.connected.delete(listener);
|
|
||||||
ls.length_c -= 1;
|
|
||||||
cleanWhenOff(element, ls);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Register a disconnection listener for an element
|
|
||||||
* @param {Element} element - Element to watch
|
|
||||||
* @param {Function} listener - Callback for disconnection event
|
|
||||||
*/
|
|
||||||
onDisconnected(element, listener) {
|
|
||||||
start();
|
|
||||||
const listeners = getElementStore(element);
|
|
||||||
if (listeners.disconnected.has(listener)) return;
|
|
||||||
listeners.disconnected.add(listener);
|
|
||||||
listeners.length_d += 1;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Unregister a disconnection listener
|
|
||||||
* @param {Element} element - Element being watched
|
|
||||||
* @param {Function} listener - Callback to remove
|
|
||||||
*/
|
|
||||||
offDisconnected(element, listener) {
|
|
||||||
if (!store.has(element)) return;
|
|
||||||
const ls = store.get(element);
|
|
||||||
ls.disconnected.delete(listener);
|
|
||||||
ls.length_d -= 1;
|
|
||||||
cleanWhenOff(element, ls);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
function cleanWhenOff(element, ls) {
|
|
||||||
if (ls.length_c || ls.length_d)
|
|
||||||
return;
|
|
||||||
store.delete(element);
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
function getElementStore(element) {
|
|
||||||
if (store.has(element)) return store.get(element);
|
|
||||||
const out = {
|
|
||||||
connected: /* @__PURE__ */ new WeakSet(),
|
|
||||||
length_c: 0,
|
|
||||||
disconnected: /* @__PURE__ */ new WeakSet(),
|
|
||||||
length_d: 0
|
|
||||||
};
|
|
||||||
store.set(element, out);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function start() {
|
|
||||||
if (is_observing) return;
|
|
||||||
is_observing = true;
|
|
||||||
observer.observe(enviroment.D.body, { childList: true, subtree: true });
|
|
||||||
}
|
|
||||||
function stop() {
|
|
||||||
if (!is_observing || store.size) return;
|
|
||||||
is_observing = false;
|
|
||||||
observer.disconnect();
|
|
||||||
}
|
|
||||||
function requestIdle() {
|
|
||||||
return new Promise(function(resolve) {
|
|
||||||
(requestIdleCallback || requestAnimationFrame)(resolve);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async function collectChildren(element) {
|
|
||||||
if (store.size > 30)
|
|
||||||
await requestIdle();
|
|
||||||
const out = [];
|
|
||||||
if (!isInstance(element, Node)) return out;
|
|
||||||
for (const el of store.keys()) {
|
|
||||||
if (el === element || !isInstance(el, Node)) continue;
|
|
||||||
if (element.contains(el))
|
|
||||||
out.push(el);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function observerAdded(addedNodes, is_root) {
|
|
||||||
let out = false;
|
|
||||||
for (const element of addedNodes) {
|
|
||||||
if (is_root) collectChildren(element).then(observerAdded);
|
|
||||||
if (!store.has(element)) continue;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.length_c) continue;
|
|
||||||
element.dispatchEvent(new Event(evc));
|
|
||||||
ls.connected = /* @__PURE__ */ new WeakSet();
|
|
||||||
ls.length_c = 0;
|
|
||||||
if (!ls.length_d) store.delete(element);
|
|
||||||
out = true;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function observerRemoved(removedNodes, is_root) {
|
|
||||||
let out = false;
|
|
||||||
for (const element of removedNodes) {
|
|
||||||
if (is_root) collectChildren(element).then(observerRemoved);
|
|
||||||
if (!store.has(element)) continue;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.length_d) continue;
|
|
||||||
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));
|
|
||||||
out = true;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function dispatchRemove(element) {
|
|
||||||
return () => {
|
|
||||||
if (element.isConnected) return;
|
|
||||||
element.dispatchEvent(new Event(evd));
|
|
||||||
store.delete(element);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// src/customElement.js
|
// src/customElement.js
|
||||||
function customElementRender(target, render, props = {}) {
|
function customElementRender(target, render, props = {}) {
|
||||||
const custom_element = target.host || target;
|
const custom_element = target.host || target;
|
||||||
@ -632,59 +689,6 @@ var DDE = (() => {
|
|||||||
}), { apply });
|
}), { apply });
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/events.js
|
|
||||||
function dispatchEvent(name, options, host) {
|
|
||||||
if (typeof options === "function") {
|
|
||||||
host = options;
|
|
||||||
options = null;
|
|
||||||
}
|
|
||||||
if (!options) options = {};
|
|
||||||
return function dispatch(element, ...d) {
|
|
||||||
if (host) {
|
|
||||||
d.unshift(element);
|
|
||||||
element = typeof host === "function" ? host() : host;
|
|
||||||
}
|
|
||||||
const event = d.length ? new CustomEvent(name, oAssign({ detail: d[0] }, options)) : new Event(name, options);
|
|
||||||
return element.dispatchEvent(event);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function on(event, listener, options) {
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(event, listener, options);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var lifeOptions = (obj) => oAssign({}, typeof obj === "object" ? obj : null, { once: true });
|
|
||||||
on.connected = function(listener, options) {
|
|
||||||
options = lifeOptions(options);
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(evc, listener, options);
|
|
||||||
if (element[keyLTE]) return element;
|
|
||||||
if (element.isConnected) return element.dispatchEvent(new Event(evc)), element;
|
|
||||||
const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener));
|
|
||||||
if (c) c_ch_o.onConnected(element, listener);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
on.disconnected = function(listener, options) {
|
|
||||||
options = lifeOptions(options);
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(evd, listener, options);
|
|
||||||
if (element[keyLTE]) return element;
|
|
||||||
const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener));
|
|
||||||
if (c) c_ch_o.onDisconnected(element, listener);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
var store_abort = /* @__PURE__ */ new WeakMap();
|
|
||||||
on.disconnectedAsAbort = function(host) {
|
|
||||||
if (store_abort.has(host)) return store_abort.get(host);
|
|
||||||
const a = new AbortController();
|
|
||||||
store_abort.set(host, a);
|
|
||||||
host(on.disconnected(() => a.abort()));
|
|
||||||
return a.signal;
|
|
||||||
};
|
|
||||||
|
|
||||||
// src/signals-lib/helpers.js
|
// src/signals-lib/helpers.js
|
||||||
var mark = "__dde_signal";
|
var mark = "__dde_signal";
|
||||||
var queueSignalWrite = /* @__PURE__ */ (() => {
|
var queueSignalWrite = /* @__PURE__ */ (() => {
|
||||||
|
4
dist/iife-with-signals.min.d.ts
vendored
4
dist/iife-with-signals.min.d.ts
vendored
@ -203,6 +203,10 @@ export const scope: {
|
|||||||
* — `scope.host(on.connected(console.log))`.
|
* — `scope.host(on.connected(console.log))`.
|
||||||
* */
|
* */
|
||||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||||
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
signal: AbortSignal;
|
||||||
state: Scope[];
|
state: Scope[];
|
||||||
/** Adds new child scope. All attributes are inherited by default. */
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||||
|
8
dist/iife-with-signals.min.js
vendored
8
dist/iife-with-signals.min.js
vendored
File diff suppressed because one or more lines are too long
4
dist/iife.d.ts
vendored
4
dist/iife.d.ts
vendored
@ -202,6 +202,10 @@ export const scope: {
|
|||||||
* — `scope.host(on.connected(console.log))`.
|
* — `scope.host(on.connected(console.log))`.
|
||||||
* */
|
* */
|
||||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||||
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
signal: AbortSignal;
|
||||||
state: Scope[];
|
state: Scope[];
|
||||||
/** Adds new child scope. All attributes are inherited by default. */
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||||
|
438
dist/iife.js
vendored
438
dist/iife.js
vendored
@ -120,6 +120,215 @@ var DDE = (() => {
|
|||||||
var evd = "dde:disconnected";
|
var evd = "dde:disconnected";
|
||||||
var eva = "dde:attributeChanged";
|
var eva = "dde:attributeChanged";
|
||||||
|
|
||||||
|
// src/events-observer.js
|
||||||
|
var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
|
||||||
|
get() {
|
||||||
|
return () => {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
function connectionsChangesObserverConstructor() {
|
||||||
|
const store = /* @__PURE__ */ new Map();
|
||||||
|
let is_observing = false;
|
||||||
|
const observerListener = (stop2) => function(mutations) {
|
||||||
|
for (const mutation of mutations) {
|
||||||
|
if (mutation.type !== "childList") continue;
|
||||||
|
if (observerAdded(mutation.addedNodes, true)) {
|
||||||
|
stop2();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (observerRemoved(mutation.removedNodes, true))
|
||||||
|
stop2();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const observer = new enviroment.M(observerListener(stop));
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Creates an observer for a specific element
|
||||||
|
* @param {Element} element - Element to observe
|
||||||
|
* @returns {Function} Cleanup function
|
||||||
|
*/
|
||||||
|
observe(element) {
|
||||||
|
const o = new enviroment.M(observerListener(() => {
|
||||||
|
}));
|
||||||
|
o.observe(element, { childList: true, subtree: true });
|
||||||
|
return () => o.disconnect();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Register a connection listener for an element
|
||||||
|
* @param {Element} element - Element to watch
|
||||||
|
* @param {Function} listener - Callback for connection event
|
||||||
|
*/
|
||||||
|
onConnected(element, listener) {
|
||||||
|
start();
|
||||||
|
const listeners = getElementStore(element);
|
||||||
|
if (listeners.connected.has(listener)) return;
|
||||||
|
listeners.connected.add(listener);
|
||||||
|
listeners.length_c += 1;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Unregister a connection listener
|
||||||
|
* @param {Element} element - Element being watched
|
||||||
|
* @param {Function} listener - Callback to remove
|
||||||
|
*/
|
||||||
|
offConnected(element, listener) {
|
||||||
|
if (!store.has(element)) return;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.connected.has(listener)) return;
|
||||||
|
ls.connected.delete(listener);
|
||||||
|
ls.length_c -= 1;
|
||||||
|
cleanWhenOff(element, ls);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Register a disconnection listener for an element
|
||||||
|
* @param {Element} element - Element to watch
|
||||||
|
* @param {Function} listener - Callback for disconnection event
|
||||||
|
*/
|
||||||
|
onDisconnected(element, listener) {
|
||||||
|
start();
|
||||||
|
const listeners = getElementStore(element);
|
||||||
|
if (listeners.disconnected.has(listener)) return;
|
||||||
|
listeners.disconnected.add(listener);
|
||||||
|
listeners.length_d += 1;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Unregister a disconnection listener
|
||||||
|
* @param {Element} element - Element being watched
|
||||||
|
* @param {Function} listener - Callback to remove
|
||||||
|
*/
|
||||||
|
offDisconnected(element, listener) {
|
||||||
|
if (!store.has(element)) return;
|
||||||
|
const ls = store.get(element);
|
||||||
|
ls.disconnected.delete(listener);
|
||||||
|
ls.length_d -= 1;
|
||||||
|
cleanWhenOff(element, ls);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function cleanWhenOff(element, ls) {
|
||||||
|
if (ls.length_c || ls.length_d)
|
||||||
|
return;
|
||||||
|
store.delete(element);
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
function getElementStore(element) {
|
||||||
|
if (store.has(element)) return store.get(element);
|
||||||
|
const out = {
|
||||||
|
connected: /* @__PURE__ */ new WeakSet(),
|
||||||
|
length_c: 0,
|
||||||
|
disconnected: /* @__PURE__ */ new WeakSet(),
|
||||||
|
length_d: 0
|
||||||
|
};
|
||||||
|
store.set(element, out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function start() {
|
||||||
|
if (is_observing) return;
|
||||||
|
is_observing = true;
|
||||||
|
observer.observe(enviroment.D.body, { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
function stop() {
|
||||||
|
if (!is_observing || store.size) return;
|
||||||
|
is_observing = false;
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
function requestIdle() {
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
(requestIdleCallback || requestAnimationFrame)(resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function collectChildren(element) {
|
||||||
|
if (store.size > 30)
|
||||||
|
await requestIdle();
|
||||||
|
const out = [];
|
||||||
|
if (!isInstance(element, Node)) return out;
|
||||||
|
for (const el of store.keys()) {
|
||||||
|
if (el === element || !isInstance(el, Node)) continue;
|
||||||
|
if (element.contains(el))
|
||||||
|
out.push(el);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function observerAdded(addedNodes, is_root) {
|
||||||
|
let out = false;
|
||||||
|
for (const element of addedNodes) {
|
||||||
|
if (is_root) collectChildren(element).then(observerAdded);
|
||||||
|
if (!store.has(element)) continue;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.length_c) continue;
|
||||||
|
element.dispatchEvent(new Event(evc));
|
||||||
|
ls.connected = /* @__PURE__ */ new WeakSet();
|
||||||
|
ls.length_c = 0;
|
||||||
|
if (!ls.length_d) store.delete(element);
|
||||||
|
out = true;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function observerRemoved(removedNodes, is_root) {
|
||||||
|
let out = false;
|
||||||
|
for (const element of removedNodes) {
|
||||||
|
if (is_root) collectChildren(element).then(observerRemoved);
|
||||||
|
if (!store.has(element)) continue;
|
||||||
|
const ls = store.get(element);
|
||||||
|
if (!ls.length_d) continue;
|
||||||
|
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));
|
||||||
|
out = true;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function dispatchRemove(element) {
|
||||||
|
return () => {
|
||||||
|
if (element.isConnected) return;
|
||||||
|
element.dispatchEvent(new Event(evd));
|
||||||
|
store.delete(element);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/events.js
|
||||||
|
function dispatchEvent(name, options, host) {
|
||||||
|
if (typeof options === "function") {
|
||||||
|
host = options;
|
||||||
|
options = null;
|
||||||
|
}
|
||||||
|
if (!options) options = {};
|
||||||
|
return function dispatch(element, ...d) {
|
||||||
|
if (host) {
|
||||||
|
d.unshift(element);
|
||||||
|
element = typeof host === "function" ? host() : host;
|
||||||
|
}
|
||||||
|
const event = d.length ? new CustomEvent(name, oAssign({ detail: d[0] }, options)) : new Event(name, options);
|
||||||
|
return element.dispatchEvent(event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function on(event, listener, options) {
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(event, listener, options);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var lifeOptions = (obj) => oAssign({}, typeof obj === "object" ? obj : null, { once: true });
|
||||||
|
on.connected = function(listener, options) {
|
||||||
|
options = lifeOptions(options);
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(evc, listener, options);
|
||||||
|
if (element[keyLTE]) return element;
|
||||||
|
if (element.isConnected) return element.dispatchEvent(new Event(evc)), element;
|
||||||
|
const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener));
|
||||||
|
if (c) c_ch_o.onConnected(element, listener);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
on.disconnected = function(listener, options) {
|
||||||
|
options = lifeOptions(options);
|
||||||
|
return function registerElement(element) {
|
||||||
|
element.addEventListener(evd, listener, options);
|
||||||
|
if (element[keyLTE]) return element;
|
||||||
|
const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener));
|
||||||
|
if (c) c_ch_o.onDisconnected(element, listener);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// src/dom.js
|
// src/dom.js
|
||||||
function queue(promise) {
|
function queue(promise) {
|
||||||
return enviroment.q(promise);
|
return enviroment.q(promise);
|
||||||
@ -131,6 +340,7 @@ var DDE = (() => {
|
|||||||
host: (c) => c ? c(enviroment.D.body) : enviroment.D.body,
|
host: (c) => c ? c(enviroment.D.body) : enviroment.D.body,
|
||||||
prevent: true
|
prevent: true
|
||||||
}];
|
}];
|
||||||
|
var store_abort = /* @__PURE__ */ new WeakMap();
|
||||||
var scope = {
|
var scope = {
|
||||||
/**
|
/**
|
||||||
* Gets the current scope
|
* Gets the current scope
|
||||||
@ -147,6 +357,17 @@ var DDE = (() => {
|
|||||||
return this.current.host;
|
return this.current.host;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
get signal() {
|
||||||
|
const { host } = this;
|
||||||
|
if (store_abort.has(host)) return store_abort.get(host);
|
||||||
|
const a = new AbortController();
|
||||||
|
store_abort.set(host, a);
|
||||||
|
host(on.disconnected(() => a.abort()));
|
||||||
|
return a.signal;
|
||||||
|
},
|
||||||
|
/**
|
||||||
* Prevents default behavior in the current scope
|
* Prevents default behavior in the current scope
|
||||||
* @returns {Object} Current scope context
|
* @returns {Object} Current scope context
|
||||||
*/
|
*/
|
||||||
@ -389,170 +610,6 @@ var DDE = (() => {
|
|||||||
return Reflect.deleteProperty(obj, key);
|
return Reflect.deleteProperty(obj, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/events-observer.js
|
|
||||||
var c_ch_o = enviroment.M ? connectionsChangesObserverConstructor() : new Proxy({}, {
|
|
||||||
get() {
|
|
||||||
return () => {
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
function connectionsChangesObserverConstructor() {
|
|
||||||
const store = /* @__PURE__ */ new Map();
|
|
||||||
let is_observing = false;
|
|
||||||
const observerListener = (stop2) => function(mutations) {
|
|
||||||
for (const mutation of mutations) {
|
|
||||||
if (mutation.type !== "childList") continue;
|
|
||||||
if (observerAdded(mutation.addedNodes, true)) {
|
|
||||||
stop2();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (observerRemoved(mutation.removedNodes, true))
|
|
||||||
stop2();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const observer = new enviroment.M(observerListener(stop));
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Creates an observer for a specific element
|
|
||||||
* @param {Element} element - Element to observe
|
|
||||||
* @returns {Function} Cleanup function
|
|
||||||
*/
|
|
||||||
observe(element) {
|
|
||||||
const o = new enviroment.M(observerListener(() => {
|
|
||||||
}));
|
|
||||||
o.observe(element, { childList: true, subtree: true });
|
|
||||||
return () => o.disconnect();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Register a connection listener for an element
|
|
||||||
* @param {Element} element - Element to watch
|
|
||||||
* @param {Function} listener - Callback for connection event
|
|
||||||
*/
|
|
||||||
onConnected(element, listener) {
|
|
||||||
start();
|
|
||||||
const listeners = getElementStore(element);
|
|
||||||
if (listeners.connected.has(listener)) return;
|
|
||||||
listeners.connected.add(listener);
|
|
||||||
listeners.length_c += 1;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Unregister a connection listener
|
|
||||||
* @param {Element} element - Element being watched
|
|
||||||
* @param {Function} listener - Callback to remove
|
|
||||||
*/
|
|
||||||
offConnected(element, listener) {
|
|
||||||
if (!store.has(element)) return;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.connected.has(listener)) return;
|
|
||||||
ls.connected.delete(listener);
|
|
||||||
ls.length_c -= 1;
|
|
||||||
cleanWhenOff(element, ls);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Register a disconnection listener for an element
|
|
||||||
* @param {Element} element - Element to watch
|
|
||||||
* @param {Function} listener - Callback for disconnection event
|
|
||||||
*/
|
|
||||||
onDisconnected(element, listener) {
|
|
||||||
start();
|
|
||||||
const listeners = getElementStore(element);
|
|
||||||
if (listeners.disconnected.has(listener)) return;
|
|
||||||
listeners.disconnected.add(listener);
|
|
||||||
listeners.length_d += 1;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Unregister a disconnection listener
|
|
||||||
* @param {Element} element - Element being watched
|
|
||||||
* @param {Function} listener - Callback to remove
|
|
||||||
*/
|
|
||||||
offDisconnected(element, listener) {
|
|
||||||
if (!store.has(element)) return;
|
|
||||||
const ls = store.get(element);
|
|
||||||
ls.disconnected.delete(listener);
|
|
||||||
ls.length_d -= 1;
|
|
||||||
cleanWhenOff(element, ls);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
function cleanWhenOff(element, ls) {
|
|
||||||
if (ls.length_c || ls.length_d)
|
|
||||||
return;
|
|
||||||
store.delete(element);
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
function getElementStore(element) {
|
|
||||||
if (store.has(element)) return store.get(element);
|
|
||||||
const out = {
|
|
||||||
connected: /* @__PURE__ */ new WeakSet(),
|
|
||||||
length_c: 0,
|
|
||||||
disconnected: /* @__PURE__ */ new WeakSet(),
|
|
||||||
length_d: 0
|
|
||||||
};
|
|
||||||
store.set(element, out);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function start() {
|
|
||||||
if (is_observing) return;
|
|
||||||
is_observing = true;
|
|
||||||
observer.observe(enviroment.D.body, { childList: true, subtree: true });
|
|
||||||
}
|
|
||||||
function stop() {
|
|
||||||
if (!is_observing || store.size) return;
|
|
||||||
is_observing = false;
|
|
||||||
observer.disconnect();
|
|
||||||
}
|
|
||||||
function requestIdle() {
|
|
||||||
return new Promise(function(resolve) {
|
|
||||||
(requestIdleCallback || requestAnimationFrame)(resolve);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async function collectChildren(element) {
|
|
||||||
if (store.size > 30)
|
|
||||||
await requestIdle();
|
|
||||||
const out = [];
|
|
||||||
if (!isInstance(element, Node)) return out;
|
|
||||||
for (const el of store.keys()) {
|
|
||||||
if (el === element || !isInstance(el, Node)) continue;
|
|
||||||
if (element.contains(el))
|
|
||||||
out.push(el);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function observerAdded(addedNodes, is_root) {
|
|
||||||
let out = false;
|
|
||||||
for (const element of addedNodes) {
|
|
||||||
if (is_root) collectChildren(element).then(observerAdded);
|
|
||||||
if (!store.has(element)) continue;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.length_c) continue;
|
|
||||||
element.dispatchEvent(new Event(evc));
|
|
||||||
ls.connected = /* @__PURE__ */ new WeakSet();
|
|
||||||
ls.length_c = 0;
|
|
||||||
if (!ls.length_d) store.delete(element);
|
|
||||||
out = true;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function observerRemoved(removedNodes, is_root) {
|
|
||||||
let out = false;
|
|
||||||
for (const element of removedNodes) {
|
|
||||||
if (is_root) collectChildren(element).then(observerRemoved);
|
|
||||||
if (!store.has(element)) continue;
|
|
||||||
const ls = store.get(element);
|
|
||||||
if (!ls.length_d) continue;
|
|
||||||
(globalThis.queueMicrotask || setTimeout)(dispatchRemove(element));
|
|
||||||
out = true;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
function dispatchRemove(element) {
|
|
||||||
return () => {
|
|
||||||
if (element.isConnected) return;
|
|
||||||
element.dispatchEvent(new Event(evd));
|
|
||||||
store.delete(element);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// src/customElement.js
|
// src/customElement.js
|
||||||
function customElementRender(target, render, props = {}) {
|
function customElementRender(target, render, props = {}) {
|
||||||
const custom_element = target.host || target;
|
const custom_element = target.host || target;
|
||||||
@ -595,58 +652,5 @@ var DDE = (() => {
|
|||||||
obj[method] = new Proxy(obj[method] || (() => {
|
obj[method] = new Proxy(obj[method] || (() => {
|
||||||
}), { apply });
|
}), { apply });
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/events.js
|
|
||||||
function dispatchEvent(name, options, host) {
|
|
||||||
if (typeof options === "function") {
|
|
||||||
host = options;
|
|
||||||
options = null;
|
|
||||||
}
|
|
||||||
if (!options) options = {};
|
|
||||||
return function dispatch(element, ...d) {
|
|
||||||
if (host) {
|
|
||||||
d.unshift(element);
|
|
||||||
element = typeof host === "function" ? host() : host;
|
|
||||||
}
|
|
||||||
const event = d.length ? new CustomEvent(name, oAssign({ detail: d[0] }, options)) : new Event(name, options);
|
|
||||||
return element.dispatchEvent(event);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
function on(event, listener, options) {
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(event, listener, options);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var lifeOptions = (obj) => oAssign({}, typeof obj === "object" ? obj : null, { once: true });
|
|
||||||
on.connected = function(listener, options) {
|
|
||||||
options = lifeOptions(options);
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(evc, listener, options);
|
|
||||||
if (element[keyLTE]) return element;
|
|
||||||
if (element.isConnected) return element.dispatchEvent(new Event(evc)), element;
|
|
||||||
const c = onAbort(options.signal, () => c_ch_o.offConnected(element, listener));
|
|
||||||
if (c) c_ch_o.onConnected(element, listener);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
on.disconnected = function(listener, options) {
|
|
||||||
options = lifeOptions(options);
|
|
||||||
return function registerElement(element) {
|
|
||||||
element.addEventListener(evd, listener, options);
|
|
||||||
if (element[keyLTE]) return element;
|
|
||||||
const c = onAbort(options.signal, () => c_ch_o.offDisconnected(element, listener));
|
|
||||||
if (c) c_ch_o.onDisconnected(element, listener);
|
|
||||||
return element;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
var store_abort = /* @__PURE__ */ new WeakMap();
|
|
||||||
on.disconnectedAsAbort = function(host) {
|
|
||||||
if (store_abort.has(host)) return store_abort.get(host);
|
|
||||||
const a = new AbortController();
|
|
||||||
store_abort.set(host, a);
|
|
||||||
host(on.disconnected(() => a.abort()));
|
|
||||||
return a.signal;
|
|
||||||
};
|
|
||||||
return __toCommonJS(index_exports);
|
return __toCommonJS(index_exports);
|
||||||
})();
|
})();
|
||||||
|
4
dist/iife.min.d.ts
vendored
4
dist/iife.min.d.ts
vendored
@ -202,6 +202,10 @@ export const scope: {
|
|||||||
* — `scope.host(on.connected(console.log))`.
|
* — `scope.host(on.connected(console.log))`.
|
||||||
* */
|
* */
|
||||||
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
host: (...addons: ddeElementAddon<SupportedElement>[]) => HTMLElement;
|
||||||
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
signal: AbortSignal;
|
||||||
state: Scope[];
|
state: Scope[];
|
||||||
/** Adds new child scope. All attributes are inherited by default. */
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>;
|
||||||
|
2
dist/iife.min.js
vendored
2
dist/iife.min.js
vendored
File diff suppressed because one or more lines are too long
@ -14,6 +14,10 @@ export function mnemonic(){
|
|||||||
el("li").append(
|
el("li").append(
|
||||||
el("code", "scope.host(...<addons>)"),
|
el("code", "scope.host(...<addons>)"),
|
||||||
" — use addons to current component",
|
" — use addons to current component",
|
||||||
|
),
|
||||||
|
el("li").append(
|
||||||
|
el("code", "scope.signal"),
|
||||||
|
" — get AbortSignal that triggers when the element disconnects",
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ el("div", { id: "example" }, myAddon({ option: "value" }));
|
|||||||
`),
|
`),
|
||||||
el("div", { className: "tip" }).append(
|
el("div", { className: "tip" }).append(
|
||||||
el("p").append(...T`
|
el("p").append(...T`
|
||||||
The ${el("code", "on.disconnectedAsAbort")} utility creates an AbortSignal that automatically
|
The ${el("code", "scope.signal")} property creates an AbortSignal that automatically
|
||||||
triggers when an element is disconnected from the DOM, making cleanup much easier to manage.
|
triggers when an element is disconnected from the DOM, making cleanup much easier to manage.
|
||||||
`)
|
`)
|
||||||
),
|
),
|
||||||
@ -80,8 +80,7 @@ function externalLibraryAddon(config, signal) {
|
|||||||
}
|
}
|
||||||
// dde component
|
// dde component
|
||||||
function Component(){
|
function Component(){
|
||||||
const { host }= scope;
|
const { signal }= scope;
|
||||||
const signal= on.disconnectedAsAbort(host);
|
|
||||||
return el("div", null, externalLibraryAddon({ option: "value" }, signal));
|
return el("div", null, externalLibraryAddon({ option: "value" }, signal));
|
||||||
}
|
}
|
||||||
`.trim(), page_id }),
|
`.trim(), page_id }),
|
||||||
@ -213,7 +212,7 @@ console.log(doubled.get()); // 10`, page_id }),
|
|||||||
el("ol").append(
|
el("ol").append(
|
||||||
el("li").append(...T`
|
el("li").append(...T`
|
||||||
${el("strong", "Use AbortSignals for cleanup:")} Always implement proper resource cleanup with
|
${el("strong", "Use AbortSignals for cleanup:")} Always implement proper resource cleanup with
|
||||||
${el("code", "on.disconnectedAsAbort")} or similar mechanisms
|
${el("code", "scope.signal")} or similar mechanisms
|
||||||
`),
|
`),
|
||||||
el("li").append(...T`
|
el("li").append(...T`
|
||||||
${el("strong", "Separate core logic from library adaptation:")} Make your core functionality work
|
${el("strong", "Separate core logic from library adaptation:")} Make your core functionality work
|
||||||
|
5
index.d.ts
vendored
5
index.d.ts
vendored
@ -243,6 +243,11 @@ export const scope: {
|
|||||||
* */
|
* */
|
||||||
host: (...addons: ddeElementAddon<SupportedElement>[])=> HTMLElement,
|
host: (...addons: ddeElementAddon<SupportedElement>[])=> HTMLElement,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
signal: AbortSignal,
|
||||||
|
|
||||||
state: Scope[],
|
state: Scope[],
|
||||||
/** Adds new child scope. All attributes are inherited by default. */
|
/** Adds new child scope. All attributes are inherited by default. */
|
||||||
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>,
|
push(scope?: Partial<Scope>): ReturnType<Array<Scope>["push"]>,
|
||||||
|
16
src/dom.js
16
src/dom.js
@ -1,6 +1,7 @@
|
|||||||
import { signals } from "./signals-lib/common.js";
|
import { signals } from "./signals-lib/common.js";
|
||||||
import { enviroment as env } from './dom-common.js';
|
import { enviroment as env } from './dom-common.js';
|
||||||
import { isInstance, isUndef, oAssign } from "./helpers.js";
|
import { isInstance, isUndef, oAssign } from "./helpers.js";
|
||||||
|
import { on } from "./events.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queues a promise, this is helpful for crossplatform components (on server side we can wait for all registered
|
* Queues a promise, this is helpful for crossplatform components (on server side we can wait for all registered
|
||||||
@ -19,6 +20,8 @@ const scopes= [ {
|
|||||||
host: c=> c ? c(env.D.body) : env.D.body,
|
host: c=> c ? c(env.D.body) : env.D.body,
|
||||||
prevent: true,
|
prevent: true,
|
||||||
} ];
|
} ];
|
||||||
|
/** Store for disconnect abort controllers */
|
||||||
|
const store_abort= new WeakMap();
|
||||||
/**
|
/**
|
||||||
* Scope management utility for tracking component hierarchies
|
* Scope management utility for tracking component hierarchies
|
||||||
*/
|
*/
|
||||||
@ -35,6 +38,19 @@ export const scope= {
|
|||||||
*/
|
*/
|
||||||
get host(){ return this.current.host; },
|
get host(){ return this.current.host; },
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates/gets an AbortController that triggers when the element disconnects
|
||||||
|
* */
|
||||||
|
get signal(){
|
||||||
|
const { host }= this;
|
||||||
|
if(store_abort.has(host)) return store_abort.get(host);
|
||||||
|
|
||||||
|
const a= new AbortController();
|
||||||
|
store_abort.set(host, a);
|
||||||
|
host(on.disconnected(()=> a.abort()));
|
||||||
|
return a.signal;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevents default behavior in the current scope
|
* Prevents default behavior in the current scope
|
||||||
* @returns {Object} Current scope context
|
* @returns {Object} Current scope context
|
||||||
|
@ -88,21 +88,3 @@ on.disconnected= function(listener, options){
|
|||||||
return element;
|
return element;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Store for disconnect abort controllers */
|
|
||||||
const store_abort= new WeakMap();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an AbortController that triggers when the element disconnects
|
|
||||||
*
|
|
||||||
* @param {Function} host - Host element or function taking an element
|
|
||||||
* @returns {AbortSignal} AbortSignal that aborts on disconnect
|
|
||||||
*/
|
|
||||||
on.disconnectedAsAbort= function(host){
|
|
||||||
if(store_abort.has(host)) return store_abort.get(host);
|
|
||||||
|
|
||||||
const a= new AbortController();
|
|
||||||
store_abort.set(host, a);
|
|
||||||
host(on.disconnected(()=> a.abort()));
|
|
||||||
return a.signal;
|
|
||||||
};
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user