mount-observer 0.0.112 → 0.1.1
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/Events.js +62 -26
- package/Events.ts +52 -30
- package/MountObserver.js +285 -514
- package/MountObserver.ts +362 -538
- package/README.md +149 -56
- package/SharedMutationObserver.js +70 -0
- package/SharedMutationObserver.ts +96 -0
- package/attrCoordinates.js +93 -0
- package/attrCoordinates.ts +122 -0
- package/index.js +3 -0
- package/index.ts +22 -0
- package/loadImports.js +47 -0
- package/loadImports.ts +56 -0
- package/mediaQuery.js +86 -0
- package/mediaQuery.ts +113 -0
- package/package.json +11 -119
- package/playwright.config.ts +0 -1
- package/types.d.ts +104 -0
- package/whereAttr.js +174 -0
- package/whereAttr.ts +221 -0
- package/LICENSE +0 -21
- package/Newish.js +0 -145
- package/Newish.ts +0 -169
- package/ObsAttr.js +0 -18
- package/ObsAttr.ts +0 -18
- package/RootMutObs.js +0 -49
- package/RootMutObs.ts +0 -58
- package/Synthesizer.js +0 -125
- package/Synthesizer.ts +0 -130
- package/bindish.js +0 -15
- package/bindish.ts +0 -22
- package/compose.js +0 -148
- package/compose.ts +0 -164
- package/doCleanup.js +0 -31
- package/doCleanup.ts +0 -34
- package/getWhereAttrSelector.js +0 -83
- package/getWhereAttrSelector.ts +0 -92
- package/preloadContent.js +0 -44
- package/preloadContent.ts +0 -47
- package/readAttrs.ts +0 -60
- package/refid/README.md +0 -259
- package/refid/arr.js +0 -4
- package/refid/arr.ts +0 -4
- package/refid/camelToKebab.js +0 -4
- package/refid/camelToKebab.ts +0 -4
- package/refid/genIds.js +0 -190
- package/refid/genIds.ts +0 -177
- package/refid/getAdjRefs.js +0 -38
- package/refid/getAdjRefs.ts +0 -38
- package/refid/getContext.js +0 -13
- package/refid/getContext.ts +0 -14
- package/refid/getCount.js +0 -8
- package/refid/getCount.ts +0 -8
- package/refid/getIsh.js +0 -35
- package/refid/getIsh.ts +0 -37
- package/refid/hostish.js +0 -18
- package/refid/hostish.ts +0 -20
- package/refid/ism.js +0 -78
- package/refid/ism.ts +0 -81
- package/refid/itemprops.js +0 -60
- package/refid/itemprops.ts +0 -67
- package/refid/joinMatching.js +0 -56
- package/refid/joinMatching.ts +0 -54
- package/refid/nudge.js +0 -23
- package/refid/nudge.ts +0 -23
- package/refid/regIsh.js +0 -27
- package/refid/regIsh.ts +0 -31
- package/refid/secretKeys.js +0 -5
- package/refid/secretKeys.ts +0 -5
- package/refid/splitRefs.js +0 -6
- package/refid/splitRefs.ts +0 -6
- package/refid/stdVal.js +0 -15
- package/refid/stdVal.ts +0 -15
- package/refid/via.js +0 -114
- package/refid/via.ts +0 -113
- package/slotkin/affine.js +0 -39
- package/slotkin/affine.ts +0 -46
- package/slotkin/beKindred.js +0 -45
- package/slotkin/beKindred.ts +0 -55
- package/slotkin/getBreadth.js +0 -19
- package/slotkin/getBreadth.ts +0 -21
- package/slotkin/getFrag.js +0 -22
- package/slotkin/getFrag.ts +0 -21
- package/slotkin/toQuery.js +0 -12
- package/slotkin/toQuery.ts +0 -13
- package/slotkin/wrap.js +0 -13
- package/slotkin/wrap.ts +0 -18
- package/ts-refs/LICENSE +0 -21
- package/ts-refs/README.md +0 -18
- package/ts-refs/be-a-beacon/types.d.ts +0 -22
- package/ts-refs/be-alit/types.d.ts +0 -1
- package/ts-refs/be-based/types.d.ts +0 -32
- package/ts-refs/be-bound/types.d.ts +0 -65
- package/ts-refs/be-buttoned-up/types.d.ts +0 -21
- package/ts-refs/be-calculating/types.d.ts +0 -57
- package/ts-refs/be-clonable/types.d.ts +0 -28
- package/ts-refs/be-committed/types.d.ts +0 -26
- package/ts-refs/be-consoling/types.d.ts +0 -25
- package/ts-refs/be-counted/types.d.ts +0 -88
- package/ts-refs/be-delible/types.d.ts +0 -26
- package/ts-refs/be-directive/types.d.ts +0 -43
- package/ts-refs/be-dispatching/types.d.ts +0 -41
- package/ts-refs/be-elevating/types.d.ts +0 -55
- package/ts-refs/be-enhanced/types.d.ts +0 -32
- package/ts-refs/be-enhancing/types.d.ts +0 -31
- package/ts-refs/be-evanescent/types.d.ts +0 -20
- package/ts-refs/be-eventing/types.d.ts +0 -27
- package/ts-refs/be-exportable/types.d.ts +0 -26
- package/ts-refs/be-fetching/types.d.ts +0 -73
- package/ts-refs/be-flashy/types.d.ts +0 -27
- package/ts-refs/be-formalizing/types.d.ts +0 -29
- package/ts-refs/be-formidable/types.d.ts +0 -64
- package/ts-refs/be-giddy/types.d.ts +0 -26
- package/ts-refs/be-gingerly/types.d.ts +0 -19
- package/ts-refs/be-gone/types.d.ts +0 -24
- package/ts-refs/be-hashing-out/types.d.ts +0 -22
- package/ts-refs/be-hive/types.d.ts +0 -18
- package/ts-refs/be-imbued/types.d.ts +0 -30
- package/ts-refs/be-included/types.d.ts +0 -20
- package/ts-refs/be-inclusive/types.d.ts +0 -30
- package/ts-refs/be-intersectional/types.d.ts +0 -37
- package/ts-refs/be-intl/types.d.ts +0 -28
- package/ts-refs/be-invoking/types.d.ts +0 -28
- package/ts-refs/be-joining/types.d.ts +0 -26
- package/ts-refs/be-kvetching/types.d.ts +0 -24
- package/ts-refs/be-lazy/types.d.ts +0 -29
- package/ts-refs/be-literate/types.d.ts +0 -29
- package/ts-refs/be-mediating/types.d.ts +0 -34
- package/ts-refs/be-methodical/types.d.ts +0 -20
- package/ts-refs/be-modding/types.d.ts +0 -18
- package/ts-refs/be-observant/types.d.ts +0 -27
- package/ts-refs/be-observing/types.d.ts +0 -84
- package/ts-refs/be-parsed/types.d.ts +0 -19
- package/ts-refs/be-parsing/types.d.ts +0 -37
- package/ts-refs/be-persistent/types.d.ts +0 -66
- package/ts-refs/be-propagating/types.d.ts +0 -26
- package/ts-refs/be-reformable/types.d.ts +0 -48
- package/ts-refs/be-render-neutral/types.d.ts +0 -31
- package/ts-refs/be-scoped/types.d.ts +0 -24
- package/ts-refs/be-sharing/types.d.ts +0 -17
- package/ts-refs/be-switched/types.d.ts +0 -155
- package/ts-refs/be-typed/types.d.ts +0 -36
- package/ts-refs/be-value-added/types.d.ts +0 -34
- package/ts-refs/be-valued/types.d.ts +0 -22
- package/ts-refs/be-written/types.d.ts +0 -59
- package/ts-refs/css-charts/types.d.ts +0 -38
- package/ts-refs/css-echarts/types.d.ts +0 -13
- package/ts-refs/data-props/types.d.ts +0 -27
- package/ts-refs/do-inc/types.d.ts +0 -28
- package/ts-refs/do-invoke/types.d.ts +0 -28
- package/ts-refs/do-toggle/types.d.ts +0 -27
- package/ts-refs/em-bower/types.d.ts +0 -24
- package/ts-refs/fetch-for/types.d.ts +0 -37
- package/ts-refs/folder-picker/types.d.ts +0 -43
- package/ts-refs/for-fetch/doc.d.ts +0 -98
- package/ts-refs/for-fetch/types.d.ts +0 -83
- package/ts-refs/mount-observer/types.d.ts +0 -248
- package/ts-refs/mt-si/types.d.ts +0 -21
- package/ts-refs/per-each/types.d.ts +0 -51
- package/ts-refs/soak-up/types.d.ts +0 -36
- package/ts-refs/trans-render/XV/types.d.ts +0 -69
- package/ts-refs/trans-render/asmr/types.d.ts +0 -138
- package/ts-refs/trans-render/be/types.d.ts +0 -198
- package/ts-refs/trans-render/dss/types.d.ts +0 -57
- package/ts-refs/trans-render/froop/types.d.ts +0 -416
- package/ts-refs/trans-render/funions/types.d.ts +0 -12
- package/ts-refs/trans-render/lib/mixins/types.d.ts +0 -42
- package/ts-refs/trans-render/lib/prs/types.d.ts +0 -40
- package/ts-refs/trans-render/lib/types.d.ts +0 -489
- package/ts-refs/trans-render/types.d.ts +0 -583
- package/ts-refs/wc-info/SimpleWCInfo.d.ts +0 -15
- package/ts-refs/when-resolved/types.d.ts +0 -30
- package/ts-refs/xp-as/types.d.ts +0 -20
- package/ts-refs/xtal-element/types.d.ts +0 -43
- package/ts-refs/xtal-frappe-chart/types.d.ts +0 -193
- package/upShadowSearch.js +0 -25
- package/upShadowSearch.ts +0 -23
- package/waitForEvent.js +0 -12
- package/waitForEvent.ts +0 -13
- package/waitForIsh.js +0 -21
- package/waitForIsh.ts +0 -20
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { WhereAttr, BranchValue } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a mapping from attribute name to coordinate
|
|
5
|
+
*/
|
|
6
|
+
export interface AttrCoordinateMap {
|
|
7
|
+
[attrName: string]: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Builds a map of attribute names to their coordinates based on whereAttr config
|
|
12
|
+
*/
|
|
13
|
+
export function buildAttrCoordinateMap(whereAttr: WhereAttr, isCustomElement: boolean): AttrCoordinateMap {
|
|
14
|
+
const map: AttrCoordinateMap = {};
|
|
15
|
+
const rootPrefixes = isCustomElement
|
|
16
|
+
? (whereAttr.hasCERootIn || [])
|
|
17
|
+
: (whereAttr.hasBuiltInRootIn || []);
|
|
18
|
+
|
|
19
|
+
// Parse base attribute for custom delimiter
|
|
20
|
+
const { delimiter: baseDelimiter, name: baseName } = parseDelimiter(whereAttr.hasBase);
|
|
21
|
+
|
|
22
|
+
// Build attribute names for each prefix
|
|
23
|
+
for (const prefix of rootPrefixes) {
|
|
24
|
+
const baseAttrName = buildAttributeName(prefix, baseName, baseDelimiter);
|
|
25
|
+
|
|
26
|
+
// If no branches specified, just the base attribute
|
|
27
|
+
if (!whereAttr.hasBranchIn || whereAttr.hasBranchIn.length === 0) {
|
|
28
|
+
map[baseAttrName] = '0';
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Process each branch
|
|
33
|
+
for (let i = 0; i < whereAttr.hasBranchIn.length; i++) {
|
|
34
|
+
const branch = whereAttr.hasBranchIn[i];
|
|
35
|
+
|
|
36
|
+
if (branch === '') {
|
|
37
|
+
// Empty string means base attribute alone is valid
|
|
38
|
+
map[baseAttrName] = '0';
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (typeof branch === 'object') {
|
|
43
|
+
// Process branch object
|
|
44
|
+
processBranch(branch, baseAttrName, String(i), map);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return map;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Recursively processes a branch object to build attribute-coordinate mappings
|
|
54
|
+
*/
|
|
55
|
+
function processBranch(
|
|
56
|
+
branch: { [key: string]: BranchValue[] },
|
|
57
|
+
parentAttrName: string,
|
|
58
|
+
parentCoordinate: string,
|
|
59
|
+
map: AttrCoordinateMap
|
|
60
|
+
): void {
|
|
61
|
+
for (const [key, subBranches] of Object.entries(branch)) {
|
|
62
|
+
const { delimiter, name } = parseDelimiter(key);
|
|
63
|
+
const attrName = parentAttrName + delimiter + name;
|
|
64
|
+
|
|
65
|
+
// Process sub-branches
|
|
66
|
+
if (!subBranches || subBranches.length === 0) {
|
|
67
|
+
map[attrName] = parentCoordinate;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
for (let i = 0; i < subBranches.length; i++) {
|
|
72
|
+
const subBranch = subBranches[i];
|
|
73
|
+
const coordinate = `${parentCoordinate}.${i}`;
|
|
74
|
+
|
|
75
|
+
if (subBranch === '') {
|
|
76
|
+
// Empty string means this level alone is valid
|
|
77
|
+
map[attrName] = parentCoordinate;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (typeof subBranch === 'string') {
|
|
82
|
+
// Simple string sub-branch
|
|
83
|
+
const { delimiter: subDelimiter, name: subName } = parseDelimiter(subBranch);
|
|
84
|
+
const subAttrName = attrName + subDelimiter + subName;
|
|
85
|
+
map[subAttrName] = coordinate;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (typeof subBranch === 'object') {
|
|
90
|
+
// Nested object - recursively process
|
|
91
|
+
processBranch(subBranch, attrName, coordinate, map);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Parses a key to extract custom delimiter and name
|
|
99
|
+
*/
|
|
100
|
+
function parseDelimiter(key: string): { delimiter: string; name: string } {
|
|
101
|
+
const match = key.match(/^\[(.+?)\](.+)$/);
|
|
102
|
+
if (match) {
|
|
103
|
+
return {
|
|
104
|
+
delimiter: match[1],
|
|
105
|
+
name: match[2]
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
delimiter: '-',
|
|
110
|
+
name: key
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Builds the full attribute name from prefix, base name, and delimiter
|
|
116
|
+
*/
|
|
117
|
+
function buildAttributeName(prefix: string, baseName: string, delimiter: string): string {
|
|
118
|
+
if (prefix === '') {
|
|
119
|
+
return baseName;
|
|
120
|
+
}
|
|
121
|
+
return prefix + delimiter + baseName;
|
|
122
|
+
}
|
package/index.js
ADDED
package/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Main entry point for MountObserver v2
|
|
2
|
+
export { MountObserver } from './MountObserver.js';
|
|
3
|
+
export type {
|
|
4
|
+
MountInit,
|
|
5
|
+
MountObserverOptions,
|
|
6
|
+
IMountObserver,
|
|
7
|
+
MountContext,
|
|
8
|
+
DoCallback,
|
|
9
|
+
DoCallbacks,
|
|
10
|
+
ImportSpec,
|
|
11
|
+
IMountEvent,
|
|
12
|
+
IDismountEvent
|
|
13
|
+
} from './types.js';
|
|
14
|
+
export {
|
|
15
|
+
mountEventName,
|
|
16
|
+
dismountEventName,
|
|
17
|
+
disconnectEventName,
|
|
18
|
+
loadEventName,
|
|
19
|
+
attrchangeEventName,
|
|
20
|
+
mediamatchEventName,
|
|
21
|
+
mediaunmatchEventName
|
|
22
|
+
} from './Events.js';
|
package/loadImports.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Dynamic import loading utilities
|
|
2
|
+
// Only loaded when MountInit.import is specified
|
|
3
|
+
export async function loadImports(imports) {
|
|
4
|
+
const importArray = Array.isArray(imports) ? imports : [imports];
|
|
5
|
+
const promises = importArray.map(imp => loadSingleImport(imp));
|
|
6
|
+
return Promise.all(promises);
|
|
7
|
+
}
|
|
8
|
+
async function loadSingleImport(imp) {
|
|
9
|
+
let url;
|
|
10
|
+
let type = 'js';
|
|
11
|
+
if (typeof imp === 'string') {
|
|
12
|
+
url = imp;
|
|
13
|
+
}
|
|
14
|
+
else if (Array.isArray(imp)) {
|
|
15
|
+
url = imp[0];
|
|
16
|
+
type = imp[1]?.type || 'js';
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
url = imp.url;
|
|
20
|
+
type = imp.type || 'js';
|
|
21
|
+
}
|
|
22
|
+
switch (type) {
|
|
23
|
+
case 'css':
|
|
24
|
+
return loadCSS(url);
|
|
25
|
+
case 'json':
|
|
26
|
+
return loadJSON(url);
|
|
27
|
+
case 'html':
|
|
28
|
+
return loadHTML(url);
|
|
29
|
+
default:
|
|
30
|
+
return import(url);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function loadCSS(url) {
|
|
34
|
+
const response = await fetch(url);
|
|
35
|
+
const text = await response.text();
|
|
36
|
+
const sheet = new CSSStyleSheet();
|
|
37
|
+
await sheet.replace(text);
|
|
38
|
+
return sheet;
|
|
39
|
+
}
|
|
40
|
+
async function loadJSON(url) {
|
|
41
|
+
const response = await fetch(url);
|
|
42
|
+
return response.json();
|
|
43
|
+
}
|
|
44
|
+
async function loadHTML(url) {
|
|
45
|
+
const response = await fetch(url);
|
|
46
|
+
return response.text();
|
|
47
|
+
}
|
package/loadImports.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Dynamic import loading utilities
|
|
2
|
+
// Only loaded when MountInit.import is specified
|
|
3
|
+
|
|
4
|
+
import { ImportSpec } from './types.js';
|
|
5
|
+
|
|
6
|
+
export async function loadImports(
|
|
7
|
+
imports: string | ImportSpec | Array<string | ImportSpec | [string, any]>
|
|
8
|
+
): Promise<any[]> {
|
|
9
|
+
const importArray = Array.isArray(imports) ? imports : [imports];
|
|
10
|
+
const promises = importArray.map(imp => loadSingleImport(imp));
|
|
11
|
+
return Promise.all(promises);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function loadSingleImport(imp: string | ImportSpec | [string, any]): Promise<any> {
|
|
15
|
+
let url: string;
|
|
16
|
+
let type: string = 'js';
|
|
17
|
+
|
|
18
|
+
if (typeof imp === 'string') {
|
|
19
|
+
url = imp;
|
|
20
|
+
} else if (Array.isArray(imp)) {
|
|
21
|
+
url = imp[0];
|
|
22
|
+
type = imp[1]?.type || 'js';
|
|
23
|
+
} else {
|
|
24
|
+
url = imp.url;
|
|
25
|
+
type = imp.type || 'js';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
switch (type) {
|
|
29
|
+
case 'css':
|
|
30
|
+
return loadCSS(url);
|
|
31
|
+
case 'json':
|
|
32
|
+
return loadJSON(url);
|
|
33
|
+
case 'html':
|
|
34
|
+
return loadHTML(url);
|
|
35
|
+
default:
|
|
36
|
+
return import(url);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function loadCSS(url: string): Promise<CSSStyleSheet> {
|
|
41
|
+
const response = await fetch(url);
|
|
42
|
+
const text = await response.text();
|
|
43
|
+
const sheet = new CSSStyleSheet();
|
|
44
|
+
await sheet.replace(text);
|
|
45
|
+
return sheet;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function loadJSON(url: string): Promise<any> {
|
|
49
|
+
const response = await fetch(url);
|
|
50
|
+
return response.json();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function loadHTML(url: string): Promise<string> {
|
|
54
|
+
const response = await fetch(url);
|
|
55
|
+
return response.text();
|
|
56
|
+
}
|
package/mediaQuery.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { MediaMatchEvent, MediaUnmatchEvent, DismountEvent } from './Events.js';
|
|
2
|
+
export function setupMediaQuery(init, rootNodeRef, mountedElements, modules, observer, processNode) {
|
|
3
|
+
const { whereMediaMatches } = init;
|
|
4
|
+
// Create or use MediaQueryList
|
|
5
|
+
let mediaQueryList;
|
|
6
|
+
if (typeof whereMediaMatches === 'string') {
|
|
7
|
+
mediaQueryList = window.matchMedia(whereMediaMatches);
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
mediaQueryList = whereMediaMatches;
|
|
11
|
+
}
|
|
12
|
+
// Track current state
|
|
13
|
+
let mediaMatches = mediaQueryList.matches;
|
|
14
|
+
// Set up change listener
|
|
15
|
+
const mediaChangeHandler = (e) => {
|
|
16
|
+
const previousMatches = mediaMatches;
|
|
17
|
+
mediaMatches = e.matches;
|
|
18
|
+
if (e.matches && !previousMatches) {
|
|
19
|
+
// Media query now matches - wake up and process elements
|
|
20
|
+
handleMediaMatch();
|
|
21
|
+
}
|
|
22
|
+
else if (!e.matches && previousMatches) {
|
|
23
|
+
// Media query no longer matches - dismount all elements
|
|
24
|
+
handleMediaUnmatch();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function handleMediaMatch() {
|
|
28
|
+
// Dispatch mediamatch event if requested
|
|
29
|
+
if (init.getPlayByPlay) {
|
|
30
|
+
observer.dispatchEvent(new MediaMatchEvent(init));
|
|
31
|
+
}
|
|
32
|
+
// Process all elements in the observed node
|
|
33
|
+
const rootNode = rootNodeRef.deref();
|
|
34
|
+
if (rootNode) {
|
|
35
|
+
processNode(rootNode);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function handleMediaUnmatch() {
|
|
39
|
+
// Dispatch mediaunmatch event if requested
|
|
40
|
+
if (init.getPlayByPlay) {
|
|
41
|
+
observer.dispatchEvent(new MediaUnmatchEvent(init));
|
|
42
|
+
}
|
|
43
|
+
// Dismount all currently mounted elements
|
|
44
|
+
const rootNode = rootNodeRef.deref();
|
|
45
|
+
if (!rootNode) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const context = {
|
|
49
|
+
modules,
|
|
50
|
+
observer: observer,
|
|
51
|
+
observeInfo: {
|
|
52
|
+
rootNode
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
// Get all mounted elements (we need to iterate through the DOM to find them)
|
|
56
|
+
const mountedElementsList = [];
|
|
57
|
+
const collectMountedElements = (node) => {
|
|
58
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
59
|
+
const element = node;
|
|
60
|
+
if (mountedElements.has(element)) {
|
|
61
|
+
mountedElementsList.push(element);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
node.childNodes.forEach(child => collectMountedElements(child));
|
|
65
|
+
};
|
|
66
|
+
collectMountedElements(rootNode);
|
|
67
|
+
// Dismount each element
|
|
68
|
+
for (const element of mountedElementsList) {
|
|
69
|
+
mountedElements.delete(element);
|
|
70
|
+
// Call dismount callback
|
|
71
|
+
if (init.do && typeof init.do !== 'function' && init.do.dismount) {
|
|
72
|
+
init.do.dismount(element, context);
|
|
73
|
+
}
|
|
74
|
+
// Dispatch dismount event with reason
|
|
75
|
+
observer.dispatchEvent(new DismountEvent(element, 'media-query-failed', init));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
mediaQueryList.addEventListener('change', mediaChangeHandler);
|
|
79
|
+
return {
|
|
80
|
+
mediaQueryList,
|
|
81
|
+
mediaMatches,
|
|
82
|
+
cleanup: () => {
|
|
83
|
+
mediaQueryList.removeEventListener('change', mediaChangeHandler);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
package/mediaQuery.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Media query handling for MountObserver
|
|
2
|
+
import type { MountInit, MountContext } from './types.js';
|
|
3
|
+
import { MediaMatchEvent, MediaUnmatchEvent, DismountEvent } from './Events.js';
|
|
4
|
+
|
|
5
|
+
export function setupMediaQuery(
|
|
6
|
+
init: MountInit,
|
|
7
|
+
rootNodeRef: WeakRef<Node>,
|
|
8
|
+
mountedElements: WeakSet<Element>,
|
|
9
|
+
modules: any[],
|
|
10
|
+
observer: EventTarget,
|
|
11
|
+
processNode: (node: Node) => void
|
|
12
|
+
): {
|
|
13
|
+
mediaQueryList: MediaQueryList;
|
|
14
|
+
mediaMatches: boolean;
|
|
15
|
+
cleanup: () => void;
|
|
16
|
+
} {
|
|
17
|
+
const { whereMediaMatches } = init;
|
|
18
|
+
|
|
19
|
+
// Create or use MediaQueryList
|
|
20
|
+
let mediaQueryList: MediaQueryList;
|
|
21
|
+
if (typeof whereMediaMatches === 'string') {
|
|
22
|
+
mediaQueryList = window.matchMedia(whereMediaMatches);
|
|
23
|
+
} else {
|
|
24
|
+
mediaQueryList = whereMediaMatches!;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Track current state
|
|
28
|
+
let mediaMatches = mediaQueryList.matches;
|
|
29
|
+
|
|
30
|
+
// Set up change listener
|
|
31
|
+
const mediaChangeHandler = (e: MediaQueryListEvent) => {
|
|
32
|
+
const previousMatches = mediaMatches;
|
|
33
|
+
mediaMatches = e.matches;
|
|
34
|
+
|
|
35
|
+
if (e.matches && !previousMatches) {
|
|
36
|
+
// Media query now matches - wake up and process elements
|
|
37
|
+
handleMediaMatch();
|
|
38
|
+
} else if (!e.matches && previousMatches) {
|
|
39
|
+
// Media query no longer matches - dismount all elements
|
|
40
|
+
handleMediaUnmatch();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
function handleMediaMatch(): void {
|
|
45
|
+
// Dispatch mediamatch event if requested
|
|
46
|
+
if (init.getPlayByPlay) {
|
|
47
|
+
observer.dispatchEvent(new MediaMatchEvent(init));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Process all elements in the observed node
|
|
51
|
+
const rootNode = rootNodeRef.deref();
|
|
52
|
+
if (rootNode) {
|
|
53
|
+
processNode(rootNode);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function handleMediaUnmatch(): void {
|
|
58
|
+
// Dispatch mediaunmatch event if requested
|
|
59
|
+
if (init.getPlayByPlay) {
|
|
60
|
+
observer.dispatchEvent(new MediaUnmatchEvent(init));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Dismount all currently mounted elements
|
|
64
|
+
const rootNode = rootNodeRef.deref();
|
|
65
|
+
if (!rootNode) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const context: MountContext = {
|
|
70
|
+
modules,
|
|
71
|
+
observer: observer as any,
|
|
72
|
+
observeInfo: {
|
|
73
|
+
rootNode
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Get all mounted elements (we need to iterate through the DOM to find them)
|
|
78
|
+
const mountedElementsList: Element[] = [];
|
|
79
|
+
const collectMountedElements = (node: Node) => {
|
|
80
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
81
|
+
const element = node as Element;
|
|
82
|
+
if (mountedElements.has(element)) {
|
|
83
|
+
mountedElementsList.push(element);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
node.childNodes.forEach(child => collectMountedElements(child));
|
|
87
|
+
};
|
|
88
|
+
collectMountedElements(rootNode);
|
|
89
|
+
|
|
90
|
+
// Dismount each element
|
|
91
|
+
for (const element of mountedElementsList) {
|
|
92
|
+
mountedElements.delete(element);
|
|
93
|
+
|
|
94
|
+
// Call dismount callback
|
|
95
|
+
if (init.do && typeof init.do !== 'function' && init.do.dismount) {
|
|
96
|
+
init.do.dismount(element, context);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Dispatch dismount event with reason
|
|
100
|
+
observer.dispatchEvent(new DismountEvent(element, 'media-query-failed', init));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
mediaQueryList.addEventListener('change', mediaChangeHandler);
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
mediaQueryList,
|
|
108
|
+
mediaMatches,
|
|
109
|
+
cleanup: () => {
|
|
110
|
+
mediaQueryList.removeEventListener('change', mediaChangeHandler);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
package/package.json
CHANGED
|
@@ -1,145 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mount-observer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Observe and act on css matches.",
|
|
5
5
|
"main": "MountObserver.js",
|
|
6
6
|
"module": "MountObserver.js",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"assign-gingerly": "0.0.2"
|
|
9
|
+
},
|
|
7
10
|
"devDependencies": {
|
|
8
|
-
"@playwright/test": "1.
|
|
9
|
-
"spa-ssi": "0.0.
|
|
11
|
+
"@playwright/test": "1.58.0",
|
|
12
|
+
"spa-ssi": "0.0.26"
|
|
10
13
|
},
|
|
11
14
|
"exports": {
|
|
12
15
|
".": {
|
|
13
|
-
"default": "./
|
|
14
|
-
"types": "./
|
|
16
|
+
"default": "./index.js",
|
|
17
|
+
"types": "./index.ts"
|
|
15
18
|
},
|
|
16
19
|
"./MountObserver.js": {
|
|
17
20
|
"default": "./MountObserver.js",
|
|
18
21
|
"types": "./MountObserver.ts"
|
|
19
|
-
},
|
|
20
|
-
"./Newish.js": {
|
|
21
|
-
"default": "./Newish.js",
|
|
22
|
-
"types": "./Newish.ts"
|
|
23
|
-
},
|
|
24
|
-
"./ObsAttr.js": {
|
|
25
|
-
"default": "./ObsAttr.js",
|
|
26
|
-
"types": "./ObsAttr.ts"
|
|
27
|
-
},
|
|
28
|
-
"./Synthesizer.js": {
|
|
29
|
-
"default": "./Synthesizer.js",
|
|
30
|
-
"types": "./Synthesizer.ts"
|
|
31
|
-
},
|
|
32
|
-
"./bindish.js": {
|
|
33
|
-
"default": "./bindish.js",
|
|
34
|
-
"types": "./bindish.ts"
|
|
35
|
-
},
|
|
36
|
-
"./compose.js": {
|
|
37
|
-
"default": "./compose.js",
|
|
38
|
-
"types": "./compose.ts"
|
|
39
|
-
},
|
|
40
|
-
"./doCleanup.js": {
|
|
41
|
-
"default": "./doCleanup.js",
|
|
42
|
-
"types": "./doCleanup.ts"
|
|
43
|
-
},
|
|
44
|
-
"./upShadowSearch.js": {
|
|
45
|
-
"default": "./upShadowSearch.js",
|
|
46
|
-
"types": "./upShadowSearch.ts"
|
|
47
|
-
},
|
|
48
|
-
"./waitForEvent.js": {
|
|
49
|
-
"default": "./waitForEvent.js",
|
|
50
|
-
"types": "./waitForEvent.ts"
|
|
51
|
-
},
|
|
52
|
-
"./waitForIsh.js": {
|
|
53
|
-
"default": "./waitForIsh.js",
|
|
54
|
-
"types": "./waitForIsh.ts"
|
|
55
|
-
},
|
|
56
|
-
"./refid/camelToKebab.js": {
|
|
57
|
-
"default": "./refid/camelToKebab.js",
|
|
58
|
-
"types": "./refid/camelToKebab.ts"
|
|
59
|
-
},
|
|
60
|
-
"./refid/refid/genIds.js": {
|
|
61
|
-
"default": "./refid/refid/genIds.js",
|
|
62
|
-
"types": "./refid/refid/genIds.ts"
|
|
63
|
-
},
|
|
64
|
-
"./refid/getAdjRefs.js": {
|
|
65
|
-
"default": "./refid/getAdjRefs.js",
|
|
66
|
-
"types": "./refid/getAdjRefs.ts"
|
|
67
|
-
},
|
|
68
|
-
"./refid/getContext.js": {
|
|
69
|
-
"default": "./refid/getContext.js",
|
|
70
|
-
"types": "./refid/getContext.ts"
|
|
71
|
-
},
|
|
72
|
-
"./refid/getCount.js": {
|
|
73
|
-
"default": "./refid/getCount.js",
|
|
74
|
-
"types": "./refid/getCount.ts"
|
|
75
|
-
},
|
|
76
|
-
"./refid/ism.js": {
|
|
77
|
-
"default": "./refid/ism.js",
|
|
78
|
-
"types": "./refid/ism.ts"
|
|
79
|
-
},
|
|
80
|
-
"./refid/itemprops.js": {
|
|
81
|
-
"default": "./refid/itemprops.js",
|
|
82
|
-
"types": "./refid/itemprops.ts"
|
|
83
|
-
},
|
|
84
|
-
"./refid/joinMatching.js": {
|
|
85
|
-
"default": "./refid/joinMatching.js",
|
|
86
|
-
"types": "./refid/joinMatching.ts"
|
|
87
|
-
},
|
|
88
|
-
"./refid/nudge.js": {
|
|
89
|
-
"default": "./refid/nudge.js",
|
|
90
|
-
"types": "./refid/nudge.ts"
|
|
91
|
-
},
|
|
92
|
-
"./refid/refs.js": {
|
|
93
|
-
"default": "./refid/refs.js",
|
|
94
|
-
"types": "./refid/refs.ts"
|
|
95
|
-
},
|
|
96
|
-
"./refid/regIsh.js": {
|
|
97
|
-
"default": "./refid/regIsh.js",
|
|
98
|
-
"types": "./refid/regIsh.ts"
|
|
99
|
-
},
|
|
100
|
-
"./refid/splitRefs.js": {
|
|
101
|
-
"default": "./refid/splitRefs.js",
|
|
102
|
-
"types": "./refid/splitRefs.ts"
|
|
103
|
-
},
|
|
104
|
-
"./refid/stdVal.js": {
|
|
105
|
-
"default": "./refid/stdVal.js",
|
|
106
|
-
"types": "./refid/stdVal.ts"
|
|
107
|
-
},
|
|
108
|
-
"./refid/via.js": {
|
|
109
|
-
"default": "./refid/via.js",
|
|
110
|
-
"types": "./refid/via.ts"
|
|
111
|
-
},
|
|
112
|
-
"./slotkin/beKindred.js": {
|
|
113
|
-
"default": "./slotkin/beKindred.js",
|
|
114
|
-
"types": "./slotkin/beKindred.ts"
|
|
115
|
-
},
|
|
116
|
-
"./slotkin/getBreadth.js": {
|
|
117
|
-
"default": "./slotkin/getBreadth.js",
|
|
118
|
-
"types": "./slotkin/getBreadth.ts"
|
|
119
|
-
},
|
|
120
|
-
"./slotkin/getFrag.js": {
|
|
121
|
-
"default": "./slotkin/getFrag.js",
|
|
122
|
-
"types": "./slotkin/getFrag.ts"
|
|
123
|
-
},
|
|
124
|
-
"./slotkin/wrap.js": {
|
|
125
|
-
"default": "./slotkin/wrap.js",
|
|
126
|
-
"types": "./slotkin/wrap.ts"
|
|
127
22
|
}
|
|
128
23
|
},
|
|
129
24
|
"files": [
|
|
130
25
|
"*.js",
|
|
131
|
-
"*.ts"
|
|
132
|
-
"./ts-refs/*",
|
|
133
|
-
"./refid/*",
|
|
134
|
-
"./slotkin/*"
|
|
26
|
+
"*.ts"
|
|
135
27
|
],
|
|
136
|
-
"types": "./
|
|
28
|
+
"types": "./types.d.ts",
|
|
137
29
|
"scripts": {
|
|
138
30
|
"serve": "node ./node_modules/spa-ssi/serve.js",
|
|
139
31
|
"test": "playwright test",
|
|
140
32
|
"safari": "npx playwright wk http://localhost:8000",
|
|
141
33
|
"update": "ncu -u && npm install"
|
|
142
34
|
},
|
|
143
|
-
"author": "",
|
|
35
|
+
"author": "Bruce B. Anderson <anderson.bruce.b@gmail.com>",
|
|
144
36
|
"license": "MIT"
|
|
145
37
|
}
|