mount-observer 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ElementMountExtension.js +5 -1
- package/ElementMountExtension.ts +5 -1
- package/getRootRegistryContainer.js +39 -17
- package/getRootRegistryContainer.ts +46 -22
- package/index.js +2 -1
- package/package.json +2 -2
package/ElementMountExtension.js
CHANGED
|
@@ -16,7 +16,11 @@ Object.defineProperty(Element.prototype, 'mount', {
|
|
|
16
16
|
const scope = options.scope ?? 'registry';
|
|
17
17
|
let thingToObserve;
|
|
18
18
|
if (scope === 'registry') {
|
|
19
|
-
|
|
19
|
+
const registryContainer = getRootRegistryContainer(this);
|
|
20
|
+
if (!registryContainer) {
|
|
21
|
+
throw new Error('Could not find root registry container');
|
|
22
|
+
}
|
|
23
|
+
thingToObserve = registryContainer;
|
|
20
24
|
}
|
|
21
25
|
else if (scope === 'self') {
|
|
22
26
|
thingToObserve = this;
|
package/ElementMountExtension.ts
CHANGED
|
@@ -35,7 +35,11 @@ Object.defineProperty(Element.prototype, 'mount', {
|
|
|
35
35
|
let thingToObserve: Node;
|
|
36
36
|
|
|
37
37
|
if (scope === 'registry') {
|
|
38
|
-
|
|
38
|
+
const registryContainer = getRootRegistryContainer(this);
|
|
39
|
+
if (!registryContainer) {
|
|
40
|
+
throw new Error('Could not find root registry container');
|
|
41
|
+
}
|
|
42
|
+
thingToObserve = registryContainer;
|
|
39
43
|
} else if (scope === 'self') {
|
|
40
44
|
thingToObserve = this;
|
|
41
45
|
} else if (scope === 'root') {
|
|
@@ -1,27 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Recursively traverses up the DOM tree to find the highest node
|
|
3
|
+
* that shares the same customElementRegistry as the passed in node.
|
|
3
4
|
* This is useful for scoped custom element registries where we want to observe within the correct scope.
|
|
4
5
|
*
|
|
5
|
-
* @param
|
|
6
|
-
* @returns The
|
|
6
|
+
* @param node - The starting node to check
|
|
7
|
+
* @returns The highest node with matching customElementRegistry, or null if node is invalid
|
|
7
8
|
*/
|
|
8
|
-
export function getRootRegistryContainer(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export function getRootRegistryContainer(node) {
|
|
10
|
+
if (!node) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
// Quick check: if root node has the same registry, return it immediately
|
|
14
|
+
const rn = node.getRootNode();
|
|
15
|
+
const { customElementRegistry } = node;
|
|
12
16
|
if (rn.customElementRegistry === customElementRegistry) {
|
|
13
17
|
return rn;
|
|
14
18
|
}
|
|
15
|
-
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const startRegistry = node.customElementRegistry;
|
|
20
|
+
let currentNode = node;
|
|
21
|
+
let highestMatch = node;
|
|
22
|
+
while (currentNode) {
|
|
23
|
+
// Check if current node has matching customElementRegistry
|
|
24
|
+
if (currentNode.customElementRegistry === startRegistry) {
|
|
25
|
+
highestMatch = currentNode;
|
|
26
|
+
}
|
|
27
|
+
// Try to get parent element first
|
|
28
|
+
const parent = currentNode.parentElement;
|
|
29
|
+
if (parent) {
|
|
30
|
+
currentNode = parent;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
// If no parent element, check for rootNode (shadow root case)
|
|
34
|
+
const root = currentNode.getRootNode();
|
|
35
|
+
if (root && root !== currentNode) {
|
|
36
|
+
// If it's a shadow root (not document), return it
|
|
37
|
+
if (root !== document) {
|
|
38
|
+
return root;
|
|
39
|
+
}
|
|
40
|
+
// If it's the document, check if it has the same registry
|
|
41
|
+
if (root.customElementRegistry === startRegistry) {
|
|
42
|
+
return root;
|
|
43
|
+
}
|
|
23
44
|
}
|
|
45
|
+
// Reached the top
|
|
46
|
+
break;
|
|
24
47
|
}
|
|
25
|
-
|
|
26
|
-
return element;
|
|
48
|
+
return highestMatch;
|
|
27
49
|
}
|
|
@@ -1,32 +1,56 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Recursively traverses up the DOM tree to find the highest node
|
|
3
|
+
* that shares the same customElementRegistry as the passed in node.
|
|
3
4
|
* This is useful for scoped custom element registries where we want to observe within the correct scope.
|
|
4
5
|
*
|
|
5
|
-
* @param
|
|
6
|
-
* @returns The
|
|
6
|
+
* @param node - The starting node to check
|
|
7
|
+
* @returns The highest node with matching customElementRegistry, or null if node is invalid
|
|
7
8
|
*/
|
|
8
|
-
export function getRootRegistryContainer(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
export function getRootRegistryContainer(node: Node): Node | null {
|
|
10
|
+
if (!node) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Quick check: if root node has the same registry, return it immediately
|
|
15
|
+
const rn = node.getRootNode();
|
|
16
|
+
const { customElementRegistry } = node as any;
|
|
13
17
|
if ((rn as any).customElementRegistry === customElementRegistry) {
|
|
14
18
|
return rn;
|
|
15
19
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
let
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
|
|
21
|
+
const startRegistry = (node as any).customElementRegistry;
|
|
22
|
+
let currentNode: Node | null = node;
|
|
23
|
+
let highestMatch: Node = node;
|
|
24
|
+
|
|
25
|
+
while (currentNode) {
|
|
26
|
+
// Check if current node has matching customElementRegistry
|
|
27
|
+
if ((currentNode as any).customElementRegistry === startRegistry) {
|
|
28
|
+
highestMatch = currentNode;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Try to get parent element first
|
|
32
|
+
const parent = (currentNode as any).parentElement as Element | null;
|
|
33
|
+
if (parent) {
|
|
34
|
+
currentNode = parent;
|
|
35
|
+
continue;
|
|
27
36
|
}
|
|
37
|
+
|
|
38
|
+
// If no parent element, check for rootNode (shadow root case)
|
|
39
|
+
const root = currentNode.getRootNode();
|
|
40
|
+
if (root && root !== currentNode) {
|
|
41
|
+
// If it's a shadow root (not document), return it
|
|
42
|
+
if (root !== document) {
|
|
43
|
+
return root;
|
|
44
|
+
}
|
|
45
|
+
// If it's the document, check if it has the same registry
|
|
46
|
+
if ((root as any).customElementRegistry === startRegistry) {
|
|
47
|
+
return root;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Reached the top
|
|
52
|
+
break;
|
|
28
53
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return element;
|
|
54
|
+
|
|
55
|
+
return highestMatch;
|
|
32
56
|
}
|
package/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export { mountEventName, dismountEventName, disconnectEventName, loadEventName,
|
|
|
9
9
|
// Register built-in handlers
|
|
10
10
|
import { MountObserver } from './MountObserver.js';
|
|
11
11
|
import { EvtRt } from './EvtRt.js';
|
|
12
|
-
import { DefineCustomElementHandler } from './DefineCustomElementHandler.js';
|
|
12
|
+
import { DefineCustomElementHandler, DefineScopedCustomElementHandler } from './DefineCustomElementHandler.js';
|
|
13
13
|
MountObserver.define('builtIns.logToConsole', EvtRt);
|
|
14
14
|
MountObserver.define('builtIns.defineCustomElement', DefineCustomElementHandler);
|
|
15
|
+
MountObserver.define('buildIns.defineScopedCustomElement', DefineScopedCustomElementHandler);
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mount-observer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Observe and act on css matches.",
|
|
5
5
|
"main": "MountObserver.js",
|
|
6
6
|
"module": "MountObserver.js",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"assign-gingerly": "0.0.
|
|
8
|
+
"assign-gingerly": "0.0.13"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@playwright/test": "1.58.2",
|