@webtides/element-js 1.1.5 → 1.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webtides/element-js",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "module": "index.js",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -37,8 +37,8 @@
37
37
  "devDependencies": {
38
38
  "@babel/eslint-parser": "^7.23.3",
39
39
  "@open-wc/testing": "^4.0.0",
40
- "@web/dev-server": "^0.4.1",
41
- "@web/test-runner": "^0.14.1",
40
+ "@web/dev-server": "^0.4.6",
41
+ "@web/test-runner": "^0.19.0",
42
42
  "babel-eslint": "^10.1.0",
43
43
  "eslint": "8.55.0",
44
44
  "eslint-config-prettier": "^9.1.0",
@@ -4,28 +4,13 @@ import { TemplateResult } from './TemplateResult.js';
4
4
  import { TemplatePart } from './TemplatePart.js';
5
5
 
6
6
  /**
7
- * @param {Node | TemplatePart | any[]} node
8
- * @return {ChildNode}
7
+ * @param {Element} commentNode
8
+ * @param {Element[]} nodes
9
9
  */
10
- const removeChildNodes = (node) => {
11
- if (!Array.isArray(node) && !(node instanceof TemplatePart) && !node.hasChildNodes()) {
12
- return node;
10
+ const insertNodesBetweenComments = (commentNode, nodes) => {
11
+ for (const node of nodes) {
12
+ commentNode.parentNode.insertBefore(node, commentNode);
13
13
  }
14
- const range = globalThis.document?.createRange();
15
- const firstChild = Array.isArray(node)
16
- ? node[0]
17
- : node instanceof TemplatePart
18
- ? node.childNodes[0]
19
- : node.firstChild;
20
- const lastChild = Array.isArray(node)
21
- ? node[node.length - 1]
22
- : node instanceof TemplatePart
23
- ? node.childNodes[node.childNodes.length - 1]
24
- : node.lastChild;
25
- range.setStartAfter(firstChild);
26
- range.setEndAfter(lastChild);
27
- range.deleteContents();
28
- return firstChild;
29
14
  };
30
15
 
31
16
  /**
@@ -51,36 +36,39 @@ const removeNodesBetweenComments = (commentNode) => {
51
36
  * @return {Node[]}
52
37
  */
53
38
  const diffChildNodes = function (parentNode, domChildNodes, templateChildNodes, anchorNode) {
54
- // We always want to have the two arrays (domChildNodes and templateChildNodes) to have the same length.
39
+ // TODO: when diffing arrays there is sometimes two lists of TemplateParts instead of lists of childNodes
40
+ const offset = domChildNodes.includes(anchorNode) ? 1 : 0;
41
+
42
+ // release first level references to prevent cache mutation
43
+ const clonedDomChildNodes = [...domChildNodes];
44
+ const clonedTemplateChildNodes = [...templateChildNodes];
45
+
46
+ // We always want to have the two arrays (domChildNodes and cloneTemplateChildNodes) to have the same length.
55
47
  // We also don't ever want to replace/diff the last node of the domChildNodes as it will always be the
56
48
  // closing comment marker (/template-part) aka the anchorNode. So we push it to the end by inserting undefined items.
57
- if (templateChildNodes.length > domChildNodes.length) {
58
- const nodesToFill = templateChildNodes.length - domChildNodes.length;
49
+ if (clonedTemplateChildNodes.length > clonedDomChildNodes.length) {
50
+ const nodesToFill = clonedTemplateChildNodes.length - clonedDomChildNodes.length;
59
51
  for (let i = 0; i < nodesToFill; i++) {
60
- domChildNodes.splice(domChildNodes.length - 1, 0, undefined);
52
+ clonedDomChildNodes.splice(clonedDomChildNodes.length - offset, 0, undefined);
61
53
  }
62
54
  }
63
55
 
64
- if (domChildNodes.length > templateChildNodes.length) {
65
- const nodesToFill = domChildNodes.length - templateChildNodes.length;
56
+ if (clonedDomChildNodes.length > clonedTemplateChildNodes.length) {
57
+ const nodesToFill = clonedDomChildNodes.length - clonedTemplateChildNodes.length;
66
58
  for (let i = 0; i < nodesToFill; i++) {
67
- templateChildNodes.splice(templateChildNodes.length - 1, 0, undefined);
59
+ clonedTemplateChildNodes.splice(clonedTemplateChildNodes.length - offset, 0, undefined);
68
60
  }
69
61
  }
70
62
 
71
- const length = domChildNodes.length;
63
+ const length = clonedDomChildNodes.length;
72
64
  // Diff each node in the child node lists
73
65
  for (let index = 0; index < length; index++) {
74
- let domChildNode = domChildNodes[index];
75
- let templateChildNode = templateChildNodes[index];
66
+ let domChildNode = clonedDomChildNodes[index];
67
+ let templateChildNode = clonedTemplateChildNodes[index];
76
68
 
77
69
  // If the DOM node doesn't exist, append/copy the template node
78
- if (!domChildNode) {
79
- if (templateChildNode instanceof TemplatePart) {
80
- anchorNode.before(...templateChildNode.childNodes);
81
- } else if (Array.isArray(templateChildNode)) {
82
- anchorNode.before(...templateChildNode);
83
- } else if (typeof templateChildNode === 'object' && 'ELEMENT_NODE' in templateChildNode) {
70
+ if (domChildNode === undefined) {
71
+ if (typeof templateChildNode === 'object' && 'ELEMENT_NODE' in templateChildNode) {
84
72
  parentNode.insertBefore(templateChildNode, anchorNode);
85
73
  } else {
86
74
  // TODO: this might not be performant?! Can we maybe handle this in processDomNode?!
@@ -90,24 +78,46 @@ const diffChildNodes = function (parentNode, domChildNodes, templateChildNodes,
90
78
  continue;
91
79
  }
92
80
 
93
- // If the template node doesn't exist, remove the node in the DOM
94
- if (!templateChildNode) {
95
- parentNode.removeChild(removeChildNodes(domChildNode));
81
+ if (templateChildNode === undefined) {
82
+ // If the template node doesn't exist, remove the node in the DOM
83
+ if ('ELEMENT_NODE' in domChildNode) {
84
+ // remove dom node
85
+ parentNode.removeChild(domChildNode);
86
+ } else if (Array.isArray(domChildNode) || domChildNode instanceof TemplatePart) {
87
+ // remove childNodes
88
+ const childNodes = Array.isArray(domChildNode) ? domChildNode : domChildNode.childNodes;
89
+ for (const childNode of childNodes) {
90
+ childNode.remove();
91
+ }
92
+ } else {
93
+ console.log('This should not happen... what do we do about this node?!', { domChildNode });
94
+ }
96
95
  continue;
97
96
  }
98
97
 
99
- // If DOM node is equal to the template node, don't do anything
98
+ // If DOM node is equal to the template node, don't do anything in the DOM
100
99
  if (
101
100
  domChildNode === templateChildNode ||
102
- (domChildNode.nodeType === COMMENT_NODE &&
103
- templateChildNode.nodeType === COMMENT_NODE &&
104
- domChildNode.isEqualNode(templateChildNode))
101
+ (domChildNode.nodeType && templateChildNode.nodeType && domChildNode.isEqualNode(templateChildNode))
105
102
  ) {
103
+ // but we need to assign the current DOM node into the templateChildNodes
104
+ // as they will be returned here at the end and become the domNodes for the next diffing.
105
+ const childIndex = templateChildNodes.indexOf(templateChildNode);
106
+ templateChildNodes[childIndex] = domChildNode;
106
107
  continue;
107
108
  }
108
109
 
109
110
  // Everything else is somehow different and can be replaced
110
- parentNode.replaceChild(templateChildNode, domChildNode);
111
+ if (parentNode.contains(domChildNode)) {
112
+ parentNode.replaceChild(templateChildNode, domChildNode);
113
+ } else {
114
+ console.warn('This should not happen', {
115
+ parentNode,
116
+ 'parentNode.contains(domChildNode)': parentNode.contains(domChildNode),
117
+ templateChildNode,
118
+ domChildNode,
119
+ });
120
+ }
111
121
  }
112
122
  return templateChildNodes;
113
123
  };
@@ -118,8 +128,8 @@ const diffChildNodes = function (parentNode, domChildNodes, templateChildNodes,
118
128
  * @return {(function(*): void)|*}
119
129
  */
120
130
  export const processNodePart = (comment, initialValue) => {
121
- let nodes = initialValue instanceof TemplatePart ? [...initialValue.childNodes] : [];
122
- let oldValue = initialValue instanceof TemplatePart ? [...initialValue.childNodes] : initialValue;
131
+ let nodes = initialValue instanceof TemplatePart ? initialValue.childNodes : [];
132
+ let oldValue = initialValue instanceof TemplatePart ? initialValue.strings : initialValue;
123
133
  // this is for string values to be inserted into the DOM. A cached TextNode will be used so that we don't have to constantly create new DOM nodes.
124
134
  let cachedTextNode = undefined;
125
135
 
@@ -161,22 +171,34 @@ export const processNodePart = (comment, initialValue) => {
161
171
  removeNodesBetweenComments(comment);
162
172
  nodes = [];
163
173
  } else {
164
- nodes = diffChildNodes(comment.parentNode, oldValue || [], newValue, comment);
174
+ // TODO: this will always diff the arrays although they might not have changed...
175
+ const unwrapArray = (nodes) => {
176
+ // we have to unwrap any complex objects inside the array so that we can diff arrays of childNodes
177
+ return nodes.flatMap((value) => {
178
+ if (value instanceof TemplatePart) {
179
+ return value.childNodes;
180
+ }
181
+ if (Array.isArray(value)) {
182
+ return unwrapArray(value);
183
+ }
184
+ return value;
185
+ });
186
+ };
187
+ nodes = diffChildNodes(comment.parentNode, nodes, unwrapArray(newValue), comment);
165
188
  }
166
189
  oldValue = newValue;
167
190
  break;
168
191
  }
169
- // if the new value is a node or a fragment, and it's different from the live node, then it's diffed.
170
- if (oldValue !== newValue) {
171
- if ('ELEMENT_NODE' in newValue) {
172
- oldValue = newValue;
173
- nodes = diffChildNodes(comment.parentNode, nodes, [newValue], comment);
174
- } else if (newValue instanceof TemplatePart) {
175
- oldValue = [...newValue.childNodes];
176
- nodes = diffChildNodes(comment.parentNode, nodes, [...newValue.childNodes], comment);
177
- } else {
178
- console.warn('Could not process value', newValue);
179
- }
192
+
193
+ if (newValue instanceof TemplatePart && oldValue !== newValue.strings) {
194
+ // if the new value is a node or a fragment, and it's different from the live node, then it's diffed.
195
+ // static strings have changed in tpl part
196
+ oldValue = newValue.strings;
197
+ nodes = diffChildNodes(comment.parentNode, nodes, newValue.childNodes, comment);
198
+ } else if (oldValue !== newValue && 'ELEMENT_NODE' in newValue) {
199
+ // DOM Node changed, needs diffing
200
+ oldValue = newValue;
201
+ nodes = diffChildNodes(comment.parentNode, nodes, [newValue], comment);
180
202
  }
181
203
  break;
182
204
  case 'function':
@@ -192,12 +214,6 @@ export const processNodePart = (comment, initialValue) => {
192
214
  * For updating a text node, a sequence of child nodes or an array of `any` values
193
215
  */
194
216
  export class ChildNodePart extends Part {
195
- /** @type {Node | undefined} */
196
- startNode = undefined;
197
-
198
- /** @type {Node | undefined} */
199
- endNode = undefined;
200
-
201
217
  // TODO: this is only for array values
202
218
  /** @type {Part[]} */
203
219
  parts = [];
@@ -221,6 +237,7 @@ export class ChildNodePart extends Part {
221
237
 
222
238
  super();
223
239
 
240
+ let endNode = undefined;
224
241
  let serverSideRendered = false;
225
242
  if (startNode) {
226
243
  startNode.__part = this; // add Part to comment node for debugging in the browser
@@ -233,7 +250,7 @@ export class ChildNodePart extends Part {
233
250
  childNode = childNode.nextSibling;
234
251
  }
235
252
 
236
- const endNode = childNode;
253
+ endNode = childNode;
237
254
  childNodes.push(endNode);
238
255
 
239
256
  // if not SSRed, childNodes will only ever have two comment nodes, the start and the end marker
@@ -242,15 +259,13 @@ export class ChildNodePart extends Part {
242
259
  }
243
260
 
244
261
  this.childNodes = childNodes;
245
- this.startNode = startNode;
246
- this.endNode = endNode;
247
262
  }
248
263
 
249
264
  // value can become array | TemplatePart | any
250
265
  const initialValue = this.parseValue(value);
251
266
 
252
- if (this.endNode) {
253
- this.processor = processNodePart(this.endNode, serverSideRendered ? initialValue : undefined);
267
+ if (endNode) {
268
+ this.processor = processNodePart(endNode, serverSideRendered ? initialValue : undefined);
254
269
  }
255
270
 
256
271
  if (!serverSideRendered) {
@@ -258,9 +273,9 @@ export class ChildNodePart extends Part {
258
273
  this.updateParts(value);
259
274
  }
260
275
 
261
- // We need a childNodes list that is NOT live so that we don't lose elements when they get removed from the dom and we can (re)add them back in later.
262
- this.childNodes = [...this.childNodes];
263
- this.processor?.(initialValue);
276
+ if (!(value instanceof TemplateResult)) {
277
+ this.processor?.(initialValue);
278
+ }
264
279
  }
265
280
  }
266
281
 
@@ -275,7 +290,9 @@ export class ChildNodePart extends Part {
275
290
  this.updateParts(value);
276
291
  }
277
292
 
278
- this.processor?.(parsedValue);
293
+ if (!(value instanceof TemplateResult)) {
294
+ this.processor?.(parsedValue);
295
+ }
279
296
  }
280
297
 
281
298
  /**
@@ -299,11 +316,19 @@ export class ChildNodePart extends Part {
299
316
  parseValue(value) {
300
317
  if (value instanceof TemplateResult) {
301
318
  if (!this.templatePart) {
302
- const templatePartCommentNodes = this.childNodes?.filter(
303
- (node) => node && node.nodeType === COMMENT_NODE && node.data === 'template-part',
304
- );
305
- const startNode = templatePartCommentNodes[0];
319
+ const startNode = Array.from(this.childNodes)
320
+ .filter((node) => node.nodeType === COMMENT_NODE)
321
+ .find((node) => node.data === 'template-part');
306
322
  this.templatePart = new TemplatePart(startNode, value);
323
+ const serverSideRendered = startNode !== undefined;
324
+ if (!serverSideRendered) {
325
+ // TODO: we should already have the "endNode" from the constructor...
326
+ const endNode = Array.from(this.childNodes)
327
+ .filter((node) => node.nodeType === COMMENT_NODE)
328
+ .find((node) => node.data.includes('/dom-part-'));
329
+ // INFO: this is similar to TemplateResult#237
330
+ insertNodesBetweenComments(endNode, this.templatePart.childNodes);
331
+ }
307
332
  }
308
333
  return this.templatePart;
309
334
  }
@@ -324,6 +349,7 @@ export class ChildNodePart extends Part {
324
349
  let value = values[index];
325
350
 
326
351
  if (value instanceof TemplateResult) {
352
+ // TODO this is probably wrong. Should only be taken from parts cache if it has the same type (eg. template vs string, mixed types arrays)
327
353
  let templatePart = this.parts[index];
328
354
  if (!templatePart) {
329
355
  const templatePartCommentNodes = this.childNodes?.filter(
@@ -347,6 +373,7 @@ export class ChildNodePart extends Part {
347
373
  }
348
374
  parsedValues[index] = childNodePart;
349
375
  } else {
376
+ // TODO: what if the value from the function is a TemplatePart or an array?! Should we do this first thing?!
350
377
  parsedValues[index] = typeof value === 'function' ? value() : value;
351
378
  }
352
379
  }
@@ -33,6 +33,7 @@ export class TemplatePart extends Part {
33
33
 
34
34
  super();
35
35
 
36
+ let endNode = undefined;
36
37
  let serverSideRendered = false;
37
38
  if (startNode) {
38
39
  startNode.__part = this; // add Part to comment node for debugging in the browser
@@ -45,7 +46,7 @@ export class TemplatePart extends Part {
45
46
  childNode = childNode.nextSibling;
46
47
  }
47
48
 
48
- const endNode = childNode;
49
+ endNode = childNode;
49
50
  childNodes.push(endNode);
50
51
 
51
52
  // if not SSRed, childNodes will only ever have two comment nodes, the start and the end marker
@@ -54,23 +55,19 @@ export class TemplatePart extends Part {
54
55
  }
55
56
 
56
57
  this.childNodes = childNodes;
57
- this.startNode = startNode;
58
- this.endNode = endNode;
59
58
  }
60
59
 
61
60
  this.parseValue(value);
62
61
 
63
62
  if (!serverSideRendered) {
63
+ // TODO: this is causing double diffing because of the this.parseValue() before, ChildNode parts will be constructed + processed
64
64
  this.updateParts(value.values);
65
- // We need a childNodes list that is NOT live so that we don't loose elements when they get removed from the dom and we can (re)add them back in later.
66
- this.childNodes = [...this.childNodes];
67
65
  }
68
66
 
69
- this.startNode = this.childNodes[0];
70
- this.endNode = this.childNodes[this.childNodes.length - 1];
67
+ endNode = this.childNodes[this.childNodes.length - 1];
71
68
 
72
- if (this.endNode) {
73
- this.processor = processNodePart(this.endNode, this);
69
+ if (endNode) {
70
+ this.processor = processNodePart(endNode, this);
74
71
  }
75
72
  }
76
73
 
@@ -78,10 +75,11 @@ export class TemplatePart extends Part {
78
75
  * @param {TemplateResult} value
79
76
  */
80
77
  update(value) {
81
- this.parseValue(value);
78
+ const shouldUpdateDOM = this.parseValue(value);
79
+ if (shouldUpdateDOM) {
80
+ this.processor?.(this);
81
+ }
82
82
  this.updateParts(value.values);
83
- this.childNodes = [...this.childNodes];
84
- this.processor?.(this);
85
83
  }
86
84
 
87
85
  /**
@@ -95,6 +93,7 @@ export class TemplatePart extends Part {
95
93
 
96
94
  /**
97
95
  * @param {TemplateResult} templateResult
96
+ * @return {boolean} whether the part needs to be updated in the DOM
98
97
  */
99
98
  parseValue(templateResult) {
100
99
  if (this.strings !== templateResult.strings) {
@@ -134,8 +133,10 @@ export class TemplatePart extends Part {
134
133
  throw `cannot map part: ${part}`;
135
134
  });
136
135
  this.strings = templateResult.strings;
136
+ this.childNodes = [...this.childNodes];
137
+ return true;
137
138
  }
138
- return this.childNodes;
139
+ return false;
139
140
  }
140
141
 
141
142
  /**
@@ -217,14 +217,18 @@ export class TemplateResult {
217
217
  * @param {Element} domNode
218
218
  */
219
219
  renderInto(domNode) {
220
- let serverSideRendered = false;
220
+ const startNode = Array.from(domNode.childNodes)
221
+ .filter((node) => node.nodeType === COMMENT_NODE)
222
+ .find((node) => node.data === 'template-part');
223
+
224
+ let serverSideRendered = startNode !== undefined;
225
+
221
226
  let templatePart = templatePartsCache.get(domNode);
222
- if (!templatePart) {
223
- const startNode = Array.from(domNode.childNodes)
224
- .filter((node) => node.nodeType === COMMENT_NODE)
225
- .find((node) => node.data === 'template-part');
226
227
 
227
- serverSideRendered = startNode !== undefined;
228
+ if (!templatePart || !startNode) {
229
+ if (!startNode) {
230
+ domNode.replaceChildren();
231
+ }
228
232
 
229
233
  templatePart = new TemplatePart(startNode, this);
230
234
  templatePartsCache.set(domNode, templatePart);
package/CHANGELOG.md DELETED
@@ -1,402 +0,0 @@
1
- # Change Log
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres
6
- to [Semantic Versioning](http://semver.org/).
7
-
8
- <!--
9
- PRs should document their user-visible changes (if any) in the
10
- Unreleased section, uncommenting the header as necessary.
11
- -->
12
-
13
- <!-- ## Unreleased -->
14
- <!-- ### Added -->
15
- <!-- ### Changed -->
16
- <!-- ### Removed -->
17
- <!-- ### Fixed -->
18
-
19
- ## [1.1.5] - 2024-11-14
20
-
21
- ### FIXED
22
-
23
- - Fixed using special characters in attribute static strings ([#134](https://github.com/webtides/element-js/issues/134))
24
-
25
- ## [1.1.4] - 2024-11-12
26
-
27
- ### FIXED
28
-
29
- - Fixed rendering interpolations inside textarea nodes ([#133](https://github.com/webtides/element-js/issues/133))
30
-
31
- ## [1.1.3] - 2024-11-11
32
-
33
- ### FIXED
34
-
35
- - Fixed unsafeHtml having more than one child ([#135](https://github.com/webtides/element-js/issues/135))
36
- - Fixed early returns from templates and fixes static html changes not reflecting to DOM ([#132](https://github.com/webtides/element-js/issues/132))
37
-
38
-
39
- ## [1.1.2] - 2024-10-30
40
-
41
- ### FIXED
42
-
43
- - Fixed rerendering of templates that were initially null, prevent runtime errors
44
-
45
- ## [1.1.1] - 2024-09-16
46
-
47
- ### FIXED
48
-
49
- - Fixed base url and css rules order in adopted style sheets.
50
- - Fixed randomUUID not being available in unsecure hosts (like localhost) by adding a helper function
51
-
52
- ## [1.1.0] - 2024-06-24
53
-
54
- ### Added
55
-
56
- - Added `optionalAttribute` directive to conditionally render attributes (plus value)
57
-
58
- ### FIXED
59
-
60
- - Fixed `spreadAttributes` to not render "null|undefined|NaN" to the attributes value but removing the entire attribute
61
- when such values are passed.
62
-
63
- ## [1.0.0] - 2024-05-24
64
-
65
- ### Added
66
-
67
- - Added our own versions of directives and template helpers ([#67](https://github.com/webtides/element-js/pull/67))
68
- - Added JSDocs for everything in the codebase. This will especially be helpful when using constructor options.
69
- - Added state serialization. This improves hydration from SSR a
70
- lot. ([#106](https://github.com/webtides/element-js/pull/106))
71
- - added declarative shadow dom rendering for template elements
72
-
73
- ### Changed
74
-
75
- - _BREAKING_ Uses a new custom renderer for the `TemplateElement`. It replaces the old `lit-html` renderer. The API and
76
- usage should be exactly the same. The only thing to do/change is the use of the old `lit-html` directives. For
77
- detailed instructions see the upgrade guide. ([#67](https://github.com/webtides/element-js/pull/67))
78
- - _BREAKING_ `element-js` will now also trigger the `afterUpdate` hook right after the `connected` hook. This is to
79
- reduce the cases where you had to do the same things in `connected` and `afterUpdate`. You can now remove those
80
- duplicate calls from the `connected` hook. ([#60](https://github.com/webtides/element-js/pull/60))
81
- - _BREAKING_ Changed `package.json` type to `module`. This should hopefully not break anything. `element-js` is either
82
- used directly from the browser or through a bundler. In both cases the added type: module should not
83
- matter. ([#64](https://github.com/webtides/element-js/pull/64))
84
- - _BRAKING_ Changed the default options when using the `dispatch` helper function. `bubbles`, `cancelable`
85
- and `composed` will now be `true` by default.
86
- - _BRAKING_ Changed adopting global styles to include ALL global styles. Previously only one inline <style> with the ID
87
- of '#globalStyles' would be adopted. For more information see the docs.
88
-
89
- ### Removed
90
-
91
- - _BREAKING_ Removed the `lit-html` dependency. `element-js` is now officially dependency
92
- free! ([#67](https://github.com/webtides/element-js/pull/67))
93
- - _BREAKING_ Removed the deprecated `BaseElement` constructor option `childListUpdate`. Please use the "
94
- mutationObserverOptions" dictionary instead. See the docs for more
95
- info. ([#99](https://github.com/webtides/element-js/pull/99))
96
- - _BREAKING_ Removed the `hooks` map in the `BaseElement`. Using the hooks() map for lifecycle hooks is deprecated!
97
- Please overwrite the existing lifecycle hook functions. See the docs for more
98
- info. ([#99](https://github.com/webtides/element-js/pull/99))
99
- - _BREAKING_ Removed the `computed` map in the `BaseElement`. Using the computed() map for computed properties is
100
- deprecated! Please use regular JS getters and return the computed value. See the docs for more
101
- info. ([#99](https://github.com/webtides/element-js/pull/99))
102
- - _BREAKING_ Removed all occurrences of `ShadyCSS`
103
- in `StyledElement`. ([#99](https://github.com/webtides/element-js/pull/99))
104
- - _BRAKING_ Removed the `i18n` helper function. See CHANGELOG how to implement it yourself or use a third party library.
105
-
106
- ## [1.0.0-alpha.13] - 2024-05-08
107
-
108
- ### Fixed
109
-
110
- - catch security errors when `GlobalStylesStore` tries to read css rules from cross-origin stylesheets.
111
-
112
- ## [1.0.0-alpha.12] - 2024-03-03
113
-
114
- ### Added
115
-
116
- - added declarative shadow dom rendering for template elements
117
-
118
- ### Fixed
119
-
120
- - fixed issues with whitespace being returned untrimmed in a template result
121
-
122
- ## [1.0.0-alpha.11] - 2024-03-13
123
-
124
- ### Fixed
125
-
126
- - fixed missing return type `string` for the `template()` function in `TemplateElement`
127
- - fixed types for the `propertyOptions` option in `BaseElement`
128
-
129
- ## [1.0.0-alpha.10] - 2024-02-20
130
-
131
- ### Fixed
132
-
133
- - fixed unsafeHTML not rendering anything when toString was called
134
- - fixed using = sign in attribute positions with interpolations
135
- - fixed rendering null values in node part positions in SSR
136
- - fixed missing .js file extensions
137
-
138
- ## [1.0.0-alpha.9] - 2024-01-05
139
-
140
- ### Changed
141
-
142
- - moved DOM methods into connected callbacks to make it safe for the elements to be created in SSR environments
143
-
144
- ## [1.0.0-alpha.8] - 2024-01-04
145
-
146
- ### Fixed
147
-
148
- - fixed ChildNodePart not replacing dom nodes from unsafeHTML
149
-
150
- ## [1.0.0-alpha.7] - 2023-12-19
151
-
152
- ### Fixed
153
-
154
- - fixed wrong attribute parts for the same name on different elements
155
-
156
- ## [1.0.0-alpha.6] - 2023-12-18
157
-
158
- ### Fixed
159
-
160
- - fixed hyphens in attribute names being split in SSR mode
161
-
162
- ## [1.0.0-alpha.5] - 2023-12-07
163
-
164
- ### Added
165
-
166
- - Added the /docs directory to the files array in package.json
167
- - Added part instances as \_\_part to comment nodes
168
-
169
- ### Fixed
170
-
171
- - fixed escaped unsafeHTML in SSR mode
172
-
173
- ## [1.0.0-alpha.4] - 2023-12-01
174
-
175
- ### Fixed
176
-
177
- - falsy creation of directive parts for non-directive attributes
178
- - creating parts with wrong comment marker positions
179
-
180
- ## [1.0.0-alpha.3] - 2023-12-01
181
-
182
- ### Added
183
-
184
- - Added state serialization. This improves hydration from SSR a
185
- lot. ([#106](https://github.com/webtides/element-js/pull/106))
186
-
187
- ### Changed
188
-
189
- - _BRAKING_ Changed the default options when using the `dispatch` helper function. `bubbles`, `cancelable`
190
- and `composed` will now be `true` by default.
191
- - _BRAKING_ Changed adopting global styles to include ALL global styles. Previously only one inline <style> with the ID
192
- of '#globalStyles' would be adopted. For more information see the docs.
193
-
194
- ### Removed
195
-
196
- - _BRAKING_ Removed `i18n` helper function. See CHANGELOG how to implement it yourself or use a third party library.
197
-
198
- ## [1.0.0-alpha.2] - 2023-08-23
199
-
200
- ### Added
201
-
202
- - Added JSDocs for everything in the codebase. This will especially be helpful when using constructor options.
203
-
204
- ## [1.0.0-alpha.1] - 2023-08-15
205
-
206
- ### Added
207
-
208
- - Added our own versions of directives and template helpers ([#67](https://github.com/webtides/element-js/pull/67))
209
-
210
- ### Changed
211
-
212
- - _BRAKING_ Uses a new custom renderer for the `TemplateElement`. It replaces the old `lit-html` renderer. The API and
213
- usage should be exactly the same. The only thing to do/change is the use of the old `lit-html` directives. For
214
- detailed instructions see the upgrade guide. ([#67](https://github.com/webtides/element-js/pull/67))
215
- - _BREAKING_ `element-js` will now also trigger the `afterUpdate` hook right after the `connected` hook. This is to
216
- reduce the cases where you had to do the same things in `connected` and `afterUpdate`. You can now remove those
217
- duplicate calls from the `connected` hook. ([#60](https://github.com/webtides/element-js/pull/60))
218
- - _BREAKING_ Changed `package.json` type to `module`. This should hopefully not break anything. `element-js` is either
219
- used directly from the browser or through a bundler. In both cases the added type: module should not
220
- matter. ([#64](https://github.com/webtides/element-js/pull/64))
221
-
222
- ### Removed
223
-
224
- - _BREAKING_ Removed the `lit-html` dependency. `element-js` is now officially dependency
225
- free! ([#67](https://github.com/webtides/element-js/pull/67))
226
- - _BREAKING_ Removed the deprecated `BaseElement` constructor option `childListUpdate`. Please use the "
227
- mutationObserverOptions" dictionary instead. See the docs for more
228
- info. ([#99](https://github.com/webtides/element-js/pull/99))
229
- - _BREAKING_ Removed the `hooks` map in the `BaseElement`. Using the hooks() map for lifecycle hooks is deprecated!
230
- Please overwrite the existing lifecycle hook functions. See the docs for more
231
- info. ([#99](https://github.com/webtides/element-js/pull/99))
232
- - _BREAKING_ Removed the `computed` map in the `BaseElement`. Using the computed() map for computed properties is
233
- deprecated! Please use regular JS getters and return the computed value. See the docs for more
234
- info. ([#99](https://github.com/webtides/element-js/pull/99))
235
- - _BREAKING_ Removed all occurrences of `ShadyCSS`
236
- in `StyledElement`. ([#99](https://github.com/webtides/element-js/pull/99))
237
-
238
- ## [0.7.4] - 2023-11-24
239
-
240
- ### Added
241
-
242
- - storeception (reactive store properties in parent stores)
243
- - context injection in shadow elements requests travel though shadow roots
244
- - defer element connection (disables client side code until called manually)
245
-
246
- ### Fixed
247
-
248
- - late context injection if parent mounts after child (loading order)
249
- - stores updating elements that want to be updated
250
-
251
- ## [0.7.3] - 2023-03-07
252
-
253
- ### Fixed
254
-
255
- - last release was tagged wrong
256
-
257
- ## [0.7.2] - 2023-03-03
258
-
259
- ### Fixed
260
-
261
- - watcher callbacks for injected stores
262
-
263
- ## [0.7.1] - 2023-03-03
264
-
265
- ### Added
266
-
267
- - Elements are now able to watch Stores
268
-
269
- ### Fixed
270
-
271
- - Injection of falsy values
272
-
273
- ## [0.7.0] - 2023-02-13
274
-
275
- ### Added
276
-
277
- - Dependency Injection via Context Protocol 💉
278
- - Provide reactive Properties or entire Stores via: provideProperties() { return { name : value}}
279
- - Inject / Request them via injectProperties() { return { name : 'defaultValue'}}
280
-
281
- ### Changed
282
-
283
- - docs structure
284
-
285
- ### Fixed
286
-
287
- - Cannot re-render slotted light dom when using the vanilla renderer https://github.com/webtides/element-js/issues/76
288
- - adds Vanilla Renderer Tests
289
-
290
- ## [0.6.2] - 2022-11-18
291
-
292
- ### FIXED
293
-
294
- - Store always switching to singleProperty Mode if constructed without any arguments.
295
-
296
- ## [0.6.1] - 2022-11-18
297
-
298
- ### ADDED
299
-
300
- - Store watch() map to control internal store state scope
301
-
302
- ## [0.6.0] - 2022-11-17
303
-
304
- ### ADDED
305
-
306
- - StoreProperty for shared application state
307
- - Directives for Vanilla Renderer
308
-
309
- ## [0.5.0] - 2022-09-13
310
-
311
- ### Changed
312
-
313
- - improved the performance of the vanilla-renderer
314
-
315
- ### Removed
316
-
317
- - setting attributes as properties during dom diffing for the vanilla renderer. This is potentially a **breaking**
318
- change if you used attributes with the "." (dot) notation
319
-
320
- ## [0.4.3] - 2022-07-06
321
-
322
- ### ADDED
323
-
324
- - parse option to propertyOptions that can be either a boolean OR a function for custom parsing
325
- - enhance reflect option in propertyOptions that it can also be a function for custom reflection
326
-
327
- ## [0.4.2] - 2022-02-03
328
-
329
- ### Fixed
330
-
331
- - vanilla-renderer: fixes attribute comparsion
332
-
333
- ## [0.4.1] - 2022-02-01
334
-
335
- ### Fixed
336
-
337
- - refs="id[]" indexing keys not nodes _rolleyes_
338
-
339
- ### Added
340
-
341
- - refs="id[]" aka possibbility to refrence a list of nodes to the $refs map.
342
-
343
- ## [0.4.0] - 2022-01-28
344
-
345
- ### Added
346
-
347
- - a "vanilla" renderer with support for hydration and no dependencies
348
-
349
- ### Changed
350
-
351
- - uses new @web/test-runner isntead of karma (#27)
352
-
353
- ## [0.3.3] - 2021-09-22
354
-
355
- ### Added
356
-
357
- - optional complex event callback notation to support addEventListener options (i.E. for passive Event Listeners )
358
- - Example: {listener: () => {}, options: { passive: true } }
359
- - docs
360
- - tests
361
-
362
- ## [0.3.2] - 2021-03-09
363
-
364
- ### Added
365
-
366
- - bundled version of `element-js` to use from a CDN and be able to prototype in tools like CodePen etc.
367
-
368
- ## [0.3.1] - 2020-12-08
369
-
370
- ### Fixed
371
-
372
- - i18n fallback values
373
-
374
- ### Added
375
-
376
- - i18n tests
377
-
378
- ## [0.3.0] - 2020-07-27
379
-
380
- ### Added
381
-
382
- - first batch/draft of the documentation
383
- - property/attribute reflection via constructor options (see the [Documentation](/docs/README.md#propertyoptions) for
384
- more info)
385
- - mutationObserverOptions to enable observing subtree mutations (see
386
- the [Documentation](/docs/README.md#mutationobserveroptions) for more info)
387
-
388
- ### Removed
389
-
390
- - `childListUpdate` constructor option has been deprecated and will be removed before `1.0`
391
-
392
- ## [0.2.0] - 2020-07-01
393
-
394
- ### Changed
395
-
396
- - uses shady-render instead of render from `lit-html` for rendering templates to be compatible with the shady-css
397
- polyfill
398
- - refactored and simplified `StyledElement`s handling/loading of style sheets
399
-
400
- ## [0.1.0] - 2020-06-26
401
-
402
- - initial release