@streamscloud/kit 0.42.1 → 0.44.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.
@@ -142,6 +142,9 @@ export class FormValidationHandler {
142
142
  if (event && event.preventDefault) {
143
143
  event.preventDefault();
144
144
  }
145
+ if (this._isSubmitting) {
146
+ return;
147
+ }
145
148
  try {
146
149
  this._isSubmitting = true;
147
150
  const values = this.form;
@@ -1,3 +1,5 @@
1
1
  import type { ArrayValidation } from './types';
2
2
  import * as yup from 'yup';
3
+ /** Value-level rules of `arrayValidationSchema`. Judges a real value — `null` / `undefined` are decided by the schema modifiers the caller adds. */
4
+ export declare const isValidArray: <TItem = unknown>(items: TItem[], rules: ArrayValidation) => boolean;
3
5
  export declare const arrayValidationSchema: <TItem = unknown>(rules: ArrayValidation) => yup.ArraySchema<TItem[] | undefined, yup.AnyObject, undefined, "">;
@@ -1,9 +1,18 @@
1
1
  import { ValidationLocalization } from './validation-localization';
2
2
  import * as yup from 'yup';
3
- export const arrayValidationSchema = (rules) => {
4
- const msg = new ValidationLocalization();
3
+ const resolveItemBounds = (rules) => {
5
4
  const minItems = rules.minItems > 0 ? rules.minItems : 0;
6
5
  const maxItems = rules.maxItems !== null && rules.maxItems >= 0 && rules.maxItems >= minItems ? rules.maxItems : undefined;
6
+ return { minItems, maxItems };
7
+ };
8
+ /** Value-level rules of `arrayValidationSchema`. Judges a real value — `null` / `undefined` are decided by the schema modifiers the caller adds. */
9
+ export const isValidArray = (items, rules) => {
10
+ const { minItems, maxItems } = resolveItemBounds(rules);
11
+ return items.length >= minItems && (maxItems === undefined || items.length <= maxItems);
12
+ };
13
+ export const arrayValidationSchema = (rules) => {
14
+ const msg = new ValidationLocalization();
15
+ const { minItems, maxItems } = resolveItemBounds(rules);
7
16
  let schema = yup.array();
8
17
  if (maxItems !== undefined) {
9
18
  schema = schema.max(maxItems, msg.maxItems(maxItems));
@@ -1,3 +1,5 @@
1
1
  import * as yup from 'yup';
2
+ /** The email format both email schemas check. Presence — empty, `null`, `undefined` — is decided by the schema the caller picks. */
3
+ export declare const isValidEmail: (value: string) => boolean;
2
4
  export declare const emailValidationSchema: () => yup.StringSchema<string, yup.AnyObject, undefined, "">;
3
5
  export declare const nullableEmailValidationSchema: () => yup.StringSchema<string | null | undefined, yup.AnyObject, undefined, "">;
@@ -1,6 +1,10 @@
1
1
  import { ValidationLocalization } from './validation-localization';
2
2
  import * as yup from 'yup';
3
- const EMAIL_REGEX = /^[a-zA-Z0-9_]([.+-]?[a-zA-Z0-9_])+@[a-zA-Z0-9]([.-]?[a-zA-Z0-9])+\.[a-zA-Z]{2,}$/;
3
+ const EMAIL_REGEX = /^[a-zA-Z0-9_]([.+-]?[a-zA-Z0-9_])*@[a-zA-Z0-9]([.-]?[a-zA-Z0-9])*\.[a-zA-Z]{2,}$/;
4
+ /** The email format both email schemas check. Presence — empty, `null`, `undefined` — is decided by the schema the caller picks. */
5
+ export const isValidEmail = (value) => {
6
+ return EMAIL_REGEX.test(value);
7
+ };
4
8
  export const emailValidationSchema = () => {
5
9
  const msg = new ValidationLocalization();
6
10
  return yup.string().required(msg.required).matches(EMAIL_REGEX, {
@@ -1,3 +1,5 @@
1
1
  import type { TextValidation } from './types';
2
2
  import * as yup from 'yup';
3
+ /** Value-level rules of `handleValidationSchema` — within length bounds and matching the handle format. */
4
+ export declare const isValidHandle: (value: string, lengthValidation?: TextValidation) => boolean;
3
5
  export declare const handleValidationSchema: (lengthValidation?: TextValidation) => yup.StringSchema<string, yup.AnyObject, undefined, "">;
@@ -3,10 +3,18 @@ import * as yup from 'yup';
3
3
  const DEFAULT_MIN_LENGTH = 3;
4
4
  const DEFAULT_MAX_LENGTH = 30;
5
5
  const HANDLE_REGEX = /^[a-z_]([a-z0-9_]|[.-](?![.-]))*[a-z0-9_]$/;
6
+ const resolveHandleLength = (lengthValidation) => ({
7
+ minLength: lengthValidation?.minLength ?? DEFAULT_MIN_LENGTH,
8
+ maxLength: lengthValidation?.maxLength ?? DEFAULT_MAX_LENGTH
9
+ });
10
+ /** Value-level rules of `handleValidationSchema` — within length bounds and matching the handle format. */
11
+ export const isValidHandle = (value, lengthValidation) => {
12
+ const { minLength, maxLength } = resolveHandleLength(lengthValidation);
13
+ return value.length >= minLength && value.length <= maxLength && HANDLE_REGEX.test(value);
14
+ };
6
15
  export const handleValidationSchema = (lengthValidation) => {
7
16
  const msg = new ValidationLocalization();
8
- const minLength = lengthValidation?.minLength ?? DEFAULT_MIN_LENGTH;
9
- const maxLength = lengthValidation?.maxLength ?? DEFAULT_MAX_LENGTH;
17
+ const { minLength, maxLength } = resolveHandleLength(lengthValidation);
10
18
  return yup
11
19
  .string()
12
20
  .required(msg.required)
@@ -1,7 +1,7 @@
1
1
  export type { TextValidation, TextWithFormatValidation, NumberValidation, MinNumberValidation, ArrayValidation, UrlValidation } from './types';
2
- export { emailValidationSchema, nullableEmailValidationSchema } from './email-validation';
3
- export { textValidationSchema, formattedTextValidationSchema } from './text-validations';
4
- export { handleValidationSchema } from './handle-validations';
5
- export { numberValidationSchema, minNumberValidationSchema } from './number-validations';
6
- export { arrayValidationSchema } from './array-validations';
7
- export { urlValidationSchema } from './url-validation';
2
+ export { emailValidationSchema, nullableEmailValidationSchema, isValidEmail } from './email-validation';
3
+ export { textValidationSchema, formattedTextValidationSchema, isValidText, isValidFormattedText } from './text-validations';
4
+ export { handleValidationSchema, isValidHandle } from './handle-validations';
5
+ export { numberValidationSchema, minNumberValidationSchema, isValidNumber, isValidMinNumber } from './number-validations';
6
+ export { arrayValidationSchema, isValidArray } from './array-validations';
7
+ export { urlValidationSchema, isValidUrl } from './url-validation';
@@ -1,6 +1,6 @@
1
- export { emailValidationSchema, nullableEmailValidationSchema } from './email-validation';
2
- export { textValidationSchema, formattedTextValidationSchema } from './text-validations';
3
- export { handleValidationSchema } from './handle-validations';
4
- export { numberValidationSchema, minNumberValidationSchema } from './number-validations';
5
- export { arrayValidationSchema } from './array-validations';
6
- export { urlValidationSchema } from './url-validation';
1
+ export { emailValidationSchema, nullableEmailValidationSchema, isValidEmail } from './email-validation';
2
+ export { textValidationSchema, formattedTextValidationSchema, isValidText, isValidFormattedText } from './text-validations';
3
+ export { handleValidationSchema, isValidHandle } from './handle-validations';
4
+ export { numberValidationSchema, minNumberValidationSchema, isValidNumber, isValidMinNumber } from './number-validations';
5
+ export { arrayValidationSchema, isValidArray } from './array-validations';
6
+ export { urlValidationSchema, isValidUrl } from './url-validation';
@@ -1,4 +1,8 @@
1
1
  import type { MinNumberValidation, NumberValidation } from './types';
2
2
  import * as yup from 'yup';
3
+ /** Value-level rules of `numberValidationSchema`. Judges a real value — `null` / `undefined` are decided by the schema modifiers the caller adds. */
4
+ export declare const isValidNumber: (value: number, rules: NumberValidation) => boolean;
5
+ /** Value-level rules of `minNumberValidationSchema`. Judges a real value — `null` / `undefined` are decided by the schema modifiers the caller adds. */
6
+ export declare const isValidMinNumber: (value: number, rules: MinNumberValidation) => boolean;
3
7
  export declare const numberValidationSchema: (rules: NumberValidation) => yup.NumberSchema<number | null | undefined, yup.AnyObject, undefined, "">;
4
8
  export declare const minNumberValidationSchema: (rules: MinNumberValidation) => yup.NumberSchema<number | null | undefined, yup.AnyObject, undefined, "">;
@@ -1,24 +1,41 @@
1
1
  import { ValidationLocalization } from './validation-localization';
2
2
  import * as yup from 'yup';
3
+ const resolveMinBound = (rules) => {
4
+ return rules.minValue === null ? null : rules.minExclusive ? rules.minValue + 1 : rules.minValue;
5
+ };
6
+ const resolveMaxBound = (rules) => {
7
+ return rules.maxValue === null ? null : rules.maxExclusive ? rules.maxValue - 1 : rules.maxValue;
8
+ };
9
+ /** Value-level rules of `numberValidationSchema`. Judges a real value — `null` / `undefined` are decided by the schema modifiers the caller adds. */
10
+ export const isValidNumber = (value, rules) => {
11
+ const min = resolveMinBound(rules);
12
+ const max = resolveMaxBound(rules);
13
+ return (min === null || value >= min) && (max === null || value <= max);
14
+ };
15
+ /** Value-level rules of `minNumberValidationSchema`. Judges a real value — `null` / `undefined` are decided by the schema modifiers the caller adds. */
16
+ export const isValidMinNumber = (value, rules) => {
17
+ const min = resolveMinBound(rules);
18
+ return min === null || value >= min;
19
+ };
3
20
  export const numberValidationSchema = (rules) => {
4
21
  const msg = new ValidationLocalization();
22
+ const min = resolveMinBound(rules);
23
+ const max = resolveMaxBound(rules);
5
24
  let schema = yup.number().typeError(msg.badFormat).nullable();
6
- if (rules.minValue !== null) {
7
- const minValue = rules.minExclusive ? rules.minValue + 1 : rules.minValue;
8
- schema = schema.min(minValue, msg.min(minValue));
25
+ if (min !== null) {
26
+ schema = schema.min(min, msg.min(min));
9
27
  }
10
- if (rules.maxValue !== null) {
11
- const maxValue = rules.maxExclusive ? rules.maxValue - 1 : rules.maxValue;
12
- schema = schema.max(maxValue, msg.max(maxValue));
28
+ if (max !== null) {
29
+ schema = schema.max(max, msg.max(max));
13
30
  }
14
31
  return schema;
15
32
  };
16
33
  export const minNumberValidationSchema = (rules) => {
17
34
  const msg = new ValidationLocalization();
35
+ const min = resolveMinBound(rules);
18
36
  let schema = yup.number().typeError(msg.badFormat).nullable();
19
- if (rules.minValue !== null) {
20
- const minValue = rules.minExclusive ? rules.minValue + 1 : rules.minValue;
21
- schema = schema.min(minValue, msg.min(minValue));
37
+ if (min !== null) {
38
+ schema = schema.min(min, msg.min(min));
22
39
  }
23
40
  return schema;
24
41
  };
@@ -1,4 +1,8 @@
1
1
  import type { TextValidation, TextWithFormatValidation } from './types';
2
2
  import * as yup from 'yup';
3
+ /** Value-level rules of `textValidationSchema`. Judges a real value — `null` / `undefined` are decided by the schema modifiers the caller adds. */
4
+ export declare const isValidText: (value: string, rules: TextValidation) => boolean;
5
+ /** Value-level rules of `formattedTextValidationSchema` — `isValidText` plus the format, which an empty value skips. */
6
+ export declare const isValidFormattedText: (value: string, rules: TextWithFormatValidation) => boolean;
3
7
  export declare const textValidationSchema: (rules: TextValidation) => yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
4
8
  export declare const formattedTextValidationSchema: (rules: TextWithFormatValidation, fieldName: string, formatMessage?: string) => yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
@@ -1,8 +1,17 @@
1
1
  import { ValidationLocalization } from './validation-localization';
2
2
  import * as yup from 'yup';
3
+ const isEmptyOrHasContent = (value) => !value || value.trim().length > 0;
4
+ /** Value-level rules of `textValidationSchema`. Judges a real value — `null` / `undefined` are decided by the schema modifiers the caller adds. */
5
+ export const isValidText = (value, rules) => {
6
+ return isEmptyOrHasContent(value) && value.length >= rules.minLength && value.length <= rules.maxLength;
7
+ };
8
+ /** Value-level rules of `formattedTextValidationSchema` — `isValidText` plus the format, which an empty value skips. */
9
+ export const isValidFormattedText = (value, rules) => {
10
+ return isValidText(value, rules) && (!value || new RegExp(rules.format).test(value));
11
+ };
3
12
  export const textValidationSchema = (rules) => {
4
13
  const msg = new ValidationLocalization();
5
- const schema = yup.string().max(rules.maxLength, msg.maxLength(rules.maxLength));
14
+ const schema = yup.string().test('whitespace-only', msg.whitespaceOnly, isEmptyOrHasContent).max(rules.maxLength, msg.maxLength(rules.maxLength));
6
15
  if (rules.minLength === 0) {
7
16
  return schema;
8
17
  }
@@ -1,3 +1,5 @@
1
1
  import type { UrlValidation } from './types';
2
2
  import * as yup from 'yup';
3
+ /** Value-level rules of `urlValidationSchema` — scheme / host check via `validateHref`, plus the optional length and required rules. */
4
+ export declare const isValidUrl: (value: string, rules?: UrlValidation) => boolean;
3
5
  export declare const urlValidationSchema: (rules?: UrlValidation) => yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
@@ -2,12 +2,25 @@ import { validateHref } from '../../utils';
2
2
  import { ValidationLocalization } from './validation-localization';
3
3
  import * as yup from 'yup';
4
4
  const DEFAULT_SCHEMES = new Set(['http:', 'https:']);
5
+ const resolveHrefOptions = (rules) => ({
6
+ allowedSchemes: rules.schemes ?? DEFAULT_SCHEMES,
7
+ requireNamedHost: rules.requireNamedHost ?? true,
8
+ allowLocalHosts: rules.allowLocalHosts ?? true
9
+ });
10
+ /** Value-level rules of `urlValidationSchema` — scheme / host check via `validateHref`, plus the optional length and required rules. */
11
+ export const isValidUrl = (value, rules = {}) => {
12
+ if (!value) {
13
+ return rules.required !== true;
14
+ }
15
+ if (!validateHref(value, resolveHrefOptions(rules)).valid) {
16
+ return false;
17
+ }
18
+ return rules.maxLength === undefined || value.length <= rules.maxLength;
19
+ };
5
20
  export const urlValidationSchema = (rules = {}) => {
6
21
  const msg = new ValidationLocalization();
7
- const allowedSchemes = rules.schemes ?? DEFAULT_SCHEMES;
8
- const requireNamedHost = rules.requireNamedHost ?? true;
9
- const allowLocalHosts = rules.allowLocalHosts ?? true;
10
- const schema = yup.string().test('url', msg.url, (value) => !value || validateHref(value, { allowedSchemes, requireNamedHost, allowLocalHosts }).valid);
22
+ const hrefOptions = resolveHrefOptions(rules);
23
+ const schema = yup.string().test('url', msg.url, (value) => !value || validateHref(value, hrefOptions).valid);
11
24
  const withMaxLength = rules.maxLength === undefined ? schema : schema.max(rules.maxLength, msg.maxLength(rules.maxLength));
12
25
  return rules.required ? withMaxLength.required(msg.required) : withMaxLength;
13
26
  };
@@ -7,6 +7,7 @@ export declare class ValidationLocalization {
7
7
  get max(): (val: number) => string;
8
8
  get minItems(): (count: number) => string;
9
9
  get maxItems(): (count: number) => string;
10
+ get whitespaceOnly(): string;
10
11
  get badFormat(): string;
11
12
  get url(): string;
12
13
  }
@@ -24,6 +24,9 @@ export class ValidationLocalization {
24
24
  get maxItems() {
25
25
  return loc.maxItems[AppLocale.current];
26
26
  }
27
+ get whitespaceOnly() {
28
+ return loc.whitespaceOnly[AppLocale.current];
29
+ }
27
30
  get badFormat() {
28
31
  return loc.badFormat[AppLocale.current];
29
32
  }
@@ -64,6 +67,10 @@ const loc = {
64
67
  en: (count) => `Must contain at most ${count} item${count === 1 ? '' : 's'}`,
65
68
  no: (count) => `Kan ikke inneholde mer enn ${count} element${count === 1 ? '' : 'er'}`
66
69
  },
70
+ whitespaceOnly: {
71
+ en: 'This field cannot contain only spaces',
72
+ no: 'Dette feltet kan ikke bestå av bare mellomrom'
73
+ },
67
74
  badFormat: {
68
75
  en: 'Invalid format',
69
76
  no: 'Ugyldig format'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamscloud/kit",
3
- "version": "0.42.1",
3
+ "version": "0.44.0",
4
4
  "author": "StreamsCloud",
5
5
  "repository": {
6
6
  "type": "git",