@fkui/logic 6.18.0 → 6.19.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/lib/cjs/index.js CHANGED
@@ -198,6 +198,7 @@ class DecoratedError extends Error {
198
198
  constructor(message, cause) {
199
199
  super(message);
200
200
  Object.setPrototypeOf(this, DecoratedError.prototype);
201
+ /* eslint-disable-next-line @typescript-eslint/restrict-plus-operands -- technical debt */
201
202
  this.stack += `\nCaused by: ${cause.stack}`;
202
203
  this.cause = cause;
203
204
  }
@@ -220,7 +221,7 @@ class DecoratedError extends Error {
220
221
  }
221
222
  }
222
223
 
223
- const DATE_REGEXP_WITH_DASH = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
224
+ const DATE_REGEXP_WITH_DASH = /^\d{4}-\d{2}-\d{2}$/;
224
225
  /**
225
226
  * @public
226
227
  */
@@ -268,6 +269,7 @@ function validLimit(limit) {
268
269
  * @param immediate - Whether the function should be called at the beginning of the delay (Before the timeout) instead of the end.
269
270
  * Default is false.
270
271
  */
272
+ /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- technical debt */
271
273
  function debounce(func, delay, immediate = false) {
272
274
  let timeout = null;
273
275
  return function functionToExecute(...args) {
@@ -2108,7 +2110,7 @@ function deepClone(value) {
2108
2110
  * @param prefix - If set this is prefixed to all keys.
2109
2111
  */
2110
2112
  function flatten(src, destination, prefix = "") {
2111
- destination = destination || {};
2113
+ destination = destination ?? {};
2112
2114
  return Object.entries(src).reduce((result, [key, data]) => {
2113
2115
  const nestedKey = `${prefix}${key}`;
2114
2116
  if (typeof data === "string") {
@@ -2148,7 +2150,7 @@ function normalizeDateFormat(value) {
2148
2150
  const match = supportedFormats
2149
2151
  .map((pattern) => value.match(pattern))
2150
2152
  .find(Boolean);
2151
- if (!match || !match.groups) {
2153
+ if (!match?.groups) {
2152
2154
  return undefined;
2153
2155
  }
2154
2156
  const { year, month, day } = match.groups;
@@ -2164,7 +2166,7 @@ function normalizeDateFormat(value) {
2164
2166
  */
2165
2167
  function testLuhnChecksum(inputString) {
2166
2168
  let sum = 0;
2167
- if (/^[0-9]+$/.test(inputString) === false) {
2169
+ if (/^\d+$/.test(inputString) === false) {
2168
2170
  throw new Error("Luhn Checksum test only works on strings containing numbers");
2169
2171
  }
2170
2172
  inputString
@@ -2242,7 +2244,7 @@ function parseBankAccountNumber(value) {
2242
2244
  : undefined;
2243
2245
  }
2244
2246
 
2245
- const BANKGIRO_REGEXP_HYPHEN = /^(\d{3,4})[-]?(\d{4})$/;
2247
+ const BANKGIRO_REGEXP_HYPHEN = /^(\d{3,4})-?(\d{4})$/;
2246
2248
  /**
2247
2249
  * @public
2248
2250
  */
@@ -2250,6 +2252,7 @@ function parseBankgiro(value) {
2250
2252
  if (isEmpty(value)) {
2251
2253
  return undefined;
2252
2254
  }
2255
+ /* eslint-disable-next-line @typescript-eslint/prefer-regexp-exec -- technical debt */
2253
2256
  const match = value.match(BANKGIRO_REGEXP_HYPHEN);
2254
2257
  if (!match) {
2255
2258
  return undefined;
@@ -2550,8 +2553,9 @@ class FDate {
2550
2553
  * @public
2551
2554
  */
2552
2555
  static fromIso(value) {
2556
+ /* eslint-disable-next-line @typescript-eslint/prefer-regexp-exec -- technical debt */
2553
2557
  const match = value.match(/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/);
2554
- if (match && match.groups) {
2558
+ if (match?.groups) {
2555
2559
  const date = new FDate(value);
2556
2560
  const { month } = match.groups;
2557
2561
  /* in dayjs (and native Date) when the day overflows (e.g. 31 feb)
@@ -2958,7 +2962,7 @@ function stripWhitespace(text) {
2958
2962
  return text.replace(/\s+/g, "");
2959
2963
  }
2960
2964
 
2961
- const NUMBER_REGEXP$1 = /^([-]?[0-9]+)([,.][0-9]+)?$/;
2965
+ const NUMBER_REGEXP$1 = /^(-?\d+)([,.]\d+)?$/;
2962
2966
  function replaceCommaWithDot(str) {
2963
2967
  return str.replace(",", ".");
2964
2968
  }
@@ -3041,7 +3045,7 @@ function resolveCentury(year, month, day, hasPlus, now) {
3041
3045
  return (Number(nowCentury) - subtractCenturies).toString();
3042
3046
  }
3043
3047
 
3044
- const PERSONNUMMER_REGEXP = /^(?<century>\d{2})?(?<year>\d{2})(?<month>\d{2})(?<day>\d{2})(?<sign>-|\+)?(?<check>\d{4})$/;
3048
+ const PERSONNUMMER_REGEXP = /^(?<century>\d{2})?(?<year>\d{2})(?<month>\d{2})(?<day>\d{2})(?<sign>[-+])?(?<check>\d{4})$/;
3045
3049
  function getDayWithoutSamordning(day) {
3046
3050
  return (Number(day) % 60).toString().padStart(2, "0");
3047
3051
  }
@@ -3069,6 +3073,7 @@ function parsePersonnummer(value, now = FDate.now()) {
3069
3073
  if (!isSet(value)) {
3070
3074
  return undefined;
3071
3075
  }
3076
+ /* eslint-disable-next-line @typescript-eslint/prefer-regexp-exec -- technical debt */
3072
3077
  const match = stripWhitespace(value).match(PERSONNUMMER_REGEXP);
3073
3078
  if (!match) {
3074
3079
  return undefined;
@@ -3125,14 +3130,14 @@ function formatPersonnummer(value) {
3125
3130
  * @public
3126
3131
  */
3127
3132
  function formatPersonnummerToDate(value) {
3128
- const datePart = parseDate(parsePersonnummer(value)?.slice(0, 8) || "");
3133
+ const datePart = parseDate(parsePersonnummer(value)?.slice(0, 8) ?? "");
3129
3134
  if (!datePart) {
3130
3135
  return undefined;
3131
3136
  }
3132
3137
  return FDate.fromIso(datePart);
3133
3138
  }
3134
3139
 
3135
- const PLUSGIRO_REGEXP = /^\d{1,7}[-]?\d{1}$/;
3140
+ const PLUSGIRO_REGEXP = /^\d{1,7}-?\d$/;
3136
3141
  function hyphenShouldBeAdded(value) {
3137
3142
  return value.length >= 2 && value.length <= 8;
3138
3143
  }
@@ -3172,7 +3177,7 @@ function parsePlusgiro(value) {
3172
3177
  /**
3173
3178
  * @internal
3174
3179
  */
3175
- const POSTAL_CODE_REGEXP = /^([1-9]{1}\d{2}) ?(\d{2})$/;
3180
+ const POSTAL_CODE_REGEXP = /^([1-9]\d{2}) ?(\d{2})$/;
3176
3181
  /**
3177
3182
  * @public
3178
3183
  */
@@ -3180,6 +3185,7 @@ function formatPostalCode(value) {
3180
3185
  if (isEmpty(value)) {
3181
3186
  return undefined;
3182
3187
  }
3188
+ /* eslint-disable-next-line @typescript-eslint/prefer-regexp-exec -- technical debt */
3183
3189
  const match = value.match(POSTAL_CODE_REGEXP);
3184
3190
  if (match === null) {
3185
3191
  return undefined;
@@ -3193,7 +3199,7 @@ function parsePostalCode(value) {
3193
3199
  return formatPostalCode(value);
3194
3200
  }
3195
3201
 
3196
- const ORGANISATIONSNUMMER_REGEXP = /^([0-9]{6})-?([0-9]{4})$/;
3202
+ const ORGANISATIONSNUMMER_REGEXP = /^(\d{6})-?(\d{4})$/;
3197
3203
  /**
3198
3204
  * @public
3199
3205
  */
@@ -3201,6 +3207,7 @@ function parseOrganisationsnummer(value) {
3201
3207
  if (isEmpty(value)) {
3202
3208
  return undefined;
3203
3209
  }
3210
+ /* eslint-disable-next-line @typescript-eslint/prefer-regexp-exec -- technical debt */
3204
3211
  const match = value.match(ORGANISATIONSNUMMER_REGEXP);
3205
3212
  if (!match) {
3206
3213
  return undefined;
@@ -3221,6 +3228,7 @@ function formatPercent(modelValue, decimals) {
3221
3228
  * @public
3222
3229
  */
3223
3230
  function parsePercent(viewValue) {
3231
+ /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- technical debt */
3224
3232
  return parseNumber(viewValue);
3225
3233
  }
3226
3234
 
@@ -3302,7 +3310,7 @@ function scrollTo(element, arg = 0) {
3302
3310
  return Promise.resolve();
3303
3311
  }
3304
3312
  else {
3305
- return scrollToSlow(element, arg.duration || 500, arg.offset || 0);
3313
+ return scrollToSlow(element, arg.duration ?? 500, arg.offset ?? 0);
3306
3314
  }
3307
3315
  }
3308
3316
  /**
@@ -3605,6 +3613,7 @@ function isValidatableFormElement(element) {
3605
3613
  */
3606
3614
  function isVisibleInViewport(element) {
3607
3615
  const rect = element.getBoundingClientRect();
3616
+ /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
3608
3617
  return Boolean(rect.top >= 0 &&
3609
3618
  rect.left >= 0 &&
3610
3619
  rect.bottom <=
@@ -3796,8 +3805,10 @@ class DefaultTranslationProvider {
3796
3805
  get currentLanguage() {
3797
3806
  return this.language;
3798
3807
  }
3799
- async changeLanguage(language) {
3808
+ /* @todo technical debt, changeLanguage should accept just void */
3809
+ changeLanguage(language) {
3800
3810
  this.language = language;
3811
+ return Promise.resolve();
3801
3812
  }
3802
3813
  translate(key, defaultValueOrArgs, args) {
3803
3814
  if (this.language === "cimode") {
@@ -3958,8 +3969,9 @@ function getErrorMessages() {
3958
3969
  * @internal
3959
3970
  */
3960
3971
  function createFieldsetValidator(element, validationService) {
3961
- /* eslint-disable-next-line no-new -- technical debt, this should be
3962
- * refactored as to not rely of side-effects of the constructor */
3972
+ /* eslint-disable-next-line no-new, sonarjs/constructor-for-side-effects --
3973
+ * technical debt, this should be refactored as to not rely of side-effects
3974
+ * of the constructor */
3963
3975
  new FieldsetValidationHandler(element, validationService);
3964
3976
  }
3965
3977
  class FieldsetValidationHandler {
@@ -3971,7 +3983,9 @@ class FieldsetValidationHandler {
3971
3983
  Object.assign(this);
3972
3984
  this.element = element;
3973
3985
  this.validationService = validationService;
3974
- element.addEventListener("focusin", (event) => this.onFocusIn(event));
3986
+ element.addEventListener("focusin", (event) => {
3987
+ this.onFocusIn(event);
3988
+ });
3975
3989
  // Handle checking of input by using keyboard (space)
3976
3990
  element.addEventListener("change", this.documentFocusIn.bind(this));
3977
3991
  Array.from(this.element.querySelectorAll("input[type='checkbox'], input[type='radio']"))
@@ -4066,9 +4080,10 @@ function getElementType(element) {
4066
4080
  if (element instanceof HTMLInputElement) {
4067
4081
  return element.type === "checkbox"
4068
4082
  ? "checkbox"
4069
- : element.type === "radio"
4070
- ? "radio"
4071
- : "text";
4083
+ : /* eslint-disable-next-line sonarjs/no-nested-conditional -- technical debt */
4084
+ element.type === "radio"
4085
+ ? "radio"
4086
+ : "text";
4072
4087
  }
4073
4088
  else if (element instanceof HTMLTextAreaElement) {
4074
4089
  return "textarea";
@@ -4263,6 +4278,7 @@ class ValidationServiceImpl {
4263
4278
  });
4264
4279
  });
4265
4280
  }
4281
+ /* eslint-disable-next-line @typescript-eslint/require-await -- technical debt */
4266
4282
  async isValid(src, root = document) {
4267
4283
  /* nest inner sync function mostly because the code itself is sync
4268
4284
  * (especially required by Array.every) but we still want the API to be
@@ -4349,6 +4365,7 @@ class ValidationServiceImpl {
4349
4365
  const tagName = element.tagName.toLowerCase();
4350
4366
  const ref = `${tagName}#${element.id}`;
4351
4367
  element.removeEventListener("validity", once);
4368
+ /* eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- technical debt */
4352
4369
  reject(`Element "${ref}" did not respond with validity event after 500ms`);
4353
4370
  }, 500);
4354
4371
  /* Dispatch request to validate, this is supposed to be picked up by
@@ -4449,7 +4466,9 @@ class ValidationServiceImpl {
4449
4466
  return foundValidators.some((validator) => {
4450
4467
  const config = validatorConfigs[validator.name];
4451
4468
  const instantConfig = isSet(config) ? config.instant : undefined;
4452
- return ((validator.instant && instantConfig !== false) ||
4469
+ return (
4470
+ /* eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- false positive */
4471
+ (validator.instant && instantConfig !== false) ||
4453
4472
  instantConfig === true);
4454
4473
  });
4455
4474
  }
@@ -4517,9 +4536,7 @@ class ValidationServiceImpl {
4517
4536
  if (element instanceof HTMLDivElement) {
4518
4537
  return false;
4519
4538
  }
4520
- return Boolean(isRadiobuttonOrCheckbox(element)
4521
- ? element.checked
4522
- : element.value);
4539
+ return Boolean(isRadiobuttonOrCheckbox(element) ? element.checked : element.value);
4523
4540
  }
4524
4541
  getValue(element) {
4525
4542
  if ("value" in element) {
@@ -4560,7 +4577,7 @@ class ValidationServiceImpl {
4560
4577
  }
4561
4578
  }
4562
4579
  validate(value, element, validator, validatorConfigs) {
4563
- const validatorConfig = validatorConfigs[validator.name] || {};
4580
+ const validatorConfig = validatorConfigs[validator.name] ?? {};
4564
4581
  const isEnabled = validatorConfig.enabled === undefined ||
4565
4582
  validatorConfig.enabled === true;
4566
4583
  /**
@@ -4711,13 +4728,16 @@ const decimalValidator = {
4711
4728
  name: "decimal",
4712
4729
  validation(value, _element, config) {
4713
4730
  const valueWithoutWhitespace = isSet(value)
4714
- ? stripWhitespace(String(value))
4731
+ ? /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4732
+ stripWhitespace(String(value))
4715
4733
  : value;
4716
4734
  const minDecimalsAsNumber = isSet(config.minDecimals)
4717
- ? Number(config.minDecimals)
4735
+ ? /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4736
+ Number(config.minDecimals)
4718
4737
  : undefined;
4719
4738
  const maxDecimalsAsNumber = isSet(config.maxDecimals)
4720
- ? Number(config.maxDecimals)
4739
+ ? /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4740
+ Number(config.maxDecimals)
4721
4741
  : undefined;
4722
4742
  /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- technical debt, should actually verfiy value instead */
4723
4743
  if (config.minDecimals && isNaN(minDecimalsAsNumber)) {
@@ -4735,7 +4755,7 @@ const decimalValidator = {
4735
4755
  const emailValidator = {
4736
4756
  name: "email",
4737
4757
  validation(value, _element, config) {
4738
- const maxLength = config.maxLength || 254;
4758
+ const maxLength = config.maxLength ?? 254;
4739
4759
  const EMAIL_REGEXP = new RegExp(`^(?=.{1,${maxLength}}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_\`a-z{|}~åäöÅÄÖ]+(\\.[-!#$%&'*+/0-9=?A-Z^_\`a-z{|}~åäöÅÄÖ]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$`);
4740
4760
  return isEmpty(value) || EMAIL_REGEXP.test(value);
4741
4761
  },
@@ -4744,6 +4764,7 @@ const emailValidator = {
4744
4764
  /**
4745
4765
  * @internal
4746
4766
  */
4767
+ /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- technical debt */
4747
4768
  function numberValidator$1(value, config, name, compare) {
4748
4769
  if (value === "") {
4749
4770
  return true;
@@ -4770,12 +4791,13 @@ const greaterThanValidator = {
4770
4791
  },
4771
4792
  };
4772
4793
 
4773
- const NUMBER_REGEXP = /^([-−]?[0-9]+)?$/;
4794
+ const NUMBER_REGEXP = /^([-−]?\d+)?$/;
4774
4795
  const integerValidator = {
4775
4796
  name: "integer",
4776
4797
  validation(value) {
4777
4798
  const valueWithoutWhitespace = isSet(value)
4778
- ? stripWhitespace(String(value))
4799
+ ? /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4800
+ stripWhitespace(String(value))
4779
4801
  : value;
4780
4802
  return (isEmpty(valueWithoutWhitespace) ||
4781
4803
  NUMBER_REGEXP.test(valueWithoutWhitespace));
@@ -4921,12 +4943,13 @@ const organisationsnummerValidator = {
4921
4943
  },
4922
4944
  };
4923
4945
 
4924
- const PERCENT_REGEXP = /^([-+]?[0-9]+)([,.][0-9]+)?$/;
4946
+ const PERCENT_REGEXP = /^([-+]?\d+)([,.]\d+)?$/;
4925
4947
  const percentValidator = {
4926
4948
  name: "percent",
4927
4949
  validation(value) {
4928
4950
  const valueWithoutWhitespace = isSet(value)
4929
- ? stripWhitespace(String(value))
4951
+ ? /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4952
+ stripWhitespace(String(value))
4930
4953
  : value;
4931
4954
  return (isEmpty(valueWithoutWhitespace) ||
4932
4955
  PERCENT_REGEXP.test(valueWithoutWhitespace));
@@ -4950,6 +4973,7 @@ const personnummerLuhnValidator = {
4950
4973
  const personnummerNotSame = {
4951
4974
  name: "personnummerNotSame",
4952
4975
  validation(value, _element, config) {
4976
+ /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4953
4977
  const valuePnr = parsePersonnummer(String(value));
4954
4978
  if (!valuePnr) {
4955
4979
  return true;
@@ -5122,6 +5146,7 @@ function waitForScreenReader(callback, delay = SCREEN_READER_DELAY) {
5122
5146
  resolve(result);
5123
5147
  }
5124
5148
  catch (err) {
5149
+ /* eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- technical debt */
5125
5150
  reject(err);
5126
5151
  }
5127
5152
  }, delay);
package/lib/esm/index.js CHANGED
@@ -196,6 +196,7 @@ class DecoratedError extends Error {
196
196
  constructor(message, cause) {
197
197
  super(message);
198
198
  Object.setPrototypeOf(this, DecoratedError.prototype);
199
+ /* eslint-disable-next-line @typescript-eslint/restrict-plus-operands -- technical debt */
199
200
  this.stack += `\nCaused by: ${cause.stack}`;
200
201
  this.cause = cause;
201
202
  }
@@ -218,7 +219,7 @@ class DecoratedError extends Error {
218
219
  }
219
220
  }
220
221
 
221
- const DATE_REGEXP_WITH_DASH = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
222
+ const DATE_REGEXP_WITH_DASH = /^\d{4}-\d{2}-\d{2}$/;
222
223
  /**
223
224
  * @public
224
225
  */
@@ -266,6 +267,7 @@ function validLimit(limit) {
266
267
  * @param immediate - Whether the function should be called at the beginning of the delay (Before the timeout) instead of the end.
267
268
  * Default is false.
268
269
  */
270
+ /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- technical debt */
269
271
  function debounce(func, delay, immediate = false) {
270
272
  let timeout = null;
271
273
  return function functionToExecute(...args) {
@@ -2106,7 +2108,7 @@ function deepClone(value) {
2106
2108
  * @param prefix - If set this is prefixed to all keys.
2107
2109
  */
2108
2110
  function flatten(src, destination, prefix = "") {
2109
- destination = destination || {};
2111
+ destination = destination ?? {};
2110
2112
  return Object.entries(src).reduce((result, [key, data]) => {
2111
2113
  const nestedKey = `${prefix}${key}`;
2112
2114
  if (typeof data === "string") {
@@ -2146,7 +2148,7 @@ function normalizeDateFormat(value) {
2146
2148
  const match = supportedFormats
2147
2149
  .map((pattern) => value.match(pattern))
2148
2150
  .find(Boolean);
2149
- if (!match || !match.groups) {
2151
+ if (!match?.groups) {
2150
2152
  return undefined;
2151
2153
  }
2152
2154
  const { year, month, day } = match.groups;
@@ -2162,7 +2164,7 @@ function normalizeDateFormat(value) {
2162
2164
  */
2163
2165
  function testLuhnChecksum(inputString) {
2164
2166
  let sum = 0;
2165
- if (/^[0-9]+$/.test(inputString) === false) {
2167
+ if (/^\d+$/.test(inputString) === false) {
2166
2168
  throw new Error("Luhn Checksum test only works on strings containing numbers");
2167
2169
  }
2168
2170
  inputString
@@ -2240,7 +2242,7 @@ function parseBankAccountNumber(value) {
2240
2242
  : undefined;
2241
2243
  }
2242
2244
 
2243
- const BANKGIRO_REGEXP_HYPHEN = /^(\d{3,4})[-]?(\d{4})$/;
2245
+ const BANKGIRO_REGEXP_HYPHEN = /^(\d{3,4})-?(\d{4})$/;
2244
2246
  /**
2245
2247
  * @public
2246
2248
  */
@@ -2248,6 +2250,7 @@ function parseBankgiro(value) {
2248
2250
  if (isEmpty(value)) {
2249
2251
  return undefined;
2250
2252
  }
2253
+ /* eslint-disable-next-line @typescript-eslint/prefer-regexp-exec -- technical debt */
2251
2254
  const match = value.match(BANKGIRO_REGEXP_HYPHEN);
2252
2255
  if (!match) {
2253
2256
  return undefined;
@@ -2548,8 +2551,9 @@ class FDate {
2548
2551
  * @public
2549
2552
  */
2550
2553
  static fromIso(value) {
2554
+ /* eslint-disable-next-line @typescript-eslint/prefer-regexp-exec -- technical debt */
2551
2555
  const match = value.match(/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/);
2552
- if (match && match.groups) {
2556
+ if (match?.groups) {
2553
2557
  const date = new FDate(value);
2554
2558
  const { month } = match.groups;
2555
2559
  /* in dayjs (and native Date) when the day overflows (e.g. 31 feb)
@@ -2956,7 +2960,7 @@ function stripWhitespace(text) {
2956
2960
  return text.replace(/\s+/g, "");
2957
2961
  }
2958
2962
 
2959
- const NUMBER_REGEXP$1 = /^([-]?[0-9]+)([,.][0-9]+)?$/;
2963
+ const NUMBER_REGEXP$1 = /^(-?\d+)([,.]\d+)?$/;
2960
2964
  function replaceCommaWithDot(str) {
2961
2965
  return str.replace(",", ".");
2962
2966
  }
@@ -3039,7 +3043,7 @@ function resolveCentury(year, month, day, hasPlus, now) {
3039
3043
  return (Number(nowCentury) - subtractCenturies).toString();
3040
3044
  }
3041
3045
 
3042
- const PERSONNUMMER_REGEXP = /^(?<century>\d{2})?(?<year>\d{2})(?<month>\d{2})(?<day>\d{2})(?<sign>-|\+)?(?<check>\d{4})$/;
3046
+ const PERSONNUMMER_REGEXP = /^(?<century>\d{2})?(?<year>\d{2})(?<month>\d{2})(?<day>\d{2})(?<sign>[-+])?(?<check>\d{4})$/;
3043
3047
  function getDayWithoutSamordning(day) {
3044
3048
  return (Number(day) % 60).toString().padStart(2, "0");
3045
3049
  }
@@ -3067,6 +3071,7 @@ function parsePersonnummer(value, now = FDate.now()) {
3067
3071
  if (!isSet(value)) {
3068
3072
  return undefined;
3069
3073
  }
3074
+ /* eslint-disable-next-line @typescript-eslint/prefer-regexp-exec -- technical debt */
3070
3075
  const match = stripWhitespace(value).match(PERSONNUMMER_REGEXP);
3071
3076
  if (!match) {
3072
3077
  return undefined;
@@ -3123,14 +3128,14 @@ function formatPersonnummer(value) {
3123
3128
  * @public
3124
3129
  */
3125
3130
  function formatPersonnummerToDate(value) {
3126
- const datePart = parseDate(parsePersonnummer(value)?.slice(0, 8) || "");
3131
+ const datePart = parseDate(parsePersonnummer(value)?.slice(0, 8) ?? "");
3127
3132
  if (!datePart) {
3128
3133
  return undefined;
3129
3134
  }
3130
3135
  return FDate.fromIso(datePart);
3131
3136
  }
3132
3137
 
3133
- const PLUSGIRO_REGEXP = /^\d{1,7}[-]?\d{1}$/;
3138
+ const PLUSGIRO_REGEXP = /^\d{1,7}-?\d$/;
3134
3139
  function hyphenShouldBeAdded(value) {
3135
3140
  return value.length >= 2 && value.length <= 8;
3136
3141
  }
@@ -3170,7 +3175,7 @@ function parsePlusgiro(value) {
3170
3175
  /**
3171
3176
  * @internal
3172
3177
  */
3173
- const POSTAL_CODE_REGEXP = /^([1-9]{1}\d{2}) ?(\d{2})$/;
3178
+ const POSTAL_CODE_REGEXP = /^([1-9]\d{2}) ?(\d{2})$/;
3174
3179
  /**
3175
3180
  * @public
3176
3181
  */
@@ -3178,6 +3183,7 @@ function formatPostalCode(value) {
3178
3183
  if (isEmpty(value)) {
3179
3184
  return undefined;
3180
3185
  }
3186
+ /* eslint-disable-next-line @typescript-eslint/prefer-regexp-exec -- technical debt */
3181
3187
  const match = value.match(POSTAL_CODE_REGEXP);
3182
3188
  if (match === null) {
3183
3189
  return undefined;
@@ -3191,7 +3197,7 @@ function parsePostalCode(value) {
3191
3197
  return formatPostalCode(value);
3192
3198
  }
3193
3199
 
3194
- const ORGANISATIONSNUMMER_REGEXP = /^([0-9]{6})-?([0-9]{4})$/;
3200
+ const ORGANISATIONSNUMMER_REGEXP = /^(\d{6})-?(\d{4})$/;
3195
3201
  /**
3196
3202
  * @public
3197
3203
  */
@@ -3199,6 +3205,7 @@ function parseOrganisationsnummer(value) {
3199
3205
  if (isEmpty(value)) {
3200
3206
  return undefined;
3201
3207
  }
3208
+ /* eslint-disable-next-line @typescript-eslint/prefer-regexp-exec -- technical debt */
3202
3209
  const match = value.match(ORGANISATIONSNUMMER_REGEXP);
3203
3210
  if (!match) {
3204
3211
  return undefined;
@@ -3219,6 +3226,7 @@ function formatPercent(modelValue, decimals) {
3219
3226
  * @public
3220
3227
  */
3221
3228
  function parsePercent(viewValue) {
3229
+ /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- technical debt */
3222
3230
  return parseNumber(viewValue);
3223
3231
  }
3224
3232
 
@@ -3300,7 +3308,7 @@ function scrollTo(element, arg = 0) {
3300
3308
  return Promise.resolve();
3301
3309
  }
3302
3310
  else {
3303
- return scrollToSlow(element, arg.duration || 500, arg.offset || 0);
3311
+ return scrollToSlow(element, arg.duration ?? 500, arg.offset ?? 0);
3304
3312
  }
3305
3313
  }
3306
3314
  /**
@@ -3603,6 +3611,7 @@ function isValidatableFormElement(element) {
3603
3611
  */
3604
3612
  function isVisibleInViewport(element) {
3605
3613
  const rect = element.getBoundingClientRect();
3614
+ /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
3606
3615
  return Boolean(rect.top >= 0 &&
3607
3616
  rect.left >= 0 &&
3608
3617
  rect.bottom <=
@@ -3794,8 +3803,10 @@ class DefaultTranslationProvider {
3794
3803
  get currentLanguage() {
3795
3804
  return this.language;
3796
3805
  }
3797
- async changeLanguage(language) {
3806
+ /* @todo technical debt, changeLanguage should accept just void */
3807
+ changeLanguage(language) {
3798
3808
  this.language = language;
3809
+ return Promise.resolve();
3799
3810
  }
3800
3811
  translate(key, defaultValueOrArgs, args) {
3801
3812
  if (this.language === "cimode") {
@@ -3956,8 +3967,9 @@ function getErrorMessages() {
3956
3967
  * @internal
3957
3968
  */
3958
3969
  function createFieldsetValidator(element, validationService) {
3959
- /* eslint-disable-next-line no-new -- technical debt, this should be
3960
- * refactored as to not rely of side-effects of the constructor */
3970
+ /* eslint-disable-next-line no-new, sonarjs/constructor-for-side-effects --
3971
+ * technical debt, this should be refactored as to not rely of side-effects
3972
+ * of the constructor */
3961
3973
  new FieldsetValidationHandler(element, validationService);
3962
3974
  }
3963
3975
  class FieldsetValidationHandler {
@@ -3969,7 +3981,9 @@ class FieldsetValidationHandler {
3969
3981
  Object.assign(this);
3970
3982
  this.element = element;
3971
3983
  this.validationService = validationService;
3972
- element.addEventListener("focusin", (event) => this.onFocusIn(event));
3984
+ element.addEventListener("focusin", (event) => {
3985
+ this.onFocusIn(event);
3986
+ });
3973
3987
  // Handle checking of input by using keyboard (space)
3974
3988
  element.addEventListener("change", this.documentFocusIn.bind(this));
3975
3989
  Array.from(this.element.querySelectorAll("input[type='checkbox'], input[type='radio']"))
@@ -4064,9 +4078,10 @@ function getElementType(element) {
4064
4078
  if (element instanceof HTMLInputElement) {
4065
4079
  return element.type === "checkbox"
4066
4080
  ? "checkbox"
4067
- : element.type === "radio"
4068
- ? "radio"
4069
- : "text";
4081
+ : /* eslint-disable-next-line sonarjs/no-nested-conditional -- technical debt */
4082
+ element.type === "radio"
4083
+ ? "radio"
4084
+ : "text";
4070
4085
  }
4071
4086
  else if (element instanceof HTMLTextAreaElement) {
4072
4087
  return "textarea";
@@ -4261,6 +4276,7 @@ class ValidationServiceImpl {
4261
4276
  });
4262
4277
  });
4263
4278
  }
4279
+ /* eslint-disable-next-line @typescript-eslint/require-await -- technical debt */
4264
4280
  async isValid(src, root = document) {
4265
4281
  /* nest inner sync function mostly because the code itself is sync
4266
4282
  * (especially required by Array.every) but we still want the API to be
@@ -4347,6 +4363,7 @@ class ValidationServiceImpl {
4347
4363
  const tagName = element.tagName.toLowerCase();
4348
4364
  const ref = `${tagName}#${element.id}`;
4349
4365
  element.removeEventListener("validity", once);
4366
+ /* eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- technical debt */
4350
4367
  reject(`Element "${ref}" did not respond with validity event after 500ms`);
4351
4368
  }, 500);
4352
4369
  /* Dispatch request to validate, this is supposed to be picked up by
@@ -4447,7 +4464,9 @@ class ValidationServiceImpl {
4447
4464
  return foundValidators.some((validator) => {
4448
4465
  const config = validatorConfigs[validator.name];
4449
4466
  const instantConfig = isSet(config) ? config.instant : undefined;
4450
- return ((validator.instant && instantConfig !== false) ||
4467
+ return (
4468
+ /* eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- false positive */
4469
+ (validator.instant && instantConfig !== false) ||
4451
4470
  instantConfig === true);
4452
4471
  });
4453
4472
  }
@@ -4515,9 +4534,7 @@ class ValidationServiceImpl {
4515
4534
  if (element instanceof HTMLDivElement) {
4516
4535
  return false;
4517
4536
  }
4518
- return Boolean(isRadiobuttonOrCheckbox(element)
4519
- ? element.checked
4520
- : element.value);
4537
+ return Boolean(isRadiobuttonOrCheckbox(element) ? element.checked : element.value);
4521
4538
  }
4522
4539
  getValue(element) {
4523
4540
  if ("value" in element) {
@@ -4558,7 +4575,7 @@ class ValidationServiceImpl {
4558
4575
  }
4559
4576
  }
4560
4577
  validate(value, element, validator, validatorConfigs) {
4561
- const validatorConfig = validatorConfigs[validator.name] || {};
4578
+ const validatorConfig = validatorConfigs[validator.name] ?? {};
4562
4579
  const isEnabled = validatorConfig.enabled === undefined ||
4563
4580
  validatorConfig.enabled === true;
4564
4581
  /**
@@ -4709,13 +4726,16 @@ const decimalValidator = {
4709
4726
  name: "decimal",
4710
4727
  validation(value, _element, config) {
4711
4728
  const valueWithoutWhitespace = isSet(value)
4712
- ? stripWhitespace(String(value))
4729
+ ? /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4730
+ stripWhitespace(String(value))
4713
4731
  : value;
4714
4732
  const minDecimalsAsNumber = isSet(config.minDecimals)
4715
- ? Number(config.minDecimals)
4733
+ ? /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4734
+ Number(config.minDecimals)
4716
4735
  : undefined;
4717
4736
  const maxDecimalsAsNumber = isSet(config.maxDecimals)
4718
- ? Number(config.maxDecimals)
4737
+ ? /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4738
+ Number(config.maxDecimals)
4719
4739
  : undefined;
4720
4740
  /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- technical debt, should actually verfiy value instead */
4721
4741
  if (config.minDecimals && isNaN(minDecimalsAsNumber)) {
@@ -4733,7 +4753,7 @@ const decimalValidator = {
4733
4753
  const emailValidator = {
4734
4754
  name: "email",
4735
4755
  validation(value, _element, config) {
4736
- const maxLength = config.maxLength || 254;
4756
+ const maxLength = config.maxLength ?? 254;
4737
4757
  const EMAIL_REGEXP = new RegExp(`^(?=.{1,${maxLength}}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_\`a-z{|}~åäöÅÄÖ]+(\\.[-!#$%&'*+/0-9=?A-Z^_\`a-z{|}~åäöÅÄÖ]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$`);
4738
4758
  return isEmpty(value) || EMAIL_REGEXP.test(value);
4739
4759
  },
@@ -4742,6 +4762,7 @@ const emailValidator = {
4742
4762
  /**
4743
4763
  * @internal
4744
4764
  */
4765
+ /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- technical debt */
4745
4766
  function numberValidator$1(value, config, name, compare) {
4746
4767
  if (value === "") {
4747
4768
  return true;
@@ -4768,12 +4789,13 @@ const greaterThanValidator = {
4768
4789
  },
4769
4790
  };
4770
4791
 
4771
- const NUMBER_REGEXP = /^([-−]?[0-9]+)?$/;
4792
+ const NUMBER_REGEXP = /^([-−]?\d+)?$/;
4772
4793
  const integerValidator = {
4773
4794
  name: "integer",
4774
4795
  validation(value) {
4775
4796
  const valueWithoutWhitespace = isSet(value)
4776
- ? stripWhitespace(String(value))
4797
+ ? /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4798
+ stripWhitespace(String(value))
4777
4799
  : value;
4778
4800
  return (isEmpty(valueWithoutWhitespace) ||
4779
4801
  NUMBER_REGEXP.test(valueWithoutWhitespace));
@@ -4919,12 +4941,13 @@ const organisationsnummerValidator = {
4919
4941
  },
4920
4942
  };
4921
4943
 
4922
- const PERCENT_REGEXP = /^([-+]?[0-9]+)([,.][0-9]+)?$/;
4944
+ const PERCENT_REGEXP = /^([-+]?\d+)([,.]\d+)?$/;
4923
4945
  const percentValidator = {
4924
4946
  name: "percent",
4925
4947
  validation(value) {
4926
4948
  const valueWithoutWhitespace = isSet(value)
4927
- ? stripWhitespace(String(value))
4949
+ ? /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4950
+ stripWhitespace(String(value))
4928
4951
  : value;
4929
4952
  return (isEmpty(valueWithoutWhitespace) ||
4930
4953
  PERCENT_REGEXP.test(valueWithoutWhitespace));
@@ -4948,6 +4971,7 @@ const personnummerLuhnValidator = {
4948
4971
  const personnummerNotSame = {
4949
4972
  name: "personnummerNotSame",
4950
4973
  validation(value, _element, config) {
4974
+ /* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion -- technical debt */
4951
4975
  const valuePnr = parsePersonnummer(String(value));
4952
4976
  if (!valuePnr) {
4953
4977
  return true;
@@ -5120,6 +5144,7 @@ function waitForScreenReader(callback, delay = SCREEN_READER_DELAY) {
5120
5144
  resolve(result);
5121
5145
  }
5122
5146
  catch (err) {
5147
+ /* eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors -- technical debt */
5123
5148
  reject(err);
5124
5149
  }
5125
5150
  }, delay);
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.52.11"
8
+ "packageVersion": "7.52.13"
9
9
  }
10
10
  ]
11
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fkui/logic",
3
- "version": "6.18.0",
3
+ "version": "6.19.0",
4
4
  "description": "Logic",
5
5
  "keywords": [
6
6
  "fkui",
@@ -61,11 +61,11 @@
61
61
  "watch": "rollup --config --watch"
62
62
  },
63
63
  "peerDependencies": {
64
- "@fkui/date": "^6.18.0"
64
+ "@fkui/date": "^6.19.0"
65
65
  },
66
66
  "engines": {
67
67
  "node": ">= 20",
68
68
  "npm": ">= 7"
69
69
  },
70
- "gitHead": "3931bff1021afd55de9cb6455e9f54e9871d8a59"
70
+ "gitHead": "fabd8b6313e8e8ff4191553456ae418b682ec010"
71
71
  }