You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
2.1 KiB
89 lines
2.1 KiB
|
|
export function scope(node) {
|
|
return mergeProxies(closestDataStack(node))
|
|
}
|
|
|
|
export function addScopeToNode(node, data, referenceNode) {
|
|
node._x_dataStack = [data, ...closestDataStack(referenceNode || node)]
|
|
|
|
return () => {
|
|
node._x_dataStack = node._x_dataStack.filter(i => i !== data)
|
|
}
|
|
}
|
|
|
|
export function hasScope(node) {
|
|
return !! node._x_dataStack
|
|
}
|
|
|
|
export function closestDataStack(node) {
|
|
if (node._x_dataStack) return node._x_dataStack
|
|
|
|
if (typeof ShadowRoot === 'function' && node instanceof ShadowRoot) {
|
|
return closestDataStack(node.host)
|
|
}
|
|
|
|
if (! node.parentNode) {
|
|
return []
|
|
}
|
|
|
|
return closestDataStack(node.parentNode)
|
|
}
|
|
|
|
export function closestDataProxy(el) {
|
|
return mergeProxies(closestDataStack(el))
|
|
}
|
|
|
|
export function mergeProxies (objects) {
|
|
return new Proxy({ objects }, mergeProxyTrap);
|
|
}
|
|
|
|
let mergeProxyTrap = {
|
|
ownKeys({ objects }) {
|
|
return Array.from(
|
|
new Set(objects.flatMap((i) => Object.keys(i)))
|
|
)
|
|
},
|
|
|
|
has({ objects }, name) {
|
|
if (name == Symbol.unscopables) return false;
|
|
|
|
return objects.some((obj) =>
|
|
Object.prototype.hasOwnProperty.call(obj, name) ||
|
|
Reflect.has(obj, name)
|
|
);
|
|
},
|
|
|
|
get({ objects }, name, thisProxy) {
|
|
if (name == "toJSON") return collapseProxies
|
|
|
|
return Reflect.get(
|
|
objects.find((obj) =>
|
|
Reflect.has(obj, name)
|
|
) || {},
|
|
name,
|
|
thisProxy
|
|
)
|
|
},
|
|
|
|
set({ objects }, name, value, thisProxy) {
|
|
const target =
|
|
objects.find((obj) =>
|
|
Object.prototype.hasOwnProperty.call(obj, name)
|
|
) || objects[objects.length - 1];
|
|
const descriptor = Object.getOwnPropertyDescriptor(target, name);
|
|
if (descriptor?.set && descriptor?.get)
|
|
return Reflect.set(target, name, value, thisProxy);
|
|
return Reflect.set(target, name, value);
|
|
},
|
|
}
|
|
|
|
function collapseProxies() {
|
|
let keys = Reflect.ownKeys(this)
|
|
|
|
return keys.reduce((acc, key) => {
|
|
acc[key] = Reflect.get(this, key)
|
|
|
|
return acc;
|
|
}, {})
|
|
}
|