11// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22// SPDX-License-Identifier: Apache-2.0
33
4+ import type { RenderOptions } from 'lit' ;
45import { GlobalStateService } from '../services/global.service.js' ;
56import type { ElementDefinition , LegacyDecoratorTarget } from '../types/index.js' ;
67import { defineElement , supportsScopedRegistry } from '../utils/dom.js' ;
78
9+ interface ScopedRegistryHost extends HTMLElement {
10+ createRenderRoot ?: ( ) => HTMLElement | DocumentFragment ;
11+ renderOptions ?: RenderOptions ;
12+ }
13+
14+ const litCreationScopeElements = new WeakSet < ElementDefinition > ( ) ;
15+
16+ /** Lit passes a legacy `deep` boolean, but scoped registries require `ImportNodeOptions`. https://html.spec.whatwg.org/multipage/custom-elements.html#scoped-custom-element-registries */
17+ function createScopedCreationScope ( ownerDocument : Document , customElementRegistry : CustomElementRegistry ) {
18+ return {
19+ importNode : ( node : Node , deep = false ) =>
20+ ownerDocument . importNode ( node , {
21+ customElementRegistry,
22+ selfOnly : ! deep
23+ } )
24+ } satisfies NonNullable < RenderOptions [ 'creationScope' ] > ;
25+ }
26+
27+ function attachLitCreationScope ( element : ElementDefinition , customElementRegistry : CustomElementRegistry ) {
28+ if ( litCreationScopeElements . has ( element ) ) return ;
29+
30+ const host = element . prototype as ScopedRegistryHost ;
31+ const createRenderRoot = host . createRenderRoot ;
32+ if ( ! createRenderRoot ) return ;
33+
34+ litCreationScopeElements . add ( element ) ;
35+ Object . defineProperty ( host , 'createRenderRoot' , {
36+ configurable : true ,
37+ value ( this : ScopedRegistryHost ) {
38+ const renderRoot = createRenderRoot . call ( this ) ;
39+ if ( renderRoot instanceof ShadowRoot ) {
40+ this . renderOptions ??= { } ;
41+ this . renderOptions . creationScope = createScopedCreationScope ( renderRoot . ownerDocument , customElementRegistry ) ;
42+ }
43+ return renderRoot ;
44+ }
45+ } ) ;
46+ }
47+
848/** decorator which registers element dependencies with the scoped custom element registry when available */
949export function scopedRegistry ( ) : ClassDecorator {
1050 return ( target : LegacyDecoratorTarget ) => {
@@ -16,6 +56,7 @@ export function scopedRegistry(): ClassDecorator {
1656 configurable : true ,
1757 value : { ...( element . shadowRootOptions ?? { mode : 'open' } ) , customElementRegistry }
1858 } ) ;
59+ attachLitCreationScope ( element , customElementRegistry ) ;
1960 }
2061 defineElement ( element , customElementRegistry ) ;
2162 } ;
0 commit comments