@webtides/element-js 1.2.6 → 1.2.11
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/docs/README.md +1 -1
- package/package.json +5 -2
- package/src/BaseElement.js +37 -6
- package/src/StyledElement.js +2 -2
- package/src/util/DOMHelper.js +16 -2
package/docs/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webtides/element-js",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.11",
|
|
4
4
|
"module": "index.js",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
"./src/util/*": "./src/util/*.js",
|
|
20
20
|
"./src/dom-parts/*": "./src/dom-parts/*.js"
|
|
21
21
|
},
|
|
22
|
-
"repository":
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/webtides/element-js.git"
|
|
25
|
+
},
|
|
23
26
|
"author": "@webtides",
|
|
24
27
|
"license": "MIT",
|
|
25
28
|
"keywords": [
|
package/src/BaseElement.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { parseAttribute, isNaN, dashToCamel, camelToDash, isObjectLike } from './util/AttributeParser.js';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getAllComposedElementChildren,
|
|
4
|
+
getAllElementChildren,
|
|
5
|
+
getClosestParentCustomElementNode,
|
|
6
|
+
isOfSameNodeType,
|
|
7
|
+
} from './util/DOMHelper.js';
|
|
3
8
|
import { Store } from './util/Store.js';
|
|
4
9
|
import { serializeState, deserializeState, hasSerializedState } from './util/SerializeStateHelper.js';
|
|
5
10
|
import { randomUUID } from './util/crypto.js';
|
|
@@ -126,11 +131,15 @@ class BaseElement extends HTMLElement {
|
|
|
126
131
|
|
|
127
132
|
this.triggerHook('connected');
|
|
128
133
|
this._internals.states.add('connected');
|
|
134
|
+
// verification must happen after connection
|
|
135
|
+
this.verifyProvidedProperties();
|
|
129
136
|
} else {
|
|
130
137
|
this.requestUpdate({ notify: false }).then(() => {
|
|
131
138
|
this.triggerHook('connected');
|
|
132
139
|
this._internals.states.add('connected');
|
|
133
140
|
this.triggerHook('afterUpdate');
|
|
141
|
+
// verification must happen after connection
|
|
142
|
+
this.verifyProvidedProperties();
|
|
134
143
|
});
|
|
135
144
|
}
|
|
136
145
|
}
|
|
@@ -289,13 +298,14 @@ class BaseElement extends HTMLElement {
|
|
|
289
298
|
* Will trigger update() when a property was changed
|
|
290
299
|
*/
|
|
291
300
|
defineProperties() {
|
|
292
|
-
|
|
301
|
+
const properties = this.properties();
|
|
302
|
+
Object.keys({ ...this.injectProperties(), ...properties }).forEach((prop) => {
|
|
293
303
|
// when mixing shadow dom elements with light dom elements and nesting custom elements
|
|
294
304
|
// it might occur that properties where set on an element before it was
|
|
295
305
|
// registered or connected. To avoid such timing issues we check
|
|
296
306
|
// if a value was set for that specific property on the
|
|
297
307
|
// prototype before assigning a default value
|
|
298
|
-
const value = this[prop] ??
|
|
308
|
+
const value = this[prop] ?? properties[prop];
|
|
299
309
|
this.defineProperty(prop, value);
|
|
300
310
|
});
|
|
301
311
|
}
|
|
@@ -452,14 +462,35 @@ class BaseElement extends HTMLElement {
|
|
|
452
462
|
const providedKeys = Object.keys(this.provideProperties());
|
|
453
463
|
if (providedKeys.length > 0) {
|
|
454
464
|
this.addEventListener('request-context', this.onRequestContext);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Verifies provided context after the element has finished connecting.
|
|
470
|
+
*
|
|
471
|
+
* This is used as a failover step for late providers and lifecycle race conditions,
|
|
472
|
+
* especially when a provided value is assigned inside `connected()` and the initial
|
|
473
|
+
* context request was resolved before that mutation happened.
|
|
474
|
+
*
|
|
475
|
+
* By replaying matching requests here we ensure children receive the final provider
|
|
476
|
+
* value instead of being stuck with an early placeholder like `null`.
|
|
477
|
+
*/
|
|
478
|
+
|
|
479
|
+
verifyProvidedProperties() {
|
|
480
|
+
// define context provider
|
|
481
|
+
const providedProperties = this.provideProperties();
|
|
482
|
+
const providedKeys = Object.keys(providedProperties);
|
|
483
|
+
if (providedKeys.length > 0) {
|
|
484
|
+
// take both light and shadow dom into account.
|
|
485
|
+
const composedChildren = getAllComposedElementChildren(this, BaseElement);
|
|
455
486
|
// check if there are already connected elements in child dom and restart requests
|
|
456
|
-
|
|
487
|
+
composedChildren.forEach((customChild) => {
|
|
457
488
|
// if injectProperties?.() is defined it means that the child got connected BEFORE the parent (Runtime Issue)
|
|
458
489
|
const requestedProperties = customChild.injectProperties?.() ?? {};
|
|
459
490
|
Object.entries(requestedProperties).forEach(([key, value]) => {
|
|
460
491
|
// iterate over requested properties to find missed context requests
|
|
461
|
-
if (providedKeys.includes(key)) {
|
|
462
|
-
// owns the provided
|
|
492
|
+
if (providedKeys.includes(key) && customChild[key] !== providedProperties[key]) {
|
|
493
|
+
// owns the provided key -> replay request
|
|
463
494
|
customChild.requestContext(key, value);
|
|
464
495
|
}
|
|
465
496
|
});
|
package/src/StyledElement.js
CHANGED
|
@@ -90,7 +90,7 @@ class StyledElement extends BaseElement {
|
|
|
90
90
|
|
|
91
91
|
this.getRoot().adoptedStyleSheets = [
|
|
92
92
|
...(adoptGlobalStyleSheets ? globalStylesStore.getGlobalStyleSheets(this._options.adoptGlobalStyles) : []),
|
|
93
|
-
...this.constructor['elementStyleSheets'],
|
|
93
|
+
...(this.constructor?.['elementStyleSheets'] ?? []),
|
|
94
94
|
];
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -107,7 +107,7 @@ class StyledElement extends BaseElement {
|
|
|
107
107
|
|
|
108
108
|
const appendableStyles = [
|
|
109
109
|
...(adoptGlobalStyleSheets ? globalStylesStore.getGlobalStyleSheets(this._options.adoptGlobalStyles) : []),
|
|
110
|
-
...this.constructor['elementStyleSheets'],
|
|
110
|
+
...(this.constructor?.['elementStyleSheets'] ?? []),
|
|
111
111
|
];
|
|
112
112
|
|
|
113
113
|
appendableStyles.forEach((styleSheet, index) => {
|
package/src/util/DOMHelper.js
CHANGED
|
@@ -60,7 +60,7 @@ export function getShadowParentOrBody(element) {
|
|
|
60
60
|
return document.body;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// TODO: add function for
|
|
63
|
+
// TODO: add function for getClosestParentOfNo deType('custom-element')
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Get the closest/first parent node that is a custom element
|
|
@@ -76,7 +76,7 @@ export function getClosestParentCustomElementNode(domNode) {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
|
-
* Get all
|
|
79
|
+
* Get all custom element children of a DOM node
|
|
80
80
|
* @param {Node} domNode
|
|
81
81
|
* @param {{prototype: HTMLElement, new()}} instanceOfFilter
|
|
82
82
|
* @return {Node[]}
|
|
@@ -95,6 +95,20 @@ export function getAllElementChildren(domNode, instanceOfFilter = HTMLElement) {
|
|
|
95
95
|
return customElements;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Get all custom element children of a DOM node, including children inside the node's shadow root.
|
|
100
|
+
*
|
|
101
|
+
* @param {Node} domNode - The root node to start the traversal from.
|
|
102
|
+
* @param {{prototype: HTMLElement, new(): HTMLElement}} [instanceOfFilter=HTMLElement] - Constructor used to filter matching custom elements.
|
|
103
|
+
* @return {Set<HTMLElement>} A set of matching custom element descendants.
|
|
104
|
+
*/
|
|
105
|
+
export function getAllComposedElementChildren(domNode, instanceOfFilter = HTMLElement) {
|
|
106
|
+
return new Set([
|
|
107
|
+
...getAllElementChildren(domNode, instanceOfFilter),
|
|
108
|
+
...(domNode.shadowRoot ? getAllElementChildren(domNode.shadowRoot, instanceOfFilter) : []),
|
|
109
|
+
]);
|
|
110
|
+
}
|
|
111
|
+
|
|
98
112
|
/**
|
|
99
113
|
* Checks whether two nodes are of the same node type
|
|
100
114
|
* @param {Node} nodeA
|