@webtides/element-js 1.0.0-alpha.1 → 1.0.0-alpha.2
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/dist/index.js +25 -6
- package/dist/index.js.map +3 -3
- package/index.js +2 -1
- package/package.json +1 -1
- package/src/BaseElement.js +100 -23
- package/src/StyledElement.js +33 -3
- package/src/TemplateElement.js +24 -0
- package/src/dom-parts/TemplateResult.js +2 -1
- package/src/dom-parts/directives.js +40 -15
- package/src/util/AttributeParser.js +54 -21
- package/src/util/DOMHelper.js +43 -14
- package/src/util/Directive.js +13 -0
- package/src/util/Store.js +25 -4
- package/src/util/defineElement.js +2 -2
- package/src/util/i18n.js +3 -3
- package/src/util/toString.js +2 -2
package/src/util/DOMHelper.js
CHANGED
|
@@ -6,10 +6,12 @@ export const ATTRIBUTE_NODE = 2;
|
|
|
6
6
|
export const TEXT_NODE = 3;
|
|
7
7
|
/* A Comment node, such as <!-- … --> */
|
|
8
8
|
export const COMMENT_NODE = 8;
|
|
9
|
+
/* A Document Fragment, a document without a parent */
|
|
10
|
+
export const DOCUMENT_FRAGMENT_NODE = 11;
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
|
-
* Gets list of (childNode) indexes for the given node
|
|
12
|
-
* @param node
|
|
13
|
+
* Gets a list of (childNode) indexes for the given node
|
|
14
|
+
* @param {Node} node
|
|
13
15
|
* @return {number[]}
|
|
14
16
|
*/
|
|
15
17
|
export const getNodePath = (node) => {
|
|
@@ -23,6 +25,11 @@ export const getNodePath = (node) => {
|
|
|
23
25
|
return path;
|
|
24
26
|
};
|
|
25
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Get a list of all parent nodes up the DOM tree
|
|
30
|
+
* @param {Node} domNode
|
|
31
|
+
* @returns {Node[]}
|
|
32
|
+
*/
|
|
26
33
|
export function getAllParentNodes(domNode) {
|
|
27
34
|
let node = domNode.parentElement;
|
|
28
35
|
let parents = [];
|
|
@@ -34,7 +41,12 @@ export function getAllParentNodes(domNode) {
|
|
|
34
41
|
return parents;
|
|
35
42
|
}
|
|
36
43
|
|
|
37
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Gets the parent/root element of a shadow root or the global document body if not in shadow root.
|
|
46
|
+
* https://stackoverflow.com/questions/27453617/how-can-i-tell-if-an-element-is-in-a-shadow-dom
|
|
47
|
+
* @param {Node} element
|
|
48
|
+
* @returns {ShadowRoot | HTMLElement}
|
|
49
|
+
*/
|
|
38
50
|
export function getShadowParentOrBody(element) {
|
|
39
51
|
if (element instanceof ShadowRoot) {
|
|
40
52
|
return element;
|
|
@@ -50,6 +62,11 @@ export function getShadowParentOrBody(element) {
|
|
|
50
62
|
|
|
51
63
|
// TODO: add function for getClosestParentOfNodeType('custom-element')
|
|
52
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Get the closest/first parent node that is a custom element
|
|
67
|
+
* @param {Node} domNode
|
|
68
|
+
* @returns {Node}
|
|
69
|
+
*/
|
|
53
70
|
export function getClosestParentCustomElementNode(domNode) {
|
|
54
71
|
const customElementParents = getAllParentNodes(domNode).filter((node) => {
|
|
55
72
|
return node.localName && node.localName.indexOf('-') !== -1;
|
|
@@ -58,19 +75,31 @@ export function getClosestParentCustomElementNode(domNode) {
|
|
|
58
75
|
return customElementParents.pop();
|
|
59
76
|
}
|
|
60
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Checks whether two nodes are of the same node type
|
|
80
|
+
* @param {Node} nodeA
|
|
81
|
+
* @param {Node} nodeB
|
|
82
|
+
* @returns {boolean}
|
|
83
|
+
*/
|
|
61
84
|
export function isOfSameNodeType(nodeA, nodeB) {
|
|
62
85
|
if (!nodeA && !nodeA.localName) return false;
|
|
63
86
|
if (!nodeB && !nodeB.localName) return false;
|
|
64
87
|
return nodeA.localName === nodeB.localName;
|
|
65
88
|
}
|
|
66
89
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
export const
|
|
90
|
+
/**
|
|
91
|
+
* Checks if adopting style sheets is supported in browser
|
|
92
|
+
* @returns {boolean}
|
|
93
|
+
*/
|
|
94
|
+
export const supportsAdoptingStyleSheets = () => {
|
|
95
|
+
return 'adoptedStyleSheets' in Document.prototype && 'replace' in CSSStyleSheet.prototype;
|
|
96
|
+
};
|
|
72
97
|
|
|
73
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Better implementation of hasChildNodes check because the native check will also count for empty whitespace as child nodes... :(
|
|
100
|
+
* @param {Node} node
|
|
101
|
+
* @returns {boolean}
|
|
102
|
+
*/
|
|
74
103
|
export const hasChildNodes = (node) => {
|
|
75
104
|
const childNodesLength = node.childNodes.length;
|
|
76
105
|
|
|
@@ -86,7 +115,7 @@ export const hasChildNodes = (node) => {
|
|
|
86
115
|
};
|
|
87
116
|
|
|
88
117
|
/**
|
|
89
|
-
* Parses the given template
|
|
118
|
+
* Parses the given string as HTML template and returns a real DOM element
|
|
90
119
|
* @param {string} template
|
|
91
120
|
* @returns {HTMLElement}
|
|
92
121
|
*/
|
|
@@ -97,8 +126,8 @@ export const convertStringToHTML = (template) => {
|
|
|
97
126
|
};
|
|
98
127
|
|
|
99
128
|
/**
|
|
100
|
-
* Parses the given string and returns a DocumentFragment
|
|
101
|
-
*
|
|
129
|
+
* Parses the given string and returns a DocumentFragment which contains the DOM subtree
|
|
130
|
+
* representing the <template> element's template contents.
|
|
102
131
|
* @param {string} string
|
|
103
132
|
* @return {DocumentFragment}
|
|
104
133
|
*/
|
|
@@ -111,8 +140,8 @@ export const convertStringToTemplate = (string) => {
|
|
|
111
140
|
|
|
112
141
|
/**
|
|
113
142
|
* Diff the attributes for a live DOM element against a template DOM element
|
|
114
|
-
* @param
|
|
115
|
-
* @param
|
|
143
|
+
* @param {Element} templateElement - The new template
|
|
144
|
+
* @param {Element} domElement - The existing DOM node
|
|
116
145
|
*/
|
|
117
146
|
export const diffAttributes = function (templateElement, domElement) {
|
|
118
147
|
// remove or update previous attributes
|
package/src/util/Directive.js
CHANGED
|
@@ -2,6 +2,9 @@ export class Directive {
|
|
|
2
2
|
/** @type {Element} */
|
|
3
3
|
node = undefined;
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @param {Node} node
|
|
7
|
+
*/
|
|
5
8
|
constructor(node) {
|
|
6
9
|
this.node = node;
|
|
7
10
|
}
|
|
@@ -10,6 +13,16 @@ export class Directive {
|
|
|
10
13
|
* @abstract
|
|
11
14
|
*/
|
|
12
15
|
update() {}
|
|
16
|
+
|
|
17
|
+
// TODO: this is somewhat custom... maybe we could set the initial values in the constructor and then simply override the default toString() method?!
|
|
18
|
+
/**
|
|
19
|
+
* Implement the stringify method and return a string for rendering the directive in SSR mode
|
|
20
|
+
* @param {...any} values
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
stringify(...values) {
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
13
26
|
}
|
|
14
27
|
|
|
15
28
|
/**
|
package/src/util/Store.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { isObjectLike, deepEquals } from './AttributeParser.js';
|
|
2
|
-
import { BaseElement } from '../BaseElement';
|
|
2
|
+
import { BaseElement } from '../BaseElement.js';
|
|
3
3
|
|
|
4
4
|
export class Store {
|
|
5
5
|
_observer = new Set();
|
|
6
6
|
_singlePropertyMode = false;
|
|
7
7
|
_state = {};
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @param {* | object} value
|
|
11
|
+
*/
|
|
9
12
|
constructor(value) {
|
|
10
13
|
// wrap primitives with a generic "value" field to generate getter and setter
|
|
11
14
|
this._singlePropertyMode = arguments.length > 0 && !isObjectLike(value);
|
|
@@ -33,6 +36,11 @@ export class Store {
|
|
|
33
36
|
});
|
|
34
37
|
}
|
|
35
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Properties to be defined and assigned on the store. Can be overridden in extended classes.
|
|
41
|
+
* Properties defined here will also trigger an update cycle when changed.
|
|
42
|
+
* @return {{}}
|
|
43
|
+
*/
|
|
36
44
|
properties() {
|
|
37
45
|
return {};
|
|
38
46
|
}
|
|
@@ -40,34 +48,47 @@ export class Store {
|
|
|
40
48
|
/**
|
|
41
49
|
* When a property as the key was changed in the store, the callback function defined as value
|
|
42
50
|
* will be called with `newValue` and `oldValue`
|
|
43
|
-
* eg. { property: (oldValue, newValue) => { console.log('property changed!, oldValue, newValue); } }
|
|
44
51
|
* @return {{}}
|
|
45
52
|
*/
|
|
46
53
|
watch() {
|
|
47
54
|
return {};
|
|
48
55
|
}
|
|
49
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Overrides `valueOf` to automatically return .value
|
|
59
|
+
* @returns {* | {}}
|
|
60
|
+
*/
|
|
50
61
|
valueOf() {
|
|
51
62
|
return this._singlePropertyMode ? this._state.value : this._state;
|
|
52
63
|
}
|
|
53
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Overrides `toString` to automatically return .value
|
|
67
|
+
* @returns {string}
|
|
68
|
+
*/
|
|
54
69
|
toString() {
|
|
55
70
|
return `${this._singlePropertyMode ? this._state.value : this._state}`;
|
|
56
71
|
}
|
|
57
72
|
|
|
58
73
|
/**
|
|
59
|
-
*
|
|
74
|
+
* Add an observer
|
|
75
|
+
* @param {BaseElement | Function} observer
|
|
60
76
|
*/
|
|
61
77
|
subscribe(observer) {
|
|
62
78
|
this._observer.add(observer);
|
|
63
79
|
}
|
|
80
|
+
|
|
64
81
|
/**
|
|
65
|
-
*
|
|
82
|
+
* Remove an observer
|
|
83
|
+
* @param {BaseElement | Function} observer
|
|
66
84
|
*/
|
|
67
85
|
unsubscribe(observer) {
|
|
68
86
|
this._observer.delete(observer);
|
|
69
87
|
}
|
|
70
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Request and batch an asynchronous update cycle
|
|
91
|
+
*/
|
|
71
92
|
requestUpdate() {
|
|
72
93
|
this._observer.forEach(async (observer) => {
|
|
73
94
|
if (observer instanceof BaseElement) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Wrapper for defining custom elements so that registering an element multiple times won't crash
|
|
3
|
-
* @param name for the tag
|
|
4
|
-
* @param constructor for the custom element
|
|
3
|
+
* @param {string} name - name for the element tag
|
|
4
|
+
* @param {CustomElementConstructor} constructor for the custom element
|
|
5
5
|
*/
|
|
6
6
|
export function defineElement(name, constructor) {
|
|
7
7
|
try {
|
package/src/util/i18n.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Retrieves a translated key from a dictionary on the window object
|
|
3
3
|
* Example: ${i18n('CustomElement.buttonLabel', 'Label')}
|
|
4
|
-
* @param key to be translated
|
|
5
|
-
* @param fallback to be used if key is not defined
|
|
6
|
-
* @return String of the translated key or fallback or original key
|
|
4
|
+
* @param {string} key - to be translated
|
|
5
|
+
* @param {string} fallback - to be used if key is not defined
|
|
6
|
+
* @return {string} - String of the translated key or fallback or original key
|
|
7
7
|
*/
|
|
8
8
|
export function i18n(key, fallback) {
|
|
9
9
|
try {
|
package/src/util/toString.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Little wrapper function for JSON.stringify() to easily convert objects and arrays to strings
|
|
3
3
|
* to be able to set them as attributes on custom elements
|
|
4
|
-
* @param value to be stringified
|
|
5
|
-
* @return
|
|
4
|
+
* @param {object | array} value - to be stringified
|
|
5
|
+
* @return {string}
|
|
6
6
|
*/
|
|
7
7
|
export function toString(value) {
|
|
8
8
|
try {
|