@schukai/monster 4.48.0 → 4.48.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/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/source/components/form/select.mjs +97 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
## [4.48.2] - 2025-12-02
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- **select:** own lookup cache
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## [4.48.1] - 2025-11-28
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
- **components:** Prevent duplicate entries in select component [#345](https://gitlab.schukai.com/oss/libraries/javascript/monster/issues/345)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
5
21
|
## [4.48.0] - 2025-11-28
|
|
6
22
|
|
|
7
23
|
### Add Features
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.7.4","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.48.
|
|
1
|
+
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.7.4","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"4.48.2"}
|
|
@@ -272,6 +272,18 @@ const currentPageSymbol = Symbol("currentPage");
|
|
|
272
272
|
*/
|
|
273
273
|
const remoteFilterFirstOpendSymbol = Symbol("remoteFilterFirstOpend");
|
|
274
274
|
|
|
275
|
+
/**
|
|
276
|
+
* @private
|
|
277
|
+
* @type {symbol}
|
|
278
|
+
*/
|
|
279
|
+
const lookupCacheSymbol = Symbol("lookupCache");
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* @private
|
|
283
|
+
* @type {symbol}
|
|
284
|
+
*/
|
|
285
|
+
const lookupInProgressSymbol = Symbol("lookupInProgress");
|
|
286
|
+
|
|
275
287
|
/**
|
|
276
288
|
* @private
|
|
277
289
|
* @type {number}
|
|
@@ -346,6 +358,8 @@ class Select extends CustomControl {
|
|
|
346
358
|
constructor() {
|
|
347
359
|
super();
|
|
348
360
|
this[currentPageSymbol] = 1;
|
|
361
|
+
this[lookupCacheSymbol] = new Map();
|
|
362
|
+
this[lookupInProgressSymbol] = new Map();
|
|
349
363
|
initOptionObserver.call(this);
|
|
350
364
|
}
|
|
351
365
|
|
|
@@ -613,6 +627,10 @@ class Select extends CustomControl {
|
|
|
613
627
|
try {
|
|
614
628
|
hide.call(this);
|
|
615
629
|
|
|
630
|
+
// Clear the lookup cache
|
|
631
|
+
this[lookupCacheSymbol].clear();
|
|
632
|
+
this[lookupInProgressSymbol].clear();
|
|
633
|
+
|
|
616
634
|
setSelection
|
|
617
635
|
.call(this, null)
|
|
618
636
|
.then(() => {
|
|
@@ -1047,21 +1065,25 @@ function importOptionsIntern(data) {
|
|
|
1047
1065
|
}
|
|
1048
1066
|
|
|
1049
1067
|
for (const [value, label] of entries) {
|
|
1068
|
+
let found = false;
|
|
1050
1069
|
for (const option of options) {
|
|
1051
1070
|
if (option.value === value) {
|
|
1052
1071
|
option.label = label;
|
|
1053
1072
|
option.visibility = visibility;
|
|
1054
1073
|
option.data = map.get(value);
|
|
1055
|
-
|
|
1074
|
+
found = true;
|
|
1075
|
+
break;
|
|
1056
1076
|
}
|
|
1057
1077
|
}
|
|
1058
1078
|
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1079
|
+
if (!found) {
|
|
1080
|
+
options.push({
|
|
1081
|
+
value,
|
|
1082
|
+
label,
|
|
1083
|
+
visibility,
|
|
1084
|
+
data: map.get(value),
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1065
1087
|
}
|
|
1066
1088
|
|
|
1067
1089
|
this.setOption("options", options);
|
|
@@ -1841,6 +1863,11 @@ function parseSlotsToOptions() {
|
|
|
1841
1863
|
* @return {*}
|
|
1842
1864
|
*/
|
|
1843
1865
|
function buildSelectionLabel(value) {
|
|
1866
|
+
// First, check the lookup cache.
|
|
1867
|
+
if (this[lookupCacheSymbol].has(value)) {
|
|
1868
|
+
return this[lookupCacheSymbol].get(value);
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1844
1871
|
const options = this.getOption("options");
|
|
1845
1872
|
|
|
1846
1873
|
for (let i = 0; i < options.length; i++) {
|
|
@@ -1875,6 +1902,62 @@ function buildSelectionLabel(value) {
|
|
|
1875
1902
|
return undefined;
|
|
1876
1903
|
}
|
|
1877
1904
|
|
|
1905
|
+
/**
|
|
1906
|
+
* @private
|
|
1907
|
+
* @param {string} value The value to look up.
|
|
1908
|
+
* @returns {Promise<void>}
|
|
1909
|
+
*/
|
|
1910
|
+
async function lookupValueAndCache(value) {
|
|
1911
|
+
const lookupUrl = this.getOption("lookup.url");
|
|
1912
|
+
if (!lookupUrl || !value) {
|
|
1913
|
+
return;
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
// Avoid duplicate lookups for the same value.
|
|
1917
|
+
if (this[lookupInProgressSymbol].has(value)) {
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
try {
|
|
1922
|
+
this[lookupInProgressSymbol].set(value, true);
|
|
1923
|
+
|
|
1924
|
+
const markerOpen = this.getOption("filter.marker.open", "{");
|
|
1925
|
+
const markerClose = this.getOption("filter.marker.close", "}");
|
|
1926
|
+
const url = lookupUrl.replace(`${markerOpen}filter${markerClose}`, value);
|
|
1927
|
+
|
|
1928
|
+
const data = await fetchData.call(this, url);
|
|
1929
|
+
|
|
1930
|
+
const mappingOptions = this.getOption("mapping", {});
|
|
1931
|
+
const map = buildMap(
|
|
1932
|
+
data,
|
|
1933
|
+
mappingOptions.selector,
|
|
1934
|
+
mappingOptions.labelTemplate,
|
|
1935
|
+
mappingOptions.valueTemplate,
|
|
1936
|
+
mappingOptions.filter,
|
|
1937
|
+
);
|
|
1938
|
+
|
|
1939
|
+
let found = false;
|
|
1940
|
+
for (const [itemValue, itemLabel] of map.entries()) {
|
|
1941
|
+
// The lookup might return more than the requested value, so we cache all of them.
|
|
1942
|
+
if (!this[lookupCacheSymbol].has(itemValue)) {
|
|
1943
|
+
this[lookupCacheSymbol].set(itemValue, itemLabel);
|
|
1944
|
+
if (`${itemValue}` === `${value}`) {
|
|
1945
|
+
found = true;
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
// If the specific value was found, trigger a re-render of the selection.
|
|
1951
|
+
if (found) {
|
|
1952
|
+
await setSelection.call(this, this.getOption("selection"));
|
|
1953
|
+
}
|
|
1954
|
+
} catch (e) {
|
|
1955
|
+
addErrorAttribute(this, e);
|
|
1956
|
+
} finally {
|
|
1957
|
+
this[lookupInProgressSymbol].delete(value);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1878
1961
|
/**
|
|
1879
1962
|
* @private
|
|
1880
1963
|
* @param {*} value
|
|
@@ -1888,6 +1971,13 @@ function getSelectionLabel(value) {
|
|
|
1888
1971
|
if (isString(label)) return label;
|
|
1889
1972
|
}
|
|
1890
1973
|
|
|
1974
|
+
// If the label was not found, and we have a lookup URL, trigger a lookup.
|
|
1975
|
+
if (this.getOption("lookup.url")) {
|
|
1976
|
+
lookupValueAndCache.call(this, value).catch((e) => {
|
|
1977
|
+
addErrorAttribute(this, e);
|
|
1978
|
+
});
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1891
1981
|
if (isString(value) || isInteger(value)) {
|
|
1892
1982
|
return `${value}`;
|
|
1893
1983
|
}
|