@schukai/monster 4.48.2 → 4.49.0

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,22 @@
2
2
 
3
3
 
4
4
 
5
+ ## [4.49.0] - 2025-12-21
6
+
7
+ ### Add Features
8
+
9
+ - Added fields object for mapping form input names in login component
10
+
11
+
12
+
13
+ ## [4.48.3] - 2025-12-02
14
+
15
+ ### Bug Fixes
16
+
17
+ - **select:** prevent NaN labels
18
+
19
+
20
+
5
21
  ## [4.48.2] - 2025-12-02
6
22
 
7
23
  ### 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.2"}
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.49.0"}
@@ -214,6 +214,9 @@ class Login extends CustomElement {
214
214
  * @property {boolean} features.redirectToFirstSuccessUrl If true, redirects to the first success URL after login
215
215
  * @property {Object} actions Action definitions for custom event handling
216
216
  * @property {Function} actions.click Callback function for generic click actions within the login component
217
+ * @property {Object} fields Field mappings for form inputs
218
+ * @property {string} fields.identifier Name of the identifier field (username/email)
219
+ * @property {string} fields.password Name of the password field
217
220
  * @property {Object} callbacks Optional callback hooks for modifying internal behavior
218
221
  * @property {Function} callbacks.username A function that receives and can transform the entered username before submission
219
222
  * @property {Function} callbacks.forgotPassword A function that receives and can transform the entered email before submission
@@ -288,6 +291,11 @@ class Login extends CustomElement {
288
291
  },
289
292
  actions: {},
290
293
 
294
+ fields: {
295
+ identifier: "username",
296
+ password: "password",
297
+ }
298
+
291
299
  callbacks: {
292
300
  username: null,
293
301
  forgotPassword: null,
@@ -1126,7 +1134,7 @@ function initEventHandler() {
1126
1134
 
1127
1135
  const type = "click";
1128
1136
 
1129
- element.addEventListener(type, function (event) {
1137
+ element.addEventListener(type, function(event) {
1130
1138
  const callback = self.getOption("actions.click");
1131
1139
 
1132
1140
  fireCustomEvent(self, "monster-login-clicked", {
@@ -1293,12 +1301,23 @@ function initEventHandler() {
1293
1301
  return;
1294
1302
  }
1295
1303
 
1304
+ const identifierField =
1305
+ this.getOption("fields.login.identifier") || "username";
1306
+
1307
+ const passwordField =
1308
+ this.getOption("fields.login.password") || "password";
1309
+
1310
+ const payload = {
1311
+ [identifierField]: username,
1312
+ [passwordField]: password,
1313
+ };
1314
+
1296
1315
  const options = {
1297
1316
  method: this.getOption("fetch.login.method"),
1298
1317
  mode: this.getOption("fetch.login.mode"),
1299
1318
  headers: this.getOption("fetch.login.headers"),
1300
1319
  credentials: this.getOption("fetch.login.credentials"),
1301
- body: JSON.stringify({ username, password }),
1320
+ body: JSON.stringify(payload),
1302
1321
  };
1303
1322
 
1304
1323
  getWindow()
@@ -1909,7 +1909,8 @@ function buildSelectionLabel(value) {
1909
1909
  */
1910
1910
  async function lookupValueAndCache(value) {
1911
1911
  const lookupUrl = this.getOption("lookup.url");
1912
- if (!lookupUrl || !value) {
1912
+ // A more robust check for invalid values. 0 and "" are valid.
1913
+ if (!lookupUrl || value === null || value === undefined || Number.isNaN(value)) {
1913
1914
  return;
1914
1915
  }
1915
1916
 
@@ -1938,6 +1939,17 @@ async function lookupValueAndCache(value) {
1938
1939
 
1939
1940
  let found = false;
1940
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
+
1941
1953
  // The lookup might return more than the requested value, so we cache all of them.
1942
1954
  if (!this[lookupCacheSymbol].has(itemValue)) {
1943
1955
  this[lookupCacheSymbol].set(itemValue, itemLabel);
@@ -1971,8 +1983,10 @@ function getSelectionLabel(value) {
1971
1983
  if (isString(label)) return label;
1972
1984
  }
1973
1985
 
1974
- // If the label was not found, and we have a lookup URL, trigger a lookup.
1975
- if (this.getOption("lookup.url")) {
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) {
1976
1990
  lookupValueAndCache.call(this, value).catch((e) => {
1977
1991
  addErrorAttribute(this, e);
1978
1992
  });