UNPKG

@github/catalyst

Version:

Helpers for creating HTML Elements as Controllers

93 lines 3.29 kB
import { registerTag, observeElementForTags } from './tag-observer.js'; import { createMark } from './mark.js'; import { attach } from './controllable.js'; import { dasherize } from './dasherize.js'; const targetChangedCallback = Symbol(); const targetsChangedCallback = Symbol(); const [target, getTarget, initializeTarget] = createMark(({ name, kind }) => { if (kind === 'getter') throw new Error(`@target cannot decorate get ${String(name)}`); }, (instance, { name, access }) => { const selector = [ `[data-target~="${instance.tagName.toLowerCase()}.${dasherize(name)}"]`, `[data-target~="${instance.tagName.toLowerCase()}.${String(name)}"]` ]; const find = findTarget(instance, selector.join(', '), false); return { get: find, set: () => { if (access?.set) access.set.call(instance, find()); } }; }); const [targets, getTargets, initializeTargets] = createMark(({ name, kind }) => { if (kind === 'getter') throw new Error(`@target cannot decorate get ${String(name)}`); }, (instance, { name, access }) => { const selector = [ `[data-targets~="${instance.tagName.toLowerCase()}.${dasherize(name)}"]`, `[data-targets~="${instance.tagName.toLowerCase()}.${String(name)}"]` ]; const find = findTarget(instance, selector.join(', '), true); return { get: find, set: () => { if (access?.set) access.set.call(instance, find()); } }; }); function setTarget(el, controller, tag, key) { const get = tag === 'data-targets' ? getTargets : getTarget; if (controller instanceof ShadowRoot) { controller = controllers.get(controller); } if (controller && get(controller)?.has(key)) { ; controller.requestUpdate(key); } } registerTag('data-target', (str) => str.split('.'), setTarget); registerTag('data-targets', (str) => str.split('.'), setTarget); const shadows = new WeakMap(); const controllers = new WeakMap(); const findTarget = (controller, selector, many) => () => { const nodes = []; const shadow = shadows.get(controller); if (shadow) { for (const el of shadow.querySelectorAll(selector)) { if (!el.closest(controller.tagName)) { nodes.push(el); if (!many) break; } } } if (many || !nodes.length) { for (const el of controller.querySelectorAll(selector)) { if (el.closest(controller.tagName) === controller) { nodes.push(el); if (!many) break; } } } return many ? nodes : nodes[0]; }; export { target, getTarget, targets, getTargets, targetChangedCallback, targetsChangedCallback }; export class TargetableController { constructor(host) { this.host = host; observeElementForTags(this.host); initializeTarget(this.host); initializeTargets(this.host); } hostShadowCreated(root) { shadows.set(this.host, root); controllers.set(root, this.host); observeElementForTags(root); } } export const targetable = attach(TargetableController); //# sourceMappingURL=targetable.js.map