1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2025-07-02 04:32:14 +02:00
Files
deka-dom-el/src/dom-lib/scopes.js
2025-03-14 13:15:31 +01:00

85 lines
2.1 KiB
JavaScript

import { enviroment as env } from './common.js';
import { oAssign } from "../helpers.js";
import { on } from "./events.js";
/**
* Array of scope contexts for tracking component hierarchies
* @type {{ scope: object, prevent: boolean, host: function }[]}
*/
const scopes= [ {
get scope(){ return env.D.body; },
host: c=> c ? c(env.D.body) : env.D.body,
prevent: true,
} ];
/** Store for disconnect abort controllers */
const store_abort= new WeakMap();
/**
* Scope management utility for tracking component hierarchies
*/
export const scope= {
/**
* Gets the current scope
* @returns {Object} Current scope context
*/
get current(){ return scopes[scopes.length-1]; },
/**
* Gets the host element of the current scope
* @returns {Function} Host accessor function
*/
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
* @returns {Object} Current scope context
*/
preventDefault(){
const { current }= this;
current.prevent= true;
return current;
},
/**
* Gets a copy of the current scope stack
* @returns {Array} Copy of scope stack
*/
get state(){ return [ ...scopes ]; },
/**
* Pushes a new scope to the stack
* @param {Object} [s={}] - Scope object to push
* @returns {number} New length of the scope stack
*/
push(s= {}){ return scopes.push(oAssign({}, this.current, { prevent: false }, s)); },
/**
* Pushes the root scope to the stack
* @returns {number} New length of the scope stack
*/
pushRoot(){ return scopes.push(scopes[0]); },
/**
* Pops the current scope from the stack
* @returns {Object|undefined} Popped scope or undefined if only one scope remains
*/
pop(){
if(scopes.length===1) return;
return scopes.pop();
},
};
// TODO: better place while no cross-import?
on.host= (fn, host= scope.host)=> el=> host(()=> fn(el));