mount-observer 0.1.4 → 0.1.6

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.
@@ -1,6 +1,6 @@
1
1
  import { EvtRt } from './EvtRt.js';
2
2
  export class DefineCustomElementHandler extends EvtRt {
3
- mount(mountedElement, mountInit, context) {
3
+ mount(mountedElement, MountConfig, context) {
4
4
  // Check if modules are specified
5
5
  if (!context.modules || context.modules.length === 0) {
6
6
  throw new Error('Must specify an ES Module');
@@ -21,8 +21,18 @@ export class DefineCustomElementHandler extends EvtRt {
21
21
  // Use anonymous class expression which works across all browsers
22
22
  const WrapperClass = class extends ElementClass {
23
23
  };
24
- // Define the custom element
25
- customElements.define(tagName, WrapperClass);
24
+ // Define the custom element using the define method
25
+ this.define(tagName, WrapperClass, mountedElement);
26
+ }
27
+ /**
28
+ * Define the custom element in the appropriate registry.
29
+ * Override this method in subclasses to use scoped registries.
30
+ * @param tagName - The custom element tag name
31
+ * @param ElementClass - The element class constructor
32
+ * @param mountedElement - The mounted element (used for scoped registry access)
33
+ */
34
+ define(tagName, ElementClass, mountedElement) {
35
+ customElements.define(tagName, ElementClass);
26
36
  }
27
37
  findSuitableClass(module) {
28
38
  // Check default export first
@@ -62,3 +72,27 @@ export class DefineCustomElementHandler extends EvtRt {
62
72
  }
63
73
  }
64
74
  }
75
+ /**
76
+ * Handler for defining custom elements in scoped registries.
77
+ * Uses the element's customElementRegistry property to define elements
78
+ * in the appropriate scoped registry instead of the global registry.
79
+ */
80
+ export class DefineScopedCustomElementHandler extends DefineCustomElementHandler {
81
+ /**
82
+ * Define the custom element in the element's scoped registry.
83
+ * @param tagName - The custom element tag name
84
+ * @param ElementClass - The element class constructor
85
+ * @param mountedElement - The mounted element with customElementRegistry
86
+ */
87
+ define(tagName, ElementClass, mountedElement) {
88
+ const registry = mountedElement.customElementRegistry;
89
+ if (!registry) {
90
+ throw new Error('Element does not have a customElementRegistry. Scoped registries require Chrome 146+ or latest WebKit/Safari.');
91
+ }
92
+ // Check if already defined in this scoped registry
93
+ if (registry.get(tagName)) {
94
+ return;
95
+ }
96
+ registry.define(tagName, ElementClass);
97
+ }
98
+ }
@@ -1,8 +1,8 @@
1
1
  import { EvtRt } from './EvtRt.js';
2
- import { MountInit, MountContext } from './types.js';
2
+ import { MountConfig, MountContext } from './types.js';
3
3
 
4
4
  export class DefineCustomElementHandler extends EvtRt {
5
- mount(mountedElement: Element, mountInit: MountInit, context: MountContext): void {
5
+ mount(mountedElement: Element, MountConfig: MountConfig, context: MountContext): void {
6
6
  // Check if modules are specified
7
7
  if (!context.modules || context.modules.length === 0) {
8
8
  throw new Error('Must specify an ES Module');
@@ -28,8 +28,19 @@ export class DefineCustomElementHandler extends EvtRt {
28
28
  // Use anonymous class expression which works across all browsers
29
29
  const WrapperClass = class extends ElementClass {};
30
30
 
31
- // Define the custom element
32
- customElements.define(tagName, WrapperClass);
31
+ // Define the custom element using the define method
32
+ this.define(tagName, WrapperClass, mountedElement);
33
+ }
34
+
35
+ /**
36
+ * Define the custom element in the appropriate registry.
37
+ * Override this method in subclasses to use scoped registries.
38
+ * @param tagName - The custom element tag name
39
+ * @param ElementClass - The element class constructor
40
+ * @param mountedElement - The mounted element (used for scoped registry access)
41
+ */
42
+ protected define(tagName: string, ElementClass: CustomElementConstructor, mountedElement: Element): void {
43
+ customElements.define(tagName, ElementClass);
33
44
  }
34
45
 
35
46
  private findSuitableClass(module: any): typeof HTMLElement {
@@ -75,3 +86,31 @@ export class DefineCustomElementHandler extends EvtRt {
75
86
  }
76
87
  }
77
88
  }
89
+
90
+ /**
91
+ * Handler for defining custom elements in scoped registries.
92
+ * Uses the element's customElementRegistry property to define elements
93
+ * in the appropriate scoped registry instead of the global registry.
94
+ */
95
+ export class DefineScopedCustomElementHandler extends DefineCustomElementHandler {
96
+ /**
97
+ * Define the custom element in the element's scoped registry.
98
+ * @param tagName - The custom element tag name
99
+ * @param ElementClass - The element class constructor
100
+ * @param mountedElement - The mounted element with customElementRegistry
101
+ */
102
+ protected define(tagName: string, ElementClass: CustomElementConstructor, mountedElement: Element): void {
103
+ const registry = (mountedElement as any).customElementRegistry;
104
+
105
+ if (!registry) {
106
+ throw new Error('Element does not have a customElementRegistry. Scoped registries require Chrome 146+ or latest WebKit/Safari.');
107
+ }
108
+
109
+ // Check if already defined in this scoped registry
110
+ if (registry.get(tagName)) {
111
+ return;
112
+ }
113
+
114
+ registry.define(tagName, ElementClass);
115
+ }
116
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Extension to Element.prototype to support mounting observers directly on elements.
3
+ * This finds the appropriate scoped registry container and observes it.
4
+ */
5
+ import { MountObserver } from './MountObserver.js';
6
+ import { getRootRegistryContainer } from './getRootRegistryContainer.js';
7
+ /**
8
+ * Adds a mount method to Element.prototype that:
9
+ * 1. Determines the observation scope based on options.scope
10
+ * 2. Creates a MountObserver with the provided config
11
+ * 3. Observes that scope
12
+ * 4. Returns the element for chaining
13
+ */
14
+ Object.defineProperty(Element.prototype, 'mount', {
15
+ value: async function (config, options = {}) {
16
+ const scope = options.scope ?? 'registry';
17
+ let thingToObserve;
18
+ if (scope === 'registry') {
19
+ const registryContainer = getRootRegistryContainer(this);
20
+ if (!registryContainer) {
21
+ throw new Error('Could not find root registry container');
22
+ }
23
+ thingToObserve = registryContainer;
24
+ }
25
+ else if (scope === 'self') {
26
+ thingToObserve = this;
27
+ }
28
+ else if (scope === 'root') {
29
+ thingToObserve = this.getRootNode();
30
+ }
31
+ else if (scope === 'shadow') {
32
+ const shadowRoot = this.shadowRoot;
33
+ if (!shadowRoot) {
34
+ throw new Error('Element does not have a shadowRoot');
35
+ }
36
+ thingToObserve = shadowRoot;
37
+ }
38
+ else {
39
+ // scope is an Element
40
+ thingToObserve = scope;
41
+ }
42
+ const mo = new MountObserver(config, options);
43
+ await mo.observe(thingToObserve);
44
+ return this;
45
+ },
46
+ writable: true,
47
+ enumerable: false,
48
+ configurable: true,
49
+ });
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Extension to Element.prototype to support mounting observers directly on elements.
3
+ * This finds the appropriate scoped registry container and observes it.
4
+ */
5
+
6
+ import { MountObserver } from './MountObserver.js';
7
+ import { getRootRegistryContainer } from './getRootRegistryContainer.js';
8
+ import type { MountConfig, MountObserverOptions } from './types.js';
9
+ import type { EnhancementConfig } from 'assign-gingerly/types.js';
10
+
11
+ declare global {
12
+ interface Element {
13
+ mount<T extends Element>(
14
+ this: T,
15
+ config: MountConfig | EnhancementConfig[],
16
+ options?: MountObserverOptions
17
+ ): Promise<T>;
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Adds a mount method to Element.prototype that:
23
+ * 1. Determines the observation scope based on options.scope
24
+ * 2. Creates a MountObserver with the provided config
25
+ * 3. Observes that scope
26
+ * 4. Returns the element for chaining
27
+ */
28
+ Object.defineProperty(Element.prototype, 'mount', {
29
+ value: async function <T extends Element>(
30
+ this: T,
31
+ config: MountConfig | EnhancementConfig[],
32
+ options: MountObserverOptions = {}
33
+ ): Promise<T> {
34
+ const scope = options.scope ?? 'registry';
35
+ let thingToObserve: Node;
36
+
37
+ if (scope === 'registry') {
38
+ const registryContainer = getRootRegistryContainer(this);
39
+ if (!registryContainer) {
40
+ throw new Error('Could not find root registry container');
41
+ }
42
+ thingToObserve = registryContainer;
43
+ } else if (scope === 'self') {
44
+ thingToObserve = this;
45
+ } else if (scope === 'root') {
46
+ thingToObserve = this.getRootNode();
47
+ } else if (scope === 'shadow') {
48
+ const shadowRoot = (this as any).shadowRoot;
49
+ if (!shadowRoot) {
50
+ throw new Error('Element does not have a shadowRoot');
51
+ }
52
+ thingToObserve = shadowRoot;
53
+ } else {
54
+ // scope is an Element
55
+ thingToObserve = scope;
56
+ }
57
+
58
+ const mo = new MountObserver(config, options);
59
+ await mo.observe(thingToObserve);
60
+ return this;
61
+ },
62
+ writable: true,
63
+ enumerable: false,
64
+ configurable: true,
65
+ });
package/Events.js CHANGED
@@ -3,78 +3,67 @@ export const loadEventName = 'load';
3
3
  export const mountEventName = 'mount';
4
4
  export const dismountEventName = 'dismount';
5
5
  export const disconnectEventName = 'disconnect';
6
- export const attrchangeEventName = 'attrchange';
7
6
  export const mediamatchEventName = 'mediamatch';
8
7
  export const mediaunmatchEventName = 'mediaunmatch';
9
8
  export class MountEvent extends Event {
10
9
  mountedElement;
11
10
  modules;
12
- mountInit;
11
+ MountConfig;
13
12
  mountContext;
14
13
  static eventName = mountEventName;
15
- constructor(mountedElement, modules, mountInit, mountContext) {
14
+ constructor(mountedElement, modules, MountConfig, mountContext) {
16
15
  super(MountEvent.eventName);
17
16
  this.mountedElement = mountedElement;
18
17
  this.modules = modules;
19
- this.mountInit = mountInit;
18
+ this.MountConfig = MountConfig;
20
19
  this.mountContext = mountContext;
21
20
  }
22
21
  }
23
22
  export class DismountEvent extends Event {
24
23
  mountedElement;
25
24
  reason;
26
- mountInit;
25
+ MountConfig;
27
26
  static eventName = dismountEventName;
28
- constructor(mountedElement, reason, mountInit) {
27
+ constructor(mountedElement, reason, MountConfig) {
29
28
  super(DismountEvent.eventName);
30
29
  this.mountedElement = mountedElement;
31
30
  this.reason = reason;
32
- this.mountInit = mountInit;
31
+ this.MountConfig = MountConfig;
33
32
  }
34
33
  }
35
34
  export class DisconnectEvent extends Event {
36
35
  mountedElement;
37
- mountInit;
36
+ MountConfig;
38
37
  static eventName = disconnectEventName;
39
- constructor(mountedElement, mountInit) {
38
+ constructor(mountedElement, MountConfig) {
40
39
  super(DisconnectEvent.eventName);
41
40
  this.mountedElement = mountedElement;
42
- this.mountInit = mountInit;
41
+ this.MountConfig = MountConfig;
43
42
  }
44
43
  }
45
44
  export class LoadEvent extends Event {
46
45
  modules;
47
- mountInit;
46
+ MountConfig;
48
47
  static eventName = loadEventName;
49
- constructor(modules, mountInit) {
48
+ constructor(modules, MountConfig) {
50
49
  super(LoadEvent.eventName);
51
50
  this.modules = modules;
52
- this.mountInit = mountInit;
53
- }
54
- }
55
- export class AttrChangeEvent extends Event {
56
- changes;
57
- mountInit;
58
- static eventName = attrchangeEventName;
59
- constructor(changes, mountInit) {
60
- super(AttrChangeEvent.eventName);
61
- this.changes = changes;
62
- this.mountInit = mountInit;
51
+ this.MountConfig = MountConfig;
63
52
  }
64
53
  }
65
54
  export class MediaMatchEvent extends Event {
66
- mountInit;
55
+ MountConfig;
67
56
  static eventName = mediamatchEventName;
68
- constructor(mountInit) {
57
+ constructor(MountConfig) {
69
58
  super(MediaMatchEvent.eventName);
70
- this.mountInit = mountInit;
59
+ this.MountConfig = MountConfig;
71
60
  }
72
61
  }
73
62
  export class MediaUnmatchEvent extends Event {
74
- mountInit;
63
+ MountConfig;
75
64
  static eventName = mediaunmatchEventName;
76
- constructor(mountInit) {
65
+ constructor(MountConfig) {
77
66
  super(MediaUnmatchEvent.eventName);
78
- this.mountInit = mountInit;
67
+ this.MountConfig = MountConfig;
79
68
  }
80
69
  }
package/Events.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  // Event classes for MountObserver
2
- import type { IMountEvent, IDismountEvent, IAttrChangeEvent, AttrChange, MountInit, DismountReason, MountContext } from './types.js';
2
+ import type { IMountEvent, IDismountEvent, MountConfig, DismountReason, MountContext } from './types.js';
3
3
 
4
4
  // Event name constants
5
5
  export const loadEventName = 'load';
6
6
  export const mountEventName = 'mount';
7
7
  export const dismountEventName = 'dismount';
8
8
  export const disconnectEventName = 'disconnect';
9
- export const attrchangeEventName = 'attrchange';
10
9
  export const mediamatchEventName = 'mediamatch';
11
10
  export const mediaunmatchEventName = 'mediaunmatch';
12
11
 
@@ -16,7 +15,7 @@ export class MountEvent extends Event implements IMountEvent {
16
15
  constructor(
17
16
  public mountedElement: Element,
18
17
  public modules: any[],
19
- public mountInit: MountInit,
18
+ public MountConfig: MountConfig,
20
19
  public mountContext: MountContext
21
20
  ) {
22
21
  super(MountEvent.eventName);
@@ -26,7 +25,7 @@ export class MountEvent extends Event implements IMountEvent {
26
25
  export class DismountEvent extends Event implements IDismountEvent {
27
26
  static eventName: typeof dismountEventName = dismountEventName;
28
27
 
29
- constructor(public mountedElement: Element, public reason: DismountReason, public mountInit: MountInit) {
28
+ constructor(public mountedElement: Element, public reason: DismountReason, public MountConfig: MountConfig) {
30
29
  super(DismountEvent.eventName);
31
30
  }
32
31
  }
@@ -34,7 +33,7 @@ export class DismountEvent extends Event implements IDismountEvent {
34
33
  export class DisconnectEvent extends Event {
35
34
  static eventName: typeof disconnectEventName = disconnectEventName;
36
35
 
37
- constructor(public mountedElement: Element, public mountInit: MountInit) {
36
+ constructor(public mountedElement: Element, public MountConfig: MountConfig) {
38
37
  super(DisconnectEvent.eventName);
39
38
  }
40
39
  }
@@ -42,23 +41,15 @@ export class DisconnectEvent extends Event {
42
41
  export class LoadEvent extends Event {
43
42
  static eventName: typeof loadEventName = loadEventName;
44
43
 
45
- constructor(public modules: any[], public mountInit: MountInit) {
44
+ constructor(public modules: any[], public MountConfig: MountConfig) {
46
45
  super(LoadEvent.eventName);
47
46
  }
48
47
  }
49
48
 
50
- export class AttrChangeEvent extends Event implements IAttrChangeEvent {
51
- static eventName: typeof attrchangeEventName = attrchangeEventName;
52
-
53
- constructor(public changes: AttrChange[], public mountInit: MountInit) {
54
- super(AttrChangeEvent.eventName);
55
- }
56
- }
57
-
58
49
  export class MediaMatchEvent extends Event {
59
50
  static eventName: typeof mediamatchEventName = mediamatchEventName;
60
51
 
61
- constructor(public mountInit: MountInit) {
52
+ constructor(public MountConfig: MountConfig) {
62
53
  super(MediaMatchEvent.eventName);
63
54
  }
64
55
  }
@@ -66,7 +57,7 @@ export class MediaMatchEvent extends Event {
66
57
  export class MediaUnmatchEvent extends Event {
67
58
  static eventName: typeof mediaunmatchEventName = mediaunmatchEventName;
68
59
 
69
- constructor(public mountInit: MountInit) {
60
+ constructor(public MountConfig: MountConfig) {
70
61
  super(MediaUnmatchEvent.eventName);
71
62
  }
72
63
  }
package/EvtRt.js CHANGED
@@ -1,34 +1,34 @@
1
1
  import { DismountEvent, MountEvent, DisconnectEvent, dismountEventName, disconnectEventName, mountEventName } from './Events.js';
2
2
  export class EvtRt {
3
3
  constructor(mountedElement, ctx) {
4
- const { observer, mountInit } = ctx;
4
+ const { observer, MountConfig } = ctx;
5
5
  const et = observer.getNotifier(mountedElement);
6
6
  et.addEventListener(mountEventName, this);
7
7
  et.addEventListener(disconnectEventName, this);
8
8
  et.addEventListener(dismountEventName, this);
9
- this.mount(mountedElement, mountInit, ctx);
9
+ this.mount(mountedElement, MountConfig, ctx);
10
10
  }
11
- mount(mountedElement, mountInit, context) {
12
- console.log({ mountedElement, mountInit, context });
11
+ mount(mountedElement, MountConfig, context) {
12
+ console.log({ mountedElement, MountConfig, context });
13
13
  }
14
- disconnect(mountedElement, mountInit) {
15
- console.log({ mountedElement, mountInit });
14
+ disconnect(mountedElement, MountConfig) {
15
+ console.log({ mountedElement, MountConfig });
16
16
  }
17
- dismount(mountedElement, mountInit) {
18
- console.log({ mountedElement, mountInit });
17
+ dismount(mountedElement, MountConfig) {
18
+ console.log({ mountedElement, MountConfig });
19
19
  }
20
20
  handleEvent(evt) {
21
21
  if (evt instanceof MountEvent) {
22
- const { mountedElement, mountContext, mountInit } = evt;
23
- this.mount(mountedElement, mountInit, mountContext);
22
+ const { mountedElement, mountContext, MountConfig } = evt;
23
+ this.mount(mountedElement, MountConfig, mountContext);
24
24
  }
25
25
  else if (evt instanceof DismountEvent) {
26
- const { mountedElement, mountInit } = evt;
27
- this.dismount(mountedElement, mountInit);
26
+ const { mountedElement, MountConfig } = evt;
27
+ this.dismount(mountedElement, MountConfig);
28
28
  }
29
29
  else if (evt instanceof DisconnectEvent) {
30
- const { mountedElement, mountInit } = evt;
31
- this.disconnect(mountedElement, mountInit);
30
+ const { mountedElement, MountConfig } = evt;
31
+ this.disconnect(mountedElement, MountConfig);
32
32
  }
33
33
  }
34
34
  }
package/EvtRt.ts CHANGED
@@ -1,4 +1,4 @@
1
- import {MountContext, MountInit} from './types.js';
1
+ import {MountContext, MountConfig} from './types.js';
2
2
 
3
3
  import {
4
4
  DismountEvent, MountEvent, DisconnectEvent,
@@ -6,37 +6,37 @@ import {
6
6
  } from './Events.js';
7
7
  export class EvtRt implements EventListenerObject{
8
8
  constructor(mountedElement: Element, ctx: MountContext ){
9
- const {observer, mountInit} = ctx;
9
+ const {observer, MountConfig} = ctx;
10
10
  const et = observer.getNotifier(mountedElement);
11
11
  et.addEventListener(mountEventName, this);
12
12
  et.addEventListener(disconnectEventName, this);
13
13
  et.addEventListener(dismountEventName, this);
14
- this.mount(mountedElement, mountInit, ctx);
14
+ this.mount(mountedElement, MountConfig, ctx);
15
15
 
16
16
  }
17
17
 
18
- mount(mountedElement: Element, mountInit: MountInit, context: MountContext){
19
- console.log({mountedElement, mountInit, context});
18
+ mount(mountedElement: Element, MountConfig: MountConfig, context: MountContext){
19
+ console.log({mountedElement, MountConfig, context});
20
20
  }
21
21
 
22
- disconnect(mountedElement: Element, mountInit: MountInit){
23
- console.log({mountedElement, mountInit});
22
+ disconnect(mountedElement: Element, MountConfig: MountConfig){
23
+ console.log({mountedElement, MountConfig});
24
24
  }
25
25
 
26
- dismount(mountedElement: Element, mountInit: MountInit){
27
- console.log({mountedElement, mountInit});
26
+ dismount(mountedElement: Element, MountConfig: MountConfig){
27
+ console.log({mountedElement, MountConfig});
28
28
  }
29
29
 
30
30
  handleEvent(evt: Event): void {
31
31
  if(evt instanceof MountEvent){
32
- const {mountedElement, mountContext, mountInit} = evt;
33
- this.mount(mountedElement, mountInit, mountContext);
32
+ const {mountedElement, mountContext, MountConfig} = evt;
33
+ this.mount(mountedElement, MountConfig, mountContext);
34
34
  }else if(evt instanceof DismountEvent){
35
- const {mountedElement, mountInit} = evt;
36
- this.dismount(mountedElement, mountInit);
35
+ const {mountedElement, MountConfig} = evt;
36
+ this.dismount(mountedElement, MountConfig);
37
37
  }else if(evt instanceof DisconnectEvent){
38
- const {mountedElement, mountInit} = evt;
39
- this.disconnect(mountedElement, mountInit);
38
+ const {mountedElement, MountConfig} = evt;
39
+ this.disconnect(mountedElement, MountConfig);
40
40
  }
41
41
  }
42
42
  }