@vaadin/component-base 25.1.10 → 25.1.12

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": "@vaadin/component-base",
3
- "version": "25.1.10",
3
+ "version": "25.1.12",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -38,11 +38,11 @@
38
38
  "lit": "^3.0.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@vaadin/chai-plugins": "~25.1.10",
42
- "@vaadin/test-runner-commands": "~25.1.10",
41
+ "@vaadin/chai-plugins": "~25.1.12",
42
+ "@vaadin/test-runner-commands": "~25.1.12",
43
43
  "@vaadin/testing-helpers": "^2.0.0",
44
44
  "sinon": "^21.0.2"
45
45
  },
46
46
  "customElements": "custom-elements.json",
47
- "gitHead": "941297a1015ae11bb75d90c0b3c52302e741a528"
47
+ "gitHead": "a83f7aa5ab76b317eb25e99cf9c96a8c72341e95"
48
48
  }
package/src/define.js CHANGED
@@ -13,7 +13,7 @@ function dashToCamelCase(dash) {
13
13
 
14
14
  const experimentalMap = {};
15
15
 
16
- export function defineCustomElement(CustomElement, version = '25.1.10') {
16
+ export function defineCustomElement(CustomElement, version = '25.1.12') {
17
17
  Object.defineProperty(CustomElement, 'version', {
18
18
  get() {
19
19
  return version;
package/src/i18n-mixin.js CHANGED
@@ -3,34 +3,7 @@
3
3
  * Copyright (c) 2025 - 2026 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
-
7
- function deepMerge(target, ...sources) {
8
- const isArray = (item) => Array.isArray(item);
9
- const isObject = (item) => item && typeof item === 'object' && !isArray(item);
10
- const merge = (target, source) => {
11
- if (isObject(source) && isObject(target)) {
12
- Object.keys(source).forEach((key) => {
13
- const sourceValue = source[key];
14
- if (isObject(sourceValue)) {
15
- if (!target[key]) {
16
- target[key] = {};
17
- }
18
- merge(target[key], sourceValue);
19
- } else if (isArray(sourceValue)) {
20
- target[key] = [...sourceValue];
21
- } else if (sourceValue !== undefined && sourceValue !== null) {
22
- target[key] = sourceValue;
23
- }
24
- });
25
- }
26
- };
27
-
28
- sources.forEach((source) => {
29
- merge(target, source);
30
- });
31
-
32
- return target;
33
- }
6
+ import { deepMergePartials } from './object-utils.js';
34
7
 
35
8
  /**
36
9
  * A mixin that allows to set partial I18N properties.
@@ -58,7 +31,7 @@ export const I18nMixin = (defaultI18n, superClass) =>
58
31
  constructor() {
59
32
  super();
60
33
 
61
- this.i18n = deepMerge({}, defaultI18n);
34
+ this.i18n = deepMergePartials({}, defaultI18n);
62
35
  }
63
36
 
64
37
  /**
@@ -80,6 +53,6 @@ export const I18nMixin = (defaultI18n, superClass) =>
80
53
  return;
81
54
  }
82
55
  this.__customI18n = value;
83
- this.__effectiveI18n = deepMerge({}, defaultI18n, this.__customI18n);
56
+ this.__effectiveI18n = deepMergePartials({}, defaultI18n, this.__customI18n);
84
57
  }
85
58
  };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2026 - 2026 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ /**
8
+ * Recursively copies own properties of `source` into `target` and returns
9
+ * `target`. Plain objects are merged, other values are assigned as they are.
10
+ * An object is plain when it inherits from `Object.prototype` or from nothing,
11
+ * so values such as a `Date` or a class instance are assigned, not merged.
12
+ *
13
+ * Merges a single source. Use `deepMergePartials()` to merge several objects,
14
+ * or to merge objects that only provide some of the properties.
15
+ *
16
+ * Both arguments are expected to be plain objects. When either of them is not,
17
+ * `target` is returned without changes. A property of the target that is not a
18
+ * plain object is replaced with the merged object, unlike the arguments.
19
+ *
20
+ * Keys that would modify `Object.prototype`, such as `__proto__`, are ignored.
21
+ */
22
+ export function deepMerge<T extends object>(target: T, source: object): T;
23
+
24
+ /**
25
+ * Recursively merges partial objects into `target` in order and returns
26
+ * `target`, so that a later source overrides an earlier one.
27
+ *
28
+ * Values that are `null` or `undefined` are skipped, so a source that only
29
+ * provides some of the properties does not remove the others. For the same
30
+ * reason, a property that the target already has is not replaced with an
31
+ * object when the source has one for the same key. Arrays are copied one level
32
+ * deep, so that the result does not share an array with any of the sources.
33
+ *
34
+ * Sources that are not plain objects are ignored. When `target` is not a plain
35
+ * object, it is returned without changes.
36
+ *
37
+ * Keys that would modify `Object.prototype`, such as `__proto__`, are ignored.
38
+ */
39
+ export function deepMergePartials<T extends object>(target: T, ...sources: object[]): T;
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2026 - 2026 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ /**
8
+ * Keys that are not copied while merging, as assigning them would modify
9
+ * `Object.prototype` instead of the merge target, and so affect every
10
+ * object in the application.
11
+ */
12
+ const IGNORED_KEYS = ['__proto__', 'constructor', 'prototype'];
13
+
14
+ const isPlainObject = (value) => {
15
+ if (!value || typeof value !== 'object') {
16
+ return false;
17
+ }
18
+ const prototype = Object.getPrototypeOf(value);
19
+ return prototype === Object.prototype || prototype === null;
20
+ };
21
+
22
+ /**
23
+ * Merges `source` into `target`. With `partial`, the source is treated as an
24
+ * object that may provide only some of the properties: nullish values are
25
+ * skipped and arrays are copied instead of shared.
26
+ */
27
+ function merge(target, source, partial) {
28
+ if (!isPlainObject(target) || !isPlainObject(source)) {
29
+ return target;
30
+ }
31
+
32
+ Object.keys(source).forEach((key) => {
33
+ if (IGNORED_KEYS.includes(key)) {
34
+ return;
35
+ }
36
+
37
+ const value = source[key];
38
+
39
+ if (isPlainObject(value)) {
40
+ // Only merge into an own plain object, so that the merge can never
41
+ // continue into an object inherited from the prototype chain.
42
+ if (!Object.hasOwn(target, key) || !isPlainObject(target[key])) {
43
+ // With `partial`, a value that the target already has is kept, so that
44
+ // a source property of an unexpected type does not remove a default.
45
+ if (partial && Object.hasOwn(target, key) && target[key]) {
46
+ return;
47
+ }
48
+
49
+ target[key] = {};
50
+ }
51
+
52
+ merge(target[key], value, partial);
53
+ } else if (partial && Array.isArray(value)) {
54
+ target[key] = [...value];
55
+ } else if (!partial || (value !== undefined && value !== null)) {
56
+ target[key] = value;
57
+ }
58
+ });
59
+
60
+ return target;
61
+ }
62
+
63
+ /**
64
+ * Recursively copies own properties of `source` into `target` and returns
65
+ * `target`. Plain objects are merged, other values are assigned as they are.
66
+ * An object is plain when it inherits from `Object.prototype` or from nothing,
67
+ * so values such as a `Date` or a class instance are assigned, not merged.
68
+ *
69
+ * Merges a single source. Use `deepMergePartials()` to merge several objects,
70
+ * or to merge objects that only provide some of the properties.
71
+ *
72
+ * Both arguments are expected to be plain objects. When either of them is not,
73
+ * `target` is returned without changes. A property of the target that is not a
74
+ * plain object is replaced with the merged object, unlike the arguments.
75
+ *
76
+ * Keys that would modify `Object.prototype`, such as `__proto__`, are ignored.
77
+ *
78
+ * @param {object} target the object to merge into, modified in place
79
+ * @param {object} source the object to copy the properties from
80
+ * @return {object} the `target` object
81
+ */
82
+ export function deepMerge(target, source) {
83
+ return merge(target, source, false);
84
+ }
85
+
86
+ /**
87
+ * Recursively merges partial objects into `target` in order and returns
88
+ * `target`, so that a later source overrides an earlier one.
89
+ *
90
+ * Values that are `null` or `undefined` are skipped, so a source that only
91
+ * provides some of the properties does not remove the others. For the same
92
+ * reason, a property that the target already has is not replaced with an
93
+ * object when the source has one for the same key. Arrays are copied one level
94
+ * deep, so that the result does not share an array with any of the sources.
95
+ *
96
+ * Sources that are not plain objects are ignored. When `target` is not a plain
97
+ * object, it is returned without changes.
98
+ *
99
+ * Keys that would modify `Object.prototype`, such as `__proto__`, are ignored.
100
+ *
101
+ * @param {object} target the object to merge into, modified in place
102
+ * @param {...object} sources the objects to copy the properties from
103
+ * @return {object} the `target` object
104
+ */
105
+ export function deepMergePartials(target, ...sources) {
106
+ sources.forEach((source) => merge(target, source, true));
107
+
108
+ return target;
109
+ }