mount-observer 0.0.6 → 0.0.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/MountObserver.js CHANGED
@@ -12,10 +12,10 @@ export class MountObserver extends EventTarget {
12
12
  #isComplex;
13
13
  constructor(init) {
14
14
  super();
15
- const { match, whereElementIntersectsWith, whereMediaMatches } = init;
15
+ const { on, whereElementIntersectsWith, whereMediaMatches } = init;
16
16
  let isComplex = false;
17
- if (match !== undefined) {
18
- const reducedMatch = match.replaceAll(':not(', '');
17
+ if (on !== undefined) {
18
+ const reducedMatch = on.replaceAll(':not(', '');
19
19
  isComplex = reducedMatch.includes(' ') || reducedMatch.includes(':');
20
20
  }
21
21
  this.#isComplex = isComplex;
@@ -31,17 +31,21 @@ export class MountObserver extends EventTarget {
31
31
  get #selector() {
32
32
  if (this.#calculatedSelector !== undefined)
33
33
  return this.#calculatedSelector;
34
- const { match, attribMatches } = this.#mountInit;
35
- const base = match || '*';
36
- if (attribMatches === undefined)
34
+ const { on, whereAttr } = this.#mountInit;
35
+ const base = on || '*';
36
+ if (whereAttr === undefined)
37
37
  return base;
38
+ const { withFirstName, andQualifiers, withStemsIn } = whereAttr;
38
39
  const matches = [];
39
- attribMatches.forEach(x => {
40
- const { names } = x;
41
- names.forEach(y => {
42
- matches.push(`${base}[${y}]`);
43
- });
44
- });
40
+ const prefixLessMatches = andQualifiers === undefined ? [withFirstName]
41
+ : andQualifiers.map(x => `${withFirstName}-${x}`);
42
+ const stems = withStemsIn || ['data', 'enh', 'data-enh'];
43
+ for (const stem of stems) {
44
+ const prefix = typeof stem === 'string' ? stem : stem.stem;
45
+ for (const prefixLessMatch of prefixLessMatches) {
46
+ matches.push(`${prefix}-${prefixLessMatch}`);
47
+ }
48
+ }
45
49
  this.#calculatedSelector = matches.join(',');
46
50
  return this.#calculatedSelector;
47
51
  }
@@ -96,7 +100,7 @@ export class MountObserver extends EventTarget {
96
100
  const { mutationRecords } = e;
97
101
  const elsToInspect = [];
98
102
  //const elsToDisconnect: Array<Element> = [];
99
- const doDisconnect = this.#mountInit.do?.onDisconnect;
103
+ const doDisconnect = this.#mountInit.do?.disconnect;
100
104
  for (const mutationRecord of mutationRecords) {
101
105
  const { addedNodes, type, removedNodes } = mutationRecord;
102
106
  //console.log(mutationRecord);
@@ -140,7 +144,7 @@ export class MountObserver extends EventTarget {
140
144
  // this.#mountedList = this.#mountedList?.filter(x => x.deref() !== deletedElement);
141
145
  this.#disconnected.add(deletedElement);
142
146
  if (doDisconnect !== undefined) {
143
- doDisconnect(deletedElement, this);
147
+ doDisconnect(deletedElement, this, {});
144
148
  }
145
149
  this.dispatchEvent(new DisconnectEvent(deletedElement));
146
150
  }
@@ -161,7 +165,7 @@ export class MountObserver extends EventTarget {
161
165
  async #mount(matching, initializing) {
162
166
  //first unmount non matching
163
167
  const alreadyMounted = this.#filterAndDismount();
164
- const onMount = this.#mountInit.do?.onMount;
168
+ const mount = this.#mountInit.do?.mount;
165
169
  const { import: imp, attribMatches } = this.#mountInit;
166
170
  for (const match of matching) {
167
171
  if (alreadyMounted.has(match))
@@ -186,8 +190,8 @@ export class MountObserver extends EventTarget {
186
190
  break;
187
191
  }
188
192
  }
189
- if (onMount !== undefined) {
190
- onMount(match, this, {
193
+ if (mount !== undefined) {
194
+ mount(match, this, {
191
195
  stage: 'PostImport',
192
196
  initializing
193
197
  });
@@ -220,7 +224,7 @@ export class MountObserver extends EventTarget {
220
224
  }
221
225
  }
222
226
  async #dismount(unmatching) {
223
- const onDismount = this.#mountInit.do?.onDismount;
227
+ const onDismount = this.#mountInit.do?.dismount;
224
228
  for (const unmatch of unmatching) {
225
229
  if (onDismount !== undefined) {
226
230
  onDismount(unmatch, this, {});
package/README.md CHANGED
@@ -10,13 +10,13 @@ Author: Bruce B. Anderson
10
10
 
11
11
  Issues / pr's / polyfill: [mount-observer](https://github.com/bahrus/mount-observer)
12
12
 
13
- Last Update: 2023-11-23
13
+ Last Update: 2024-2-11
14
14
 
15
15
  ## Benefits of this API
16
16
 
17
- What follows is a far more ambitious alternative to the [lazy custom element proposal](https://github.com/w3c/webcomponents/issues/782). The goals of the MountObserver api are more encompassing, and less focused on registering custom elements. In fact, this proposal addresses numerous use cases in one api. It is basically mapping common filtering conditions in the DOM, to common actions, like importing a resource, or progressively enhancing an element, or "binding from a distance".
17
+ What follows is a far more ambitious alternative to the [lazy custom element proposal](https://github.com/w3c/webcomponents/issues/782). The goals of the MountObserver api are more encompassing, and less focused on registering custom elements. In fact, this proposal addresses numerous use cases in one api. It is basically mapping common filtering conditions in the DOM, to mounting a "campaign" of some sort, like importing a resource, and/or progressively enhancing an element, and/or "binding from a distance".
18
18
 
19
- "Binding from a distance" refers to empowering the developer to essentially manage their own "stylesheets" -- but rather than for purposes of styling, using these rules to attach behaviors, set property values, etc.
19
+ ["Binding from a distance"](https://github.com/WICG/webcomponents/issues/1035#issuecomment-1806393525) refers to empowering the developer to essentially manage their own "stylesheets" -- but rather than for purposes of styling, using these rules to attach behaviors, set property values, etc, to the HTML as it streams in. Libraries that take this approach include [Corset](https://corset.dev/) and [trans-render](https://github.com/bahrus/trans-render). The concept has been promoted by a [number](https://bkardell.com/blog/CSSLike.html) [of](https://www.w3.org/TR/NOTE-AS) prominent voices in the community.
20
20
 
21
21
  The underlying theme is this api is meant to make it easy for the developer to do the right thing, by encouraging lazy loading and smaller footprints. It rolls up most all the other observer api's into one.
22
22
 
@@ -36,11 +36,10 @@ The amount of code necessary to accomplish these common tasks designed to improv
36
36
 
37
37
  1. Give the developer a strong signal to do the right thing, by
38
38
  1. Making lazy loading of resource dependencies easy, to the benefit of users with expensive networks.
39
- 2. Supporting "binding from a distance" that can allow SSR to provide common, shared data using the "DRY" philosophy, similar to how CSS can reduce the amount of repetitive styling instructions found inline within the HTML Markup.
40
- 3. Supporting "progressive enhancement."
41
- 2. Allow numerous components / libraries to leverage this common functionality, which could potentially significantly reduce bandwidth.
42
- 3. Potentially by allowing the platform to do more work in the low-level (c/c++/rust?) code, without as much context switching into the JavaScript memory space, which may reduce cpu cycles as well.
43
- 4. To do the job right, polyfills really need to reexamine **all** the elements within the observed node for matches **anytime any element within the Shadow Root so much as sneezes (has attribute modified, changes custom state, etc)**, due to modern selectors such as the :has selector. Surely, the platform has found ways to do this more efficiently?
39
+ 2. Supporting "binding from a distance" that can set property values of elements in bulk as the HTML streams in. For example, say a web page is streaming in HTML with thousands of input elements (say a long tax form). We want to have some indication in the head tag of the HTML (for example) to make all the input elements read only as they stream through the page. With css, we could do similar things, for example set the background to red of all input elements. Why can't we do something similar with setting properties like readOnly, disabled, etc? With this api, giving developers the "keys" to css filtering, so they can "mount a campaign" to apply common settings on them all feels like something that almost every web developer has mentally screamed to themselves "why can't I do that?", doesn't it?
40
+ 3. Supporting "progressive enhancement" more effectively.
41
+ 2. Potentially by allowing the platform to do more work in the low-level (c/c++/rust?) code, without as much context switching into the JavaScript memory space, which may reduce cpu cycles as well. This is done by passing into the API substantial number of conditions, which can all be evaluated at a lower level, before surfacing up the developer "found one!".
42
+ 3. As discussed earlier, to do the job right, polyfills really need to reexamine **all** the elements within the observed node for matches **anytime any element within the Shadow Root so much as sneezes (has attribute modified, changes custom state, etc)**, due to modern selectors such as the :has selector. Surely, the platform has found ways to do this more efficiently?
44
43
 
45
44
  The extra flexibility this new primitive would provide could be quite useful to things other than lazy loading of custom elements, such as implementing [custom enhancements](https://github.com/WICG/webcomponents/issues/1000) as well as [binding from a distance](https://github.com/WICG/webcomponents/issues/1035#issuecomment-1806393525) in userland.
46
45
 
@@ -50,12 +49,12 @@ To specify the equivalent of what the alternative proposal linked to above would
50
49
 
51
50
  ```JavaScript
52
51
  const observer = new MountObserver({
53
- match:'my-element',
52
+ on:'my-element',
54
53
  import: './my-element.js',
55
54
  do: {
56
- onMount: ({localName}, {module}) => {
55
+ mount: ({localName}, {module}) => {
57
56
  if(!customElements.get(localName)) {
58
- customElements.define(localName, module.default);
57
+ customElements.define(localName, module.MyElement);
59
58
  }
60
59
  }
61
60
  }
@@ -67,36 +66,41 @@ If no import is specified, it would go straight to do.* (if any such callbacks a
67
66
 
68
67
  This only searches for elements matching 'my-element' outside any shadow DOM.
69
68
 
70
- But the observe method can accept a shadowRoot, or a node inside a shadowRoot as well.
69
+ But the observe method can accept a node within the document, or a shadowRoot, or a node inside a shadowRoot as well.
71
70
 
72
71
  The import can also be a function:
73
72
 
74
73
  ```JavaScript
75
74
  const observer = new MountObserver({
76
- match: 'my-element',
75
+ on: 'my-element',
77
76
  import: async (matchingElement, {module}) => await import('./my-element.js');
78
77
  });
79
78
  observer.observe(myRootNode);
80
79
  ```
81
80
 
82
- which would work better with current bundlers, I suspect. Also, we can do interesting things like merge multiple imports into one "module". But should this API built into the platform, such functions wouldn't be necessary, as bundlers could start to recognize strings that are passed to the MountObserver's constructor.
81
+ which would work better with current bundlers, I suspect. Also, we can do interesting things like merge multiple imports into one "module". But should this API be built into the platform, such functions wouldn't be necessary, as bundlers could start to recognize strings that are passed to the MountObserver's constructor.
83
82
 
84
- This proposal would also include support for CSS, JSON, HTML module imports.
85
-
86
- "match" is a css query, and could include multiple matches using the comma separator, i.e. no limitation on CSS expressions.
83
+ This proposal would also include support for CSS, JSON, HTML module imports.
87
84
 
88
85
  The "observer" constant above is a class instance that inherits from EventTarget, which means it can be subscribed to by outside interests.
89
86
 
90
- <!-- As matches are found (for example, right away if matching elements are immediately found), the imports object would maintain a read-only array of weak references, along with the imported module:
87
+ ## Binding from a distance
88
+
89
+ It is important to note that "on" is a css query with no restrictions. So something like:
91
90
 
92
- ```TypeScript
93
- interface MountContext {
94
- weakReferences: readonly WeakRef<Element>[];
95
- module: any;
96
- }
91
+ ```JavaScript
92
+ const observer = new MountObserver({
93
+ on:'div > p + p ~ span[class$="name"]',
94
+ do:{
95
+ mount: (matchingElement) => {
96
+ //attach some behavior or set some property value or add an event listener, etc.
97
+ matchingElement.textContent = 'hello';
98
+ }
99
+ }
100
+ })
97
101
  ```
98
102
 
99
- This allows code that comes into being after the matching elements were found, to "get caught up" on all the matches. -->
103
+ This would allow developers to create "stylesheet" like capabilities.
100
104
 
101
105
 
102
106
  ## Extra lazy loading
@@ -107,7 +111,7 @@ However, we could make the loading even more lazy by specifying intersection opt
107
111
 
108
112
  ```JavaScript
109
113
  const observer = new MountObserver({
110
- match: 'my-element',
114
+ on: 'my-element',
111
115
  whereElementIntersectsWith:{
112
116
  rootMargin: "0px",
113
117
  threshold: 1.0,
@@ -122,27 +126,31 @@ Unlike traditional CSS @import, CSS Modules don't support specifying different i
122
126
 
123
127
  ```JavaScript
124
128
  const observer = new MountObserver({
125
- match: 'my-element',
129
+ on: 'div > p + p ~ span[class$="name"]',
126
130
  whereMediaMatches: '(max-width: 1250px)',
127
131
  whereSizeOfContainerMatches: '(min-width: 700px)',
128
132
  whereInstanceOf: [HTMLMarqueeElement],
129
133
  whereSatisfies: async (matchingElement, context) => true,
134
+ whereLangIn: ['en-GB'],
135
+ whereConnection:{
136
+ effectiveTypeIn: ["slow-2g"],
137
+ },
130
138
  import: ['./my-element-small.css', {type: 'css'}],
131
139
  do: {
132
- onMount: ({localName}, {module}) => {
140
+ mount: ({localName}, {module}) => {
133
141
  ...
134
142
  },
135
- onDismount: ...,
136
- onDisconnect: ...,
137
- onOutsideRootNode: ...,
138
- onReconnect: ...,
139
- onReconfirm: ...,
140
- onOutOfScope: ...,
143
+ dismount: ...,
144
+ disconnect: ...,
145
+ reconnect: ...,
146
+ reconfirm: ...,
147
+ exit: ...,
148
+ forget: ...,
141
149
  }
142
150
  })
143
151
  ```
144
152
 
145
- Callbacks like we see above are useful for tight coupling, and probably are unmatched in terms of performance. However, since these rules may be of interest to multiple parties, it is usesful to also provide the ability for multiple parties to subscribe to these css rules. This can be done via:
153
+ Callbacks like we see above are useful for tight coupling, and probably are unmatched in terms of performance. However, since these rules may be of interest to multiple parties, it is useful to also provide the ability for multiple parties to subscribe to these css rules. This can be done via:
146
154
 
147
155
  ## Subscribing
148
156
 
@@ -155,21 +163,22 @@ observer.addEventListener('mount', e => {
155
163
  module: e.module
156
164
  });
157
165
  });
158
-
159
166
  observer.addEventListener('dismount', e => {
160
167
  ...
161
168
  });
162
-
163
- observer.addEventListener('reconnect', e => {
169
+ observer.addEventListener('disconnect', e => {
164
170
  ...
165
171
  });
166
- observer.addEventListener('disconnect', e => {
172
+ observer.addEventListener('reconnect', e => {
167
173
  ...
168
174
  });
169
175
  observer.addEventListener('reconfirm', e => {
170
176
  ...
171
177
  });
172
- observer.addEventListener('out-of-scope', e => {
178
+ observer.addEventListener('exit', e => {
179
+ ...
180
+ });
181
+ observer.addEventListener('forget', e => {
173
182
  ...
174
183
  });
175
184
  ```
@@ -184,35 +193,162 @@ If an element that is in "mounted" state according to a MountObserver instance i
184
193
 
185
194
  1) "disconnect" event is dispatched from the MountObserver instance the moment the mounted element is disconnected from the DOM fragment.
186
195
  2) If/when the element is added somewhere else in the DOM tree, the mountObserver instance will dispatch event "reconnect", regardless of where. [Note: can't polyfill this very easily]
187
- 3) If the mounted element is added outside the rootNode being observed, the mountObserver instance will dispatch event "outside-root-node", and the MountObserver instance will relinquish any further responsibility for this element. Ideally this would also be dispatched when the platform garbage collects the element as well after all hard references are relinquished.
188
- 4) If the new place it was added remains within the original rootNode and remains mounted, the MountObserver instance dispatches event "reconfirmed".
189
- 5) If the element no longer satisfies the criteria of the MountObserver instance, the MountObserver instance will dispatch event "dismount".
196
+ 3) If the mounted element is added outside the rootNode being observed, the mountObserver instance will dispatch event "exit", and the MountObserver instance will relinquish any further responsibility for this element.
197
+ 4) Ideally event "forget" would be dispatched just before the platform garbage collects an element the MountObserver instance is still monitoring, after all hard references are relinquished (or is that self-contradictory?).
198
+ 5) If the new place it was added remains within the original rootNode and remains mounted, the MountObserver instance dispatches event "reconfirmed".
199
+ 6) If the element no longer satisfies the criteria of the MountObserver instance, the MountObserver instance will dispatch event "dismount".
200
+
201
+ ## A tribute to attributes
202
+
203
+ Extra support is provided for monitoring attributes. There are two primary reasons for needing to provide special support for attributes with this API:
190
204
 
191
- ## Special support for observable attributes
205
+ Being that for both custom elements, as well as (hopefully) [custom enhancements](https://github.com/WICG/webcomponents/issues/1000) we need to carefully work with sets of "owned" [observed](https://github.com/WICG/webcomponents/issues/1045) attributes, and in some cases we may need to manage combinations of prefixes and suffixes for better name-spacing management, creating the most effective css query becomes challenging.
192
206
 
193
- Extra support is provided for monitoring attributes.
207
+ We want to be alerted by the discovery of elements adorned by these attributes, but then continue to be alerted to changes of their values, and we can't enumerate which values we are interested in, so we must subscribe to all values as they change.
208
+
209
+ ### Scenario 1 -- Custom Element integration with ObserveObservableAttributes API [WIP]
194
210
 
195
211
  Example:
196
212
 
197
213
  ```html
198
214
  <div id=div>
199
- <span id=span></span>
215
+ <my-custom-element my-first-observed-attribute="hello"></my-custom-element>
200
216
  </div>
201
217
  <script type=module>
202
218
  import {MountObserver} from '../MountObserver.js';
203
219
  const mo = new MountObserver({
204
- match: '#span',
205
- attribMatches:[
220
+ on: '*',
221
+ whereInstanceOf: [MyCustomElement]
222
+ });
223
+ mo.addEventListener('parsed-attrs-changed', e => {
224
+ const {matchingElement, modifiedObjectFieldValues, preModifiedFieldValues} = e;
225
+ console.log({matchingElement, modifiedObjectFieldValues, preModifiedFieldValues});
226
+ });
227
+ mo.observe(div);
228
+ setTimeout(() => {
229
+ const myCustomElement = document.querySelector('my-custom-element');
230
+ myCustomElement.setAttribute('my-first-observed-attribute', 'good-bye');
231
+ }, 1000);
232
+ </script>
233
+ ```
234
+
235
+
236
+ ### Scenario 2 -- Custom Enhancements in userland
237
+
238
+ Based on [the proposal as it currently stands](https://github.com/WICG/webcomponents/issues/1000), in this case the class prototype would *not* have the attributes defined as a static property of the class, so that the constructor arguments in the previous scenario wouldn't be sufficient. So instead, what would seem to provide the most help for providing for custom enhancements in userland, and for any other kind of progressive enhancement based on attributes going forward.
239
+
240
+ Suppose we have a progressive enhancement that we want to apply based on the presence of 1 or more attributes.
241
+
242
+ To make this discussion concrete, let's suppose the "canonical" names of those attributes are:
243
+
244
+ ```html
245
+ <div id=div>
246
+ <section
247
+ my-enhancement=greetings
248
+ my-enhancement-first-aspect=hello
249
+ my-enhancement-second-aspect=goodbye
250
+ ></section>
251
+ </div>
252
+ ```
253
+
254
+ Now suppose we are worried about namespace clashes, plus we want to serve environments where HTML5 compliance is a must.
255
+
256
+ So we also want to recognize additional attributes that should map to these canonical attributes:
257
+
258
+ We want to also support:
259
+
260
+ ```html
261
+ <div id=div>
262
+ <section class=hello
263
+ data-my-enhancement=greetings
264
+ data-my-enhancement-first-aspect=hello
265
+ data-my-enhancement-second-aspect=goodbye
266
+ ></section>
267
+ </div>
268
+ ```
269
+
270
+ Based on the current unspoken rules, no one will raise an eyebrow with these attributes, because the platform has indicated it will generally avoid dashes in attributes (with an exception or two that will only happen in a blue moon, like aria-*).
271
+
272
+ But now when we consider applying this enhancement to custom elements, we have a new risk. What's to prevent the custom element from having an attribute named my-enhancement-first-aspect? (Okay, with this particular example, the names are so long and generic it's unlikely, but who would ever use such a long, generic name in practice?)
273
+
274
+ So let's say we want to insist that on custom elements, we must have the dat- prefix?
275
+
276
+ And we want to support an alternative prefix to data, say enh-*, endorsed by [this proposal](https://github.com/WICG/webcomponents/issues/1000).
277
+
278
+ Here's what the api provides:
279
+
280
+ ## Option 1 -- The carpal syndrome syntax
281
+
282
+ ```JavaScript
283
+ import {MountObserver} from '../MountObserver.js';
284
+ const mo = new MountObserver({
285
+ on: '*',
286
+ whereAttr:{
287
+ isIn: [
288
+ 'data-my-enhancement',
289
+ 'data-my-enhancement-first-aspect',
290
+ 'data-my-enhancement-second-aspect',
291
+ 'enh-my-enhancement',
292
+ 'enh-my-enhancement-first-aspect',
293
+ 'enh-my-enhancement-second-aspect',
206
294
  {
207
- names: ['test-1']
295
+ name: 'my-enhancement',
296
+ builtIn: true
297
+ },
298
+ {
299
+ name: 'my-enhancement-first-attr',
300
+ builtIn: true
301
+ },
302
+ {
303
+ name: 'my-enhancement-second-aspect',
304
+ builtIn: true
208
305
  }
209
306
  ]
307
+
308
+ }
309
+ });
310
+ ```
311
+
312
+ ## Option 2 -- The DRY Way
313
+
314
+ ```JavaScript
315
+ import {MountObserver} from '../MountObserver.js';
316
+ const mo = new MountObserver({
317
+ on: '*',
318
+ whereAttr:{
319
+ withFirstName: 'my-enhancement',
320
+ andQualifiers: ['first-attr', 'second-attr', ''],
321
+ withStemsIn: ['data', 'enh', 'data-enh'],
322
+ }
323
+ });
324
+ ```
325
+
326
+ MountObserver supports both approaches
327
+
328
+ ```html
329
+ <div id=div>
330
+ <section class=hello my-enhancement-first-attr="hello"></section>
331
+ </div>
332
+ <script type=module>
333
+ import {MountObserver} from '../MountObserver.js';
334
+ const mo = new MountObserver({
335
+ on: '*',
336
+ whereAttr:{
337
+ hasPrefixesIn: ['enh-', 'data-enh-'],
338
+ hasSuffixesIn:[
339
+ 'my-enhancement-first-attr',
340
+ 'my-enhancement-second-aspect'
341
+ ],
342
+
343
+ }
210
344
  });
211
- mo.addEventListener('attr-change', e => {
345
+ mo.addEventListener('observed-attr-change', e => {
212
346
  console.log(e);
213
347
  // {
348
+ // matchingElement,
214
349
  // attrChangeInfo:{
215
- // name: 'test-1',
350
+ // fullName: 'data-enh-my-first-enhancement-attr',
351
+ // suffix: 'my-first-enhancement-attr',
216
352
  // oldValue: null,
217
353
  // newValue: 'hello'
218
354
  // idx: 0,
@@ -221,13 +357,12 @@ Example:
221
357
  });
222
358
  mo.observe(div);
223
359
  setTimeout(() => {
224
- span.setAttribute('test-1', 'hello')
360
+ const myCustomElement = document.querySelector('my-custom-element');
361
+ myCustomElement.setAttribute('my-first-observed-attribute', 'good-bye');
225
362
  }, 1000);
226
363
  </script>
227
364
  ```
228
365
 
229
-
230
-
231
366
  ## Preemptive downloading
232
367
 
233
368
  There are two significant steps to imports, each of which imposes a cost:
@@ -243,11 +378,11 @@ So for this we add option:
243
378
 
244
379
  ```JavaScript
245
380
  const observer = new MountObserver({
246
- match: 'my-element',
381
+ on: 'my-element',
247
382
  loading: 'eager',
248
383
  import: './my-element.js',
249
384
  do:{
250
- onMount: (matchingElement, {module}) => customElements.define(module.MyElement)
385
+ mount: (matchingElement, {module}) => customElements.define(module.MyElement)
251
386
  }
252
387
  })
253
388
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mount-observer",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Observe and act on css matches.",
5
5
  "main": "MountObserver.js",
6
6
  "module": "MountObserver.js",
package/types.d.ts CHANGED
@@ -1,17 +1,25 @@
1
1
  export interface MountInit{
2
- readonly match?: CSSMatch,
3
- readonly attribMatches?: Array<AttribMatch>,
2
+ readonly on?: CSSMatch,
3
+ readonly attribMatches?: Array<AttribMatch>,
4
+ readonly whereAttr?: {
5
+ withFirstName: string,
6
+ andQualifiers?: Array<string>,
7
+ withStemsIn?: Array<string | {
8
+ stem: string,
9
+ context: 'BuiltIn' | 'CustomElement'
10
+ }>,
11
+ },
4
12
  readonly whereElementIntersectsWith?: IntersectionObserverInit,
5
13
  readonly whereMediaMatches?: MediaQuery,
6
14
  readonly whereInstanceOf?: Array<typeof Node>, //[TODO] What's the best way to type this?,
7
15
  readonly whereSatisfies?: PipelineProcessor<boolean>,
8
16
  readonly import?: ImportString | [ImportString, ImportAssertions] | PipelineProcessor,
9
17
  readonly do?: {
10
- readonly onMount?: PipelineProcessor,
11
- readonly onDismount?: PipelineProcessor,
12
- readonly onDisconnect?: PipelineProcessor,
13
- readonly onReconfirmed?: PipelineProcessor,
14
- readonly onOutsideRootNode?: PipelineProcessor,
18
+ readonly mount?: PipelineProcessor,
19
+ readonly dismount?: PipelineProcessor,
20
+ readonly disconnect?: PipelineProcessor,
21
+ readonly reconfirm?: PipelineProcessor,
22
+ readonly exit?: PipelineProcessor,
15
23
  }
16
24
  // /**
17
25
  // * Purpose -- there are scenarios where we may only want to affect changes that occur after the initial