@schukai/monster 4.48.1 → 4.48.3
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 +100 -0
package/CHANGELOG.md
CHANGED
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.3"}
|
|
@@ -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(() => {
|
|
@@ -1845,6 +1863,11 @@ function parseSlotsToOptions() {
|
|
|
1845
1863
|
* @return {*}
|
|
1846
1864
|
*/
|
|
1847
1865
|
function buildSelectionLabel(value) {
|
|
1866
|
+
// First, check the lookup cache.
|
|
1867
|
+
if (this[lookupCacheSymbol].has(value)) {
|
|
1868
|
+
return this[lookupCacheSymbol].get(value);
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1848
1871
|
const options = this.getOption("options");
|
|
1849
1872
|
|
|
1850
1873
|
for (let i = 0; i < options.length; i++) {
|
|
@@ -1879,6 +1902,74 @@ function buildSelectionLabel(value) {
|
|
|
1879
1902
|
return undefined;
|
|
1880
1903
|
}
|
|
1881
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
|
+
// A more robust check for invalid values. 0 and "" are valid.
|
|
1913
|
+
if (!lookupUrl || value === null || value === undefined || Number.isNaN(value)) {
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
// Avoid duplicate lookups for the same value.
|
|
1918
|
+
if (this[lookupInProgressSymbol].has(value)) {
|
|
1919
|
+
return;
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
try {
|
|
1923
|
+
this[lookupInProgressSymbol].set(value, true);
|
|
1924
|
+
|
|
1925
|
+
const markerOpen = this.getOption("filter.marker.open", "{");
|
|
1926
|
+
const markerClose = this.getOption("filter.marker.close", "}");
|
|
1927
|
+
const url = lookupUrl.replace(`${markerOpen}filter${markerClose}`, value);
|
|
1928
|
+
|
|
1929
|
+
const data = await fetchData.call(this, url);
|
|
1930
|
+
|
|
1931
|
+
const mappingOptions = this.getOption("mapping", {});
|
|
1932
|
+
const map = buildMap(
|
|
1933
|
+
data,
|
|
1934
|
+
mappingOptions.selector,
|
|
1935
|
+
mappingOptions.labelTemplate,
|
|
1936
|
+
mappingOptions.valueTemplate,
|
|
1937
|
+
mappingOptions.filter,
|
|
1938
|
+
);
|
|
1939
|
+
|
|
1940
|
+
let found = false;
|
|
1941
|
+
for (const [itemValue, itemLabel] of map.entries()) {
|
|
1942
|
+
// If the label template results in NaN, log an error and skip caching.
|
|
1943
|
+
if (itemLabel === "NaN") {
|
|
1944
|
+
addErrorAttribute(
|
|
1945
|
+
this,
|
|
1946
|
+
new Error(
|
|
1947
|
+
`Lookup for value '${itemValue}' resulted in a 'NaN' label. Check 'mapping.labelTemplate' and API response.`,
|
|
1948
|
+
),
|
|
1949
|
+
);
|
|
1950
|
+
continue;
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
// The lookup might return more than the requested value, so we cache all of them.
|
|
1954
|
+
if (!this[lookupCacheSymbol].has(itemValue)) {
|
|
1955
|
+
this[lookupCacheSymbol].set(itemValue, itemLabel);
|
|
1956
|
+
if (`${itemValue}` === `${value}`) {
|
|
1957
|
+
found = true;
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
// If the specific value was found, trigger a re-render of the selection.
|
|
1963
|
+
if (found) {
|
|
1964
|
+
await setSelection.call(this, this.getOption("selection"));
|
|
1965
|
+
}
|
|
1966
|
+
} catch (e) {
|
|
1967
|
+
addErrorAttribute(this, e);
|
|
1968
|
+
} finally {
|
|
1969
|
+
this[lookupInProgressSymbol].delete(value);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1882
1973
|
/**
|
|
1883
1974
|
* @private
|
|
1884
1975
|
* @param {*} value
|
|
@@ -1892,6 +1983,15 @@ function getSelectionLabel(value) {
|
|
|
1892
1983
|
if (isString(label)) return label;
|
|
1893
1984
|
}
|
|
1894
1985
|
|
|
1986
|
+
// If the label was not found, and we have a lookup URL, trigger a lookup for valid values.
|
|
1987
|
+
const isValueValidForLookup =
|
|
1988
|
+
value !== null && value !== undefined && !Number.isNaN(value);
|
|
1989
|
+
if (this.getOption("lookup.url") && isValueValidForLookup) {
|
|
1990
|
+
lookupValueAndCache.call(this, value).catch((e) => {
|
|
1991
|
+
addErrorAttribute(this, e);
|
|
1992
|
+
});
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1895
1995
|
if (isString(value) || isInteger(value)) {
|
|
1896
1996
|
return `${value}`;
|
|
1897
1997
|
}
|