@schukai/monster 4.48.1 → 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 CHANGED
@@ -2,6 +2,14 @@
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
+
5
13
  ## [4.48.1] - 2025-11-28
6
14
 
7
15
  ### Bug Fixes
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"}
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(() => {
@@ -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,62 @@ 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
+ 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
+
1882
1961
  /**
1883
1962
  * @private
1884
1963
  * @param {*} value
@@ -1892,6 +1971,13 @@ function getSelectionLabel(value) {
1892
1971
  if (isString(label)) return label;
1893
1972
  }
1894
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
+
1895
1981
  if (isString(value) || isInteger(value)) {
1896
1982
  return `${value}`;
1897
1983
  }