mount-observer 0.1.4 → 0.1.5
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/DefineCustomElementHandler.js +37 -3
- package/DefineCustomElementHandler.ts +43 -4
- package/ElementMountExtension.js +45 -0
- package/ElementMountExtension.ts +61 -0
- package/Events.js +18 -29
- package/Events.ts +7 -16
- package/EvtRt.js +14 -14
- package/EvtRt.ts +15 -15
- package/MountObserver.js +240 -111
- package/MountObserver.ts +283 -131
- package/README.md +667 -447
- package/emitEvents.js +13 -13
- package/emitEvents.ts +14 -14
- package/getRootRegistryContainer.js +27 -0
- package/getRootRegistryContainer.ts +32 -0
- package/index.js +2 -3
- package/index.ts +4 -5
- package/loadImports.js +1 -1
- package/loadImports.ts +1 -1
- package/mediaQuery.js +5 -5
- package/mediaQuery.ts +7 -7
- package/package.json +5 -9
- package/playwright.config.ts +8 -8
- package/types.d.ts +22 -46
- package/{whereOutside.js → withScopePerimeter.js} +1 -1
- package/{whereOutside.ts → withScopePerimeter.ts} +1 -1
- package/attrChanges.js +0 -70
- package/attrChanges.ts +0 -90
- package/attrCoordinates.js +0 -93
- package/attrCoordinates.ts +0 -122
- package/whereAttr.js +0 -174
- package/whereAttr.ts +0 -221
package/emitEvents.js
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
* Emits events from a mounted element based on the mountedElemEmits configuration.
|
|
3
3
|
* This module is dynamically loaded only when mountedElemEmits is configured.
|
|
4
4
|
*/
|
|
5
|
-
export async function emitMountedElementEvents(element,
|
|
6
|
-
const configs = Array.isArray(
|
|
7
|
-
?
|
|
8
|
-
: [
|
|
5
|
+
export async function emitMountedElementEvents(element, MountConfig, processedEventsForElement) {
|
|
6
|
+
const configs = Array.isArray(MountConfig.mountedElemEmits)
|
|
7
|
+
? MountConfig.mountedElemEmits
|
|
8
|
+
: [MountConfig.mountedElemEmits];
|
|
9
9
|
for (const config of configs) {
|
|
10
|
-
await emitSingleEvent(element,
|
|
10
|
+
await emitSingleEvent(element, MountConfig, config, processedEventsForElement);
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
async function emitSingleEvent(element,
|
|
13
|
+
async function emitSingleEvent(element, MountConfig, config, processedEventsForElement) {
|
|
14
14
|
// Check if this event should only fire once per element
|
|
15
15
|
if (config.oncePerMountedElement) {
|
|
16
16
|
const eventId = getEventId(config);
|
|
@@ -28,7 +28,7 @@ async function emitSingleEvent(element, mountInit, config, processedEventsForEle
|
|
|
28
28
|
const EventCtor = resolveEventConstructor(config.event);
|
|
29
29
|
// Process args with magic string substitution
|
|
30
30
|
const processedArgs = config.args !== undefined
|
|
31
|
-
? processMagicStrings(config.args, element,
|
|
31
|
+
? processMagicStrings(config.args, element, MountConfig)
|
|
32
32
|
: undefined;
|
|
33
33
|
// Construct the event
|
|
34
34
|
let event;
|
|
@@ -58,7 +58,7 @@ async function emitSingleEvent(element, mountInit, config, processedEventsForEle
|
|
|
58
58
|
// Apply eventProps if specified
|
|
59
59
|
if (config.eventProps) {
|
|
60
60
|
const { assignGingerly } = await import('assign-gingerly/assignGingerly.js');
|
|
61
|
-
const processedProps = processMagicStrings(config.eventProps, element,
|
|
61
|
+
const processedProps = processMagicStrings(config.eventProps, element, MountConfig);
|
|
62
62
|
assignGingerly(event, processedProps);
|
|
63
63
|
}
|
|
64
64
|
// Dispatch the event from the mounted element
|
|
@@ -79,23 +79,23 @@ function getEventId(config) {
|
|
|
79
79
|
const argsStr = JSON.stringify(config.args || '');
|
|
80
80
|
return `${eventName}:${argsStr}`;
|
|
81
81
|
}
|
|
82
|
-
function processMagicStrings(value, element,
|
|
82
|
+
function processMagicStrings(value, element, MountConfig) {
|
|
83
83
|
if (typeof value === 'string') {
|
|
84
84
|
if (value === '{{mountedElement}}') {
|
|
85
85
|
return element;
|
|
86
86
|
}
|
|
87
|
-
if (value === '{{
|
|
88
|
-
return
|
|
87
|
+
if (value === '{{MountConfig}}') {
|
|
88
|
+
return MountConfig;
|
|
89
89
|
}
|
|
90
90
|
return value;
|
|
91
91
|
}
|
|
92
92
|
if (Array.isArray(value)) {
|
|
93
|
-
return value.map(item => processMagicStrings(item, element,
|
|
93
|
+
return value.map(item => processMagicStrings(item, element, MountConfig));
|
|
94
94
|
}
|
|
95
95
|
if (value && typeof value === 'object') {
|
|
96
96
|
const processed = {};
|
|
97
97
|
for (const [key, val] of Object.entries(value)) {
|
|
98
|
-
processed[key] = processMagicStrings(val, element,
|
|
98
|
+
processed[key] = processMagicStrings(val, element, MountConfig);
|
|
99
99
|
}
|
|
100
100
|
return processed;
|
|
101
101
|
}
|
package/emitEvents.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EventConfig, EventConstructor,
|
|
1
|
+
import type { EventConfig, EventConstructor, MountConfig } from './types.d.ts';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Emits events from a mounted element based on the mountedElemEmits configuration.
|
|
@@ -6,21 +6,21 @@ import type { EventConfig, EventConstructor, MountInit } from './types.d.ts';
|
|
|
6
6
|
*/
|
|
7
7
|
export async function emitMountedElementEvents(
|
|
8
8
|
element: Element,
|
|
9
|
-
|
|
9
|
+
MountConfig: MountConfig,
|
|
10
10
|
processedEventsForElement: WeakMap<Element, Set<string>>
|
|
11
11
|
): Promise<void> {
|
|
12
|
-
const configs = Array.isArray(
|
|
13
|
-
?
|
|
14
|
-
: [
|
|
12
|
+
const configs = Array.isArray(MountConfig.mountedElemEmits)
|
|
13
|
+
? MountConfig.mountedElemEmits
|
|
14
|
+
: [MountConfig.mountedElemEmits!];
|
|
15
15
|
|
|
16
16
|
for (const config of configs) {
|
|
17
|
-
await emitSingleEvent(element,
|
|
17
|
+
await emitSingleEvent(element, MountConfig, config, processedEventsForElement);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
async function emitSingleEvent(
|
|
22
22
|
element: Element,
|
|
23
|
-
|
|
23
|
+
MountConfig: MountConfig,
|
|
24
24
|
config: EventConfig,
|
|
25
25
|
processedEventsForElement: WeakMap<Element, Set<string>>
|
|
26
26
|
): Promise<void> {
|
|
@@ -46,7 +46,7 @@ async function emitSingleEvent(
|
|
|
46
46
|
|
|
47
47
|
// Process args with magic string substitution
|
|
48
48
|
const processedArgs = config.args !== undefined
|
|
49
|
-
? processMagicStrings(config.args, element,
|
|
49
|
+
? processMagicStrings(config.args, element, MountConfig)
|
|
50
50
|
: undefined;
|
|
51
51
|
|
|
52
52
|
// Construct the event
|
|
@@ -74,7 +74,7 @@ async function emitSingleEvent(
|
|
|
74
74
|
// Apply eventProps if specified
|
|
75
75
|
if (config.eventProps) {
|
|
76
76
|
const { assignGingerly } = await import('assign-gingerly/assignGingerly.js');
|
|
77
|
-
const processedProps = processMagicStrings(config.eventProps, element,
|
|
77
|
+
const processedProps = processMagicStrings(config.eventProps, element, MountConfig);
|
|
78
78
|
assignGingerly(event, processedProps);
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -99,25 +99,25 @@ function getEventId(config: EventConfig): string {
|
|
|
99
99
|
return `${eventName}:${argsStr}`;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
function processMagicStrings(value: any, element: Element,
|
|
102
|
+
function processMagicStrings(value: any, element: Element, MountConfig: MountConfig): any {
|
|
103
103
|
if (typeof value === 'string') {
|
|
104
104
|
if (value === '{{mountedElement}}') {
|
|
105
105
|
return element;
|
|
106
106
|
}
|
|
107
|
-
if (value === '{{
|
|
108
|
-
return
|
|
107
|
+
if (value === '{{MountConfig}}') {
|
|
108
|
+
return MountConfig;
|
|
109
109
|
}
|
|
110
110
|
return value;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
if (Array.isArray(value)) {
|
|
114
|
-
return value.map(item => processMagicStrings(item, element,
|
|
114
|
+
return value.map(item => processMagicStrings(item, element, MountConfig));
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
if (value && typeof value === 'object') {
|
|
118
118
|
const processed: any = {};
|
|
119
119
|
for (const [key, val] of Object.entries(value)) {
|
|
120
|
-
processed[key] = processMagicStrings(val, element,
|
|
120
|
+
processed[key] = processMagicStrings(val, element, MountConfig);
|
|
121
121
|
}
|
|
122
122
|
return processed;
|
|
123
123
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds the highest scoped container that has the same customElementRegistry as the given element.
|
|
3
|
+
* This is useful for scoped custom element registries where we want to observe within the correct scope.
|
|
4
|
+
*
|
|
5
|
+
* @param element - The element to find the root registry container for
|
|
6
|
+
* @returns The root node or highest parent element with the same customElementRegistry
|
|
7
|
+
*/
|
|
8
|
+
export function getRootRegistryContainer(element) {
|
|
9
|
+
const rn = element.getRootNode();
|
|
10
|
+
const { customElementRegistry } = element;
|
|
11
|
+
// If root node has the same registry, return it
|
|
12
|
+
if (rn.customElementRegistry === customElementRegistry) {
|
|
13
|
+
return rn;
|
|
14
|
+
}
|
|
15
|
+
// Walk up the parent chain to find the highest element with the same registry
|
|
16
|
+
let parent = element.parentElement;
|
|
17
|
+
while (parent) {
|
|
18
|
+
const prevParent = parent;
|
|
19
|
+
parent = parent.parentElement;
|
|
20
|
+
// If parent has a different registry, return the previous parent
|
|
21
|
+
if (parent && parent.customElementRegistry !== customElementRegistry) {
|
|
22
|
+
return prevParent;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// If we reached the top without finding a different registry, return the element itself
|
|
26
|
+
return element;
|
|
27
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds the highest scoped container that has the same customElementRegistry as the given element.
|
|
3
|
+
* This is useful for scoped custom element registries where we want to observe within the correct scope.
|
|
4
|
+
*
|
|
5
|
+
* @param element - The element to find the root registry container for
|
|
6
|
+
* @returns The root node or highest parent element with the same customElementRegistry
|
|
7
|
+
*/
|
|
8
|
+
export function getRootRegistryContainer(element: Element): Node {
|
|
9
|
+
const rn = element.getRootNode();
|
|
10
|
+
const { customElementRegistry } = element as any;
|
|
11
|
+
|
|
12
|
+
// If root node has the same registry, return it
|
|
13
|
+
if ((rn as any).customElementRegistry === customElementRegistry) {
|
|
14
|
+
return rn;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Walk up the parent chain to find the highest element with the same registry
|
|
18
|
+
let parent = element.parentElement;
|
|
19
|
+
|
|
20
|
+
while (parent) {
|
|
21
|
+
const prevParent = parent;
|
|
22
|
+
parent = parent.parentElement;
|
|
23
|
+
|
|
24
|
+
// If parent has a different registry, return the previous parent
|
|
25
|
+
if (parent && (parent as any).customElementRegistry !== customElementRegistry) {
|
|
26
|
+
return prevParent;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// If we reached the top without finding a different registry, return the element itself
|
|
31
|
+
return element;
|
|
32
|
+
}
|
package/index.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
// Main entry point for MountObserver v2
|
|
2
2
|
export { MountObserver } from './MountObserver.js';
|
|
3
|
-
export {
|
|
3
|
+
export { withScopePerimeter } from './withScopePerimeter.js';
|
|
4
4
|
export { emitMountedElementEvents } from './emitEvents.js';
|
|
5
|
-
export { checkAttrChanges } from './attrChanges.js';
|
|
6
5
|
export { arr } from './arr.js';
|
|
7
6
|
export { EvtRt } from './EvtRt.js';
|
|
8
7
|
export { DefineCustomElementHandler } from './DefineCustomElementHandler.js';
|
|
9
|
-
export { mountEventName, dismountEventName, disconnectEventName, loadEventName,
|
|
8
|
+
export { mountEventName, dismountEventName, disconnectEventName, loadEventName, mediamatchEventName, mediaunmatchEventName } from './Events.js';
|
|
10
9
|
// Register built-in handlers
|
|
11
10
|
import { MountObserver } from './MountObserver.js';
|
|
12
11
|
import { EvtRt } from './EvtRt.js';
|
package/index.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
// Main entry point for MountObserver v2
|
|
2
2
|
export { MountObserver } from './MountObserver.js';
|
|
3
|
-
export {
|
|
3
|
+
export { withScopePerimeter } from './withScopePerimeter.js';
|
|
4
4
|
export { emitMountedElementEvents } from './emitEvents.js';
|
|
5
|
-
export { checkAttrChanges } from './attrChanges.js';
|
|
6
5
|
export { arr } from './arr.js';
|
|
7
6
|
export { EvtRt } from './EvtRt.js';
|
|
8
7
|
export { DefineCustomElementHandler } from './DefineCustomElementHandler.js';
|
|
9
8
|
export type {
|
|
10
|
-
|
|
9
|
+
MountConfig,
|
|
11
10
|
MountObserverOptions,
|
|
12
11
|
IMountObserver,
|
|
13
12
|
MountContext,
|
|
@@ -21,7 +20,6 @@ export {
|
|
|
21
20
|
dismountEventName,
|
|
22
21
|
disconnectEventName,
|
|
23
22
|
loadEventName,
|
|
24
|
-
attrchangeEventName,
|
|
25
23
|
mediamatchEventName,
|
|
26
24
|
mediaunmatchEventName
|
|
27
25
|
} from './Events.js';
|
|
@@ -29,7 +27,8 @@ export {
|
|
|
29
27
|
// Register built-in handlers
|
|
30
28
|
import { MountObserver } from './MountObserver.js';
|
|
31
29
|
import { EvtRt } from './EvtRt.js';
|
|
32
|
-
import { DefineCustomElementHandler } from './DefineCustomElementHandler.js';
|
|
30
|
+
import { DefineCustomElementHandler, DefineScopedCustomElementHandler } from './DefineCustomElementHandler.js';
|
|
33
31
|
|
|
34
32
|
MountObserver.define('builtIns.logToConsole', EvtRt);
|
|
35
33
|
MountObserver.define('builtIns.defineCustomElement', DefineCustomElementHandler);
|
|
34
|
+
MountObserver.define('buildIns.defineScopedCustomElement', DefineScopedCustomElementHandler);
|
package/loadImports.js
CHANGED
package/loadImports.ts
CHANGED
package/mediaQuery.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { MediaMatchEvent, MediaUnmatchEvent, DismountEvent } from './Events.js';
|
|
2
2
|
export function setupMediaQuery(init, rootNodeRef, mountedElements, modules, observer, processNode) {
|
|
3
|
-
const {
|
|
3
|
+
const { withMediaMatching } = init;
|
|
4
4
|
// Create or use MediaQueryList
|
|
5
5
|
let mediaQueryList;
|
|
6
|
-
if (typeof
|
|
7
|
-
mediaQueryList = window.matchMedia(
|
|
6
|
+
if (typeof withMediaMatching === 'string') {
|
|
7
|
+
mediaQueryList = window.matchMedia(withMediaMatching);
|
|
8
8
|
}
|
|
9
9
|
else {
|
|
10
|
-
mediaQueryList =
|
|
10
|
+
mediaQueryList = withMediaMatching;
|
|
11
11
|
}
|
|
12
12
|
// Track current state
|
|
13
13
|
let mediaMatches = mediaQueryList.matches;
|
|
@@ -49,7 +49,7 @@ export function setupMediaQuery(init, rootNodeRef, mountedElements, modules, obs
|
|
|
49
49
|
modules,
|
|
50
50
|
observer: observer,
|
|
51
51
|
rootNode,
|
|
52
|
-
|
|
52
|
+
MountConfig: init
|
|
53
53
|
};
|
|
54
54
|
// Get all mounted elements from the WeakDual setWeak
|
|
55
55
|
const mountedElementsList = [];
|
package/mediaQuery.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Media query handling for MountObserver
|
|
2
|
-
import type {
|
|
2
|
+
import type { MountConfig, MountContext, WeakDual } from './types.js';
|
|
3
3
|
import { MediaMatchEvent, MediaUnmatchEvent, DismountEvent } from './Events.js';
|
|
4
4
|
|
|
5
5
|
export function setupMediaQuery(
|
|
6
|
-
init:
|
|
6
|
+
init: MountConfig,
|
|
7
7
|
rootNodeRef: WeakRef<Node>,
|
|
8
8
|
mountedElements: WeakDual<Element>,
|
|
9
9
|
modules: any[],
|
|
@@ -14,14 +14,14 @@ export function setupMediaQuery(
|
|
|
14
14
|
mediaMatches: boolean;
|
|
15
15
|
cleanup: () => void;
|
|
16
16
|
} {
|
|
17
|
-
const {
|
|
17
|
+
const { withMediaMatching } = init;
|
|
18
18
|
|
|
19
19
|
// Create or use MediaQueryList
|
|
20
20
|
let mediaQueryList: MediaQueryList;
|
|
21
|
-
if (typeof
|
|
22
|
-
mediaQueryList = window.matchMedia(
|
|
21
|
+
if (typeof withMediaMatching === 'string') {
|
|
22
|
+
mediaQueryList = window.matchMedia(withMediaMatching);
|
|
23
23
|
} else {
|
|
24
|
-
mediaQueryList =
|
|
24
|
+
mediaQueryList = withMediaMatching!;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// Track current state
|
|
@@ -70,7 +70,7 @@ export function setupMediaQuery(
|
|
|
70
70
|
modules,
|
|
71
71
|
observer: observer as any,
|
|
72
72
|
rootNode,
|
|
73
|
-
|
|
73
|
+
MountConfig: init
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
// Get all mounted elements from the WeakDual setWeak
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mount-observer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
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.12"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"@playwright/test": "1.58.2",
|
|
@@ -20,18 +20,14 @@
|
|
|
20
20
|
"default": "./MountObserver.js",
|
|
21
21
|
"types": "./MountObserver.ts"
|
|
22
22
|
},
|
|
23
|
-
"./
|
|
24
|
-
"default": "./
|
|
25
|
-
"types": "./
|
|
23
|
+
"./withScopePerimeter.js": {
|
|
24
|
+
"default": "./withScopePerimeter.js",
|
|
25
|
+
"types": "./withScopePerimeter.ts"
|
|
26
26
|
},
|
|
27
27
|
"./emitEvents.js": {
|
|
28
28
|
"default": "./emitEvents.js",
|
|
29
29
|
"types": "./emitEvents.ts"
|
|
30
30
|
},
|
|
31
|
-
"./attrChanges.js": {
|
|
32
|
-
"default": "./attrChanges.js",
|
|
33
|
-
"types": "./attrChanges.ts"
|
|
34
|
-
},
|
|
35
31
|
"./arr.js": {
|
|
36
32
|
"default": "./arr.js",
|
|
37
33
|
"types": "./arr.ts"
|
package/playwright.config.ts
CHANGED
|
@@ -15,14 +15,14 @@ const config: PlaywrightTestConfig = {
|
|
|
15
15
|
name: 'chromium',
|
|
16
16
|
use: { ...devices['Desktop Chrome'] },
|
|
17
17
|
},
|
|
18
|
-
{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
18
|
+
// {
|
|
19
|
+
// name: 'firefox',
|
|
20
|
+
// use: { ...devices['Desktop Firefox'] },
|
|
21
|
+
// },
|
|
22
|
+
// {
|
|
23
|
+
// name: 'webkit',
|
|
24
|
+
// use: { ...devices['Desktop Safari'] },
|
|
25
|
+
// },
|
|
26
26
|
],
|
|
27
27
|
};
|
|
28
28
|
export default config;
|
package/types.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// Core types for MountObserver v2 - Polyfill Supported Scenario I
|
|
2
2
|
|
|
3
|
+
import {EnhancementConfig} from 'assign-gingerly/types.d.ts';
|
|
4
|
+
|
|
3
5
|
export type Constructor = new (...args: any[]) => any;
|
|
4
6
|
|
|
5
7
|
export type EventConstructor = {new(...args: any[]): Event};
|
|
@@ -13,51 +15,29 @@ export interface EventConfig {
|
|
|
13
15
|
|
|
14
16
|
export type DismountReason =
|
|
15
17
|
| 'media-query-failed'
|
|
16
|
-
| '
|
|
17
|
-
|
|
18
|
-
export interface
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
whereOutside?: string;
|
|
18
|
+
| 'with-matching-failed';
|
|
19
|
+
|
|
20
|
+
export interface MountConfig {
|
|
21
|
+
matching?: string;
|
|
22
|
+
withInstance?: Constructor | Constructor[];
|
|
23
|
+
withMediaMatching?: string | MediaQueryList;
|
|
24
|
+
withScopePerimeter?: string;
|
|
24
25
|
import?: string | ImportSpec | Array<string | ImportSpec>;
|
|
25
26
|
do?: string | DoCallback | (string | DoCallback)[];
|
|
26
27
|
loadingEagerness?: 'eager' | 'lazy';
|
|
27
28
|
assignOnMount?: Record<string, any>;
|
|
28
29
|
assignOnDismount?: Record<string, any>;
|
|
29
|
-
|
|
30
|
+
stageOnMount?: Record<string, any>;
|
|
30
31
|
getPlayByPlay?: boolean;
|
|
31
32
|
mountedElemEmits?: EventConfig | EventConfig[];
|
|
32
33
|
reference?: number | number[];
|
|
33
34
|
//allow handler classes or functions
|
|
34
35
|
//to be passed some custom information
|
|
35
36
|
customData?: unknown;
|
|
37
|
+
enhancementConfig?: EnhancementConfig | EnhancementConfig[];
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
export interface MapConfig {
|
|
39
|
-
[coordinate: string]: MapEntry;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface MapEntry {
|
|
43
|
-
instanceOf?: string;
|
|
44
|
-
mapsTo?: string;
|
|
45
|
-
/**
|
|
46
|
-
* Only notify the presence of this attribute
|
|
47
|
-
* the first time it is seen
|
|
48
|
-
*/
|
|
49
|
-
once?: boolean;
|
|
50
|
-
[key: string]: any;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export type BranchValue = string | { [key: string]: BranchValue[] };
|
|
54
40
|
|
|
55
|
-
export interface WhereAttr {
|
|
56
|
-
hasBuiltInRootIn?: string[];
|
|
57
|
-
hasCERootIn?: string[];
|
|
58
|
-
hasBase: string;
|
|
59
|
-
hasBranchIn?: BranchValue[];
|
|
60
|
-
}
|
|
61
41
|
|
|
62
42
|
export interface ImportSpec {
|
|
63
43
|
url: string;
|
|
@@ -68,7 +48,7 @@ export interface MountContext {
|
|
|
68
48
|
modules: any[];
|
|
69
49
|
observer: IMountObserver;
|
|
70
50
|
rootNode: Node;
|
|
71
|
-
|
|
51
|
+
MountConfig: MountConfig
|
|
72
52
|
}
|
|
73
53
|
|
|
74
54
|
|
|
@@ -82,8 +62,16 @@ export type DoCallback = (mountedElement: Element, context: MountContext) => voi
|
|
|
82
62
|
// reconnect?: (mountedElement: Element, context: MountContext) => void;
|
|
83
63
|
// }
|
|
84
64
|
|
|
65
|
+
export type MountScope =
|
|
66
|
+
| 'registry' // getRootRegistryContainer (default)
|
|
67
|
+
| 'self' // this element
|
|
68
|
+
| 'root' // getRootNode()
|
|
69
|
+
| 'shadow' // shadowRoot (throws if none)
|
|
70
|
+
| Element; // custom element to observe
|
|
71
|
+
|
|
85
72
|
export interface MountObserverOptions {
|
|
86
73
|
disconnectedSignal?: AbortSignal;
|
|
74
|
+
scope?: MountScope;
|
|
87
75
|
}
|
|
88
76
|
|
|
89
77
|
export interface WeakDual<T extends Object>{
|
|
@@ -102,26 +90,14 @@ export interface IMountObserver extends EventTarget {
|
|
|
102
90
|
export interface IMountEvent extends Event {
|
|
103
91
|
mountedElement: Element;
|
|
104
92
|
modules: any[];
|
|
105
|
-
|
|
93
|
+
MountConfig: MountConfig;
|
|
106
94
|
mountContext: MountContext;
|
|
107
95
|
}
|
|
108
96
|
|
|
109
97
|
export interface IDismountEvent extends Event {
|
|
110
98
|
mountedElement: Element;
|
|
111
99
|
reason: DismountReason;
|
|
112
|
-
|
|
100
|
+
MountConfig: MountConfig;
|
|
113
101
|
}
|
|
114
102
|
|
|
115
|
-
export interface IAttrChangeEvent extends Event {
|
|
116
|
-
changes: AttrChange[];
|
|
117
|
-
mountInit: MountInit;
|
|
118
|
-
}
|
|
119
103
|
|
|
120
|
-
export interface AttrChange {
|
|
121
|
-
value: string | null;
|
|
122
|
-
attrNode: Attr | null;
|
|
123
|
-
mapEntry: MapEntry | null;
|
|
124
|
-
attrName: string;
|
|
125
|
-
coordinate: string;
|
|
126
|
-
element: Element;
|
|
127
|
-
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @param outside - CSS selector for excluding ancestors
|
|
8
8
|
* @returns true if element is outside all matching ancestors, false otherwise
|
|
9
9
|
*/
|
|
10
|
-
export function
|
|
10
|
+
export function withScopePerimeter(rootNode, matchCandidate, outside) {
|
|
11
11
|
let current = matchCandidate.parentElement;
|
|
12
12
|
while (current && current !== rootNode) {
|
|
13
13
|
if (current.matches(outside)) {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @param outside - CSS selector for excluding ancestors
|
|
8
8
|
* @returns true if element is outside all matching ancestors, false otherwise
|
|
9
9
|
*/
|
|
10
|
-
export function
|
|
10
|
+
export function withScopePerimeter(
|
|
11
11
|
rootNode: Node,
|
|
12
12
|
matchCandidate: Element,
|
|
13
13
|
outside: string
|
package/attrChanges.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checks for attribute changes on a mounted element.
|
|
3
|
-
* This module is dynamically loaded only when whereAttr is configured.
|
|
4
|
-
*/
|
|
5
|
-
export function checkAttrChanges(element, mountInit, buildAttrCoordinateMapFn, elementAttrStates, elementOnceAttrs) {
|
|
6
|
-
if (!mountInit.whereAttr || !buildAttrCoordinateMapFn) {
|
|
7
|
-
return [];
|
|
8
|
-
}
|
|
9
|
-
const isCustomElement = element.tagName.toLowerCase().includes('-');
|
|
10
|
-
const attrCoordMap = buildAttrCoordinateMapFn(mountInit.whereAttr, isCustomElement);
|
|
11
|
-
// Get or create the attribute state for this element
|
|
12
|
-
let attrState = elementAttrStates.get(element);
|
|
13
|
-
if (!attrState) {
|
|
14
|
-
attrState = new Map();
|
|
15
|
-
elementAttrStates.set(element, attrState);
|
|
16
|
-
}
|
|
17
|
-
const changes = [];
|
|
18
|
-
const currentAttrs = new Set();
|
|
19
|
-
// Check all possible attributes from the coordinate map
|
|
20
|
-
for (const attrName of Object.keys(attrCoordMap)) {
|
|
21
|
-
const coordinate = attrCoordMap[attrName];
|
|
22
|
-
const currentValue = element.getAttribute(attrName);
|
|
23
|
-
const previousValue = attrState.get(attrName);
|
|
24
|
-
if (currentValue !== null) {
|
|
25
|
-
currentAttrs.add(attrName);
|
|
26
|
-
}
|
|
27
|
-
// Check if this attribute has "once: true" in its map entry
|
|
28
|
-
const mapEntry = mountInit.map?.[coordinate] || null;
|
|
29
|
-
const isOnce = mapEntry?.once === true;
|
|
30
|
-
// If "once" is true, check if we've already seen this attribute
|
|
31
|
-
if (isOnce) {
|
|
32
|
-
let onceAttrs = elementOnceAttrs.get(element);
|
|
33
|
-
if (!onceAttrs) {
|
|
34
|
-
onceAttrs = new Set();
|
|
35
|
-
elementOnceAttrs.set(element, onceAttrs);
|
|
36
|
-
}
|
|
37
|
-
// If we've already seen this attribute, skip it
|
|
38
|
-
if (onceAttrs.has(attrName)) {
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
// Mark this attribute as seen if it currently has a value
|
|
42
|
-
if (currentValue !== null) {
|
|
43
|
-
onceAttrs.add(attrName);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// Include if: currently has value OR previously had value but now removed
|
|
47
|
-
if (currentValue !== null || (previousValue !== undefined && currentValue === null)) {
|
|
48
|
-
// Check if value changed
|
|
49
|
-
if (currentValue !== previousValue) {
|
|
50
|
-
const attrNode = currentValue !== null ? element.getAttributeNode(attrName) : null;
|
|
51
|
-
changes.push({
|
|
52
|
-
value: currentValue,
|
|
53
|
-
attrNode,
|
|
54
|
-
mapEntry,
|
|
55
|
-
attrName,
|
|
56
|
-
coordinate,
|
|
57
|
-
element
|
|
58
|
-
});
|
|
59
|
-
// Update state
|
|
60
|
-
if (currentValue !== null) {
|
|
61
|
-
attrState.set(attrName, currentValue);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
attrState.delete(attrName);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return changes;
|
|
70
|
-
}
|