diff --git a/src/app.ts b/src/app.ts index 64f33f6..a0709b8 100644 --- a/src/app.ts +++ b/src/app.ts @@ -62,18 +62,34 @@ class App { }; } - private getComponentContext({ mounted, triggered }: { mounted: Hook; triggered: Hook }): Context { + private static scopeSelector(selectors: string): string { + return `${selectors}:not([data-component] ${selectors})`; + } + + private getComponentContext({ + element, + mounted, + triggered, + }: { + element: HTMLElement; + mounted: Hook; + triggered: Hook; + }): Context { return { ...this.context, onTriggered: triggered.addListener, onMounted: mounted.addListener, + scopedQuerySelector: (selectors: string) => + element.querySelector(App.scopeSelector(selectors)), + scopedQuerySelectorAll: (selectors: string) => + document.querySelectorAll(App.scopeSelector(selectors)), }; } private createComponent(element: HTMLElement, args: LoaderArguments): void { const mounted = App.createHook(); const triggered = App.createHook(); - const context = this.getComponentContext({ mounted, triggered }); + const context = this.getComponentContext({ element, mounted, triggered }); this.components.set(element, 'created'); diff --git a/src/context.ts b/src/context.ts index 505bb8f..7805b06 100644 --- a/src/context.ts +++ b/src/context.ts @@ -7,6 +7,26 @@ export type Context = { useEventHistory: EventStore['history']; onMounted: (fn: () => void) => void; onTriggered: (fn: () => void) => void; + scopedQuerySelector( + selectors: K, + ): HTMLElementTagNameMap[K] | null; + scopedQuerySelector( + selectors: K, + ): SVGElementTagNameMap[K] | null; + scopedQuerySelector( + selectors: K, + ): MathMLElementTagNameMap[K] | null; + scopedQuerySelector(selectors: string): E | null; + scopedQuerySelectorAll( + selectors: K, + ): NodeListOf; + scopedQuerySelectorAll( + selectors: K, + ): NodeListOf; + scopedQuerySelectorAll( + selectors: K, + ): NodeListOf; + scopedQuerySelectorAll(selectors: string): NodeListOf; }; export type AppContext = Pick;