@arsedizioni/ars-utils 22.5.42 → 22.5.44

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.
@@ -662,20 +662,68 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
662
662
  }], propDecorators: { slots: [{ type: i0.Input, args: [{ isSignal: true, alias: "slots", required: false }] }] } });
663
663
 
664
664
  /**
665
- * Directive that validates that a string control value is not blank (whitespace-only).
666
- * Apply `notEmpty` to a text input where non-blank content is required.
665
+ * @file emptiness.ts
666
+ *
667
+ * The single definition of "empty" shared by the `notEmpty` / `requiredNotEmpty` rules, in both
668
+ * their flavours: the template-driven directives and the signal-form validators. It lives apart
669
+ * from either of them so that the two faces of the same rule cannot drift, and it pulls in
670
+ * nothing — not `@angular/forms`, not `@angular/core`.
671
+ */
672
+ /**
673
+ * Tells whether a value carries nothing at all.
674
+ *
675
+ * Nullish, the empty string and the empty array all count as missing; anything else does not,
676
+ * including `0` and `false`, which are legitimate values a form can hold.
677
+ *
678
+ * @param value - The value to inspect.
679
+ * @returns `true` when the value is absent, an empty string or an empty array.
680
+ */
681
+ function isMissingValue(value) {
682
+ if (value === undefined || value === null)
683
+ return true;
684
+ if (typeof value === 'string')
685
+ return value.length === 0;
686
+ if (Array.isArray(value))
687
+ return value.length === 0;
688
+ return false;
689
+ }
690
+ /**
691
+ * Tells whether a value is what the `notEmpty` rule rejects: a string made of whitespace alone,
692
+ * or an array with no elements.
693
+ *
694
+ * An absent value and an empty string are deliberately NOT rejected: declaring a field mandatory
695
+ * is the job of `required()` (or of `requiredNotEmpty`), and a blank field would otherwise raise
696
+ * two errors saying the same thing. The empty array is the one exception, because there it IS the
697
+ * only shape emptiness can take — a multi-select never holds `''`.
698
+ *
699
+ * @param value - The value to inspect.
700
+ * @returns `true` when the value is a whitespace-only string or an empty array.
701
+ */
702
+ function isBlankValue(value) {
703
+ if (Array.isArray(value))
704
+ return value.length === 0;
705
+ if (typeof value !== 'string')
706
+ return false;
707
+ return value.length > 0 && value.trim().length === 0;
708
+ }
709
+
710
+ /**
711
+ * Directive that validates that a control value is not blank: neither a whitespace-only string
712
+ * nor an empty array. Apply `notEmpty` to a text input where non-blank content is required, or
713
+ * to a multi-value control that must carry at least one entry.
714
+ *
715
+ * A value that is simply absent passes: saying "obbligatorio" is the job of `required`, or of
716
+ * `requiredNotEmpty` when both rules belong on the same control.
667
717
  */
668
718
  class NotEmptyValidatorDirective {
669
719
  /**
670
- * Validates that the control value is a non-blank string.
671
- * Returns `null` when the control is empty or not a string.
720
+ * Validates that the control value carries content.
721
+ * Returns `null` when the control is absent or holds a type this rule says nothing about.
672
722
  * @param control - The form control to validate.
723
+ * @returns `{ notEmpty: true }` when the value is a blank string or an empty array, `null` otherwise.
673
724
  */
674
725
  validate(control) {
675
- const input = control?.value;
676
- if (!input || typeof input !== 'string' || input.length === 0)
677
- return null;
678
- return input.trim().length > 0 ? null : { notEmpty: true };
726
+ return isBlankValue(control?.value) ? { notEmpty: true } : null;
679
727
  }
680
728
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: NotEmptyValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
681
729
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: NotEmptyValidatorDirective, isStandalone: true, selector: "[notEmpty]", providers: [
@@ -701,6 +749,52 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
701
749
  }]
702
750
  }] });
703
751
 
752
+ /**
753
+ * Directive that validates that a control carries actual content: present AND not blank.
754
+ * Apply `requiredNotEmpty` where `required notEmpty` would otherwise be spelled out together.
755
+ *
756
+ * It raises the very errors those two rules raise — `required` when the value is missing, an
757
+ * empty string or an empty array, `notEmpty` when a value is there but made of whitespace alone —
758
+ * so existing error messages and `getFieldErrorMessage` keep working untouched, and the user
759
+ * still reads "Obbligatorio" rather than the vaguer "Non può contenere solo spazi".
760
+ */
761
+ class RequiredNotEmptyValidatorDirective {
762
+ /**
763
+ * Validates that the control value is present and carries content.
764
+ * @param control - The form control to validate.
765
+ * @returns `{ required: true }` when nothing was entered, `{ notEmpty: true }` when the value
766
+ * is blank, `null` when the value is acceptable.
767
+ */
768
+ validate(control) {
769
+ const input = control?.value;
770
+ if (isMissingValue(input))
771
+ return { required: true };
772
+ return isBlankValue(input) ? { notEmpty: true } : null;
773
+ }
774
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: RequiredNotEmptyValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
775
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: RequiredNotEmptyValidatorDirective, isStandalone: true, selector: "[requiredNotEmpty]", providers: [
776
+ {
777
+ provide: NG_VALIDATORS,
778
+ useExisting: forwardRef(() => RequiredNotEmptyValidatorDirective),
779
+ multi: true,
780
+ },
781
+ ], ngImport: i0 }); }
782
+ }
783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: RequiredNotEmptyValidatorDirective, decorators: [{
784
+ type: Directive,
785
+ args: [{
786
+ selector: "[requiredNotEmpty]",
787
+ providers: [
788
+ {
789
+ provide: NG_VALIDATORS,
790
+ useExisting: forwardRef(() => RequiredNotEmptyValidatorDirective),
791
+ multi: true,
792
+ },
793
+ ],
794
+ standalone: true,
795
+ }]
796
+ }] });
797
+
704
798
  /**
705
799
  * Default texts of the rules declared here, in one place so that the validators and the fallback
706
800
  * map of `SignalsUtils.getFieldErrorMessage` cannot drift apart: a rule added below without a
@@ -717,6 +811,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
717
811
  */
718
812
  const MIN_VALID_YEAR = 1970;
719
813
  const ARS_VALIDATOR_MESSAGES = {
814
+ // Produced by the Angular built-in `required()` and by {@link requiredNotEmpty}. It sits here,
815
+ // and no longer among the built-in fallbacks below, so that the text exists exactly once.
816
+ required: 'Obbligatorio',
720
817
  guid: 'Ticket non riconosciuto',
721
818
  password: 'Password non sufficientemente robusta',
722
819
  notEmpty: 'Non può contenere solo spazi',
@@ -780,12 +877,13 @@ function password(path, config) {
780
877
  });
781
878
  }
782
879
  /**
783
- * Requires the value not to be made of whitespace alone.
880
+ * Requires the value not to be made of whitespace alone, and a collection not to be empty.
784
881
  *
785
- * The signal-form counterpart of `NotEmptyValidatorDirective`, with its exact semantics: an empty
786
- * value passes. That is not an oversight saying "obbligatorio" belongs to `required()`, and a
787
- * field that is merely blank would otherwise raise two errors that mean the same thing. Pair the
788
- * two when a field must be both present and non-blank.
882
+ * The signal-form counterpart of `NotEmptyValidatorDirective`, sharing its predicate through
883
+ * {@link isBlankValue}: a blank string and an empty array are errors, an absent value is not.
884
+ * That last part is not an oversight saying "obbligatorio" belongs to `required()`, and a field
885
+ * that is merely blank would otherwise raise two errors that mean the same thing. Pair the two,
886
+ * or reach for {@link requiredNotEmpty}, when a field must be both present and non-blank.
789
887
  *
790
888
  * Replaces the `pattern(p.x, /\S/)` workaround: same rule, but the intent is in the name and the
791
889
  * error kind is `notEmpty` rather than `pattern`.
@@ -795,17 +893,47 @@ function password(path, config) {
795
893
  * @returns void
796
894
  * @example
797
895
  * const f = form(this.model, p => { required(p.city); notEmpty(p.city); });
896
+ * @example
897
+ * const f = form(this.model, p => { notEmpty(p.tags); }); // at least one tag
798
898
  */
799
899
  function notEmpty(path, config) {
800
900
  validate(path, ctx => {
801
901
  if (config?.when && !config.when(ctx))
802
902
  return null;
803
- const input = ctx.value();
804
- if (!input || typeof input !== 'string' || input.length === 0)
903
+ return isBlankValue(ctx.value())
904
+ ? { kind: 'notEmpty', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notEmpty'] }
905
+ : null;
906
+ });
907
+ }
908
+ /**
909
+ * Requires the value to be both present and made of something: the two rules a mandatory text
910
+ * field almost always needs together, declared once.
911
+ *
912
+ * The signal-form counterpart of `RequiredNotEmptyValidatorDirective`. It raises the errors the
913
+ * two rules raise on their own rather than a kind of its own — `required` when nothing was
914
+ * entered (nullish, empty string, empty array), `notEmpty` when a value is there but blank — so
915
+ * the message stays as precise as it was and nothing downstream needs to learn a new kind.
916
+ *
917
+ * Not a wrapper around Angular's `required()`: that one would have to be declared on the same
918
+ * path anyway, and the pair would then report two errors on an empty field.
919
+ *
920
+ * @param path - Path of the field to validate.
921
+ * @param config - Optional message override, applied to whichever of the two errors is raised.
922
+ * @returns void
923
+ * @example
924
+ * const f = form(this.model, p => { requiredNotEmpty(p.city); });
925
+ */
926
+ function requiredNotEmpty(path, config) {
927
+ validate(path, ctx => {
928
+ if (config?.when && !config.when(ctx))
805
929
  return null;
806
- return input.trim().length > 0
807
- ? null
808
- : { kind: 'notEmpty', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notEmpty'] };
930
+ const input = ctx.value();
931
+ if (isMissingValue(input)) {
932
+ return { kind: 'required', message: config?.message ?? ARS_VALIDATOR_MESSAGES['required'] };
933
+ }
934
+ return isBlankValue(input)
935
+ ? { kind: 'notEmpty', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notEmpty'] }
936
+ : null;
809
937
  });
810
938
  }
811
939
  /**
@@ -1214,7 +1342,6 @@ class SignalsUtils {
1214
1342
  return undefined;
1215
1343
  const fallback = {
1216
1344
  // Angular built-ins declared without a message of their own.
1217
- required: 'Obbligatorio',
1218
1345
  min: 'Valore troppo basso',
1219
1346
  max: 'Valore troppo alto',
1220
1347
  minLength: 'Testo troppo corto',
@@ -1255,5 +1382,5 @@ class SignalsUtils {
1255
1382
  * Generated bundle index. Do not edit.
1256
1383
  */
1257
1384
 
1258
- export { ARS_VALIDATOR_MESSAGES, EmailsValidatorDirective, EqualsValidatorDirective, FileSizeValidatorDirective, GuidValidatorDirective, MIN_VALID_YEAR, MaxTermsValidatorDirective, NotEmptyValidatorDirective, NotEqualValidatorDirective, NotFutureValidatorDirective, PasswordValidatorDirective, SignalsUtils, SqlDateValidatorDirective, TimeValidatorDirective, UrlValidatorDirective, ValidIfDirective, ValidatorDirective, date, dateRange, emails, equals, fileSize, guid, maxTerms, notEmpty, notEqual, notFuture, otp, password, sqlDate, time, url, validIf };
1385
+ export { ARS_VALIDATOR_MESSAGES, EmailsValidatorDirective, EqualsValidatorDirective, FileSizeValidatorDirective, GuidValidatorDirective, MIN_VALID_YEAR, MaxTermsValidatorDirective, NotEmptyValidatorDirective, NotEqualValidatorDirective, NotFutureValidatorDirective, PasswordValidatorDirective, RequiredNotEmptyValidatorDirective, SignalsUtils, SqlDateValidatorDirective, TimeValidatorDirective, UrlValidatorDirective, ValidIfDirective, ValidatorDirective, date, dateRange, emails, equals, fileSize, guid, maxTerms, notEmpty, notEqual, notFuture, otp, password, requiredNotEmpty, sqlDate, time, url, validIf };
1259
1386
  //# sourceMappingURL=arsedizioni-ars-utils-core.validators.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"arsedizioni-ars-utils-core.validators.mjs","sources":["../../../projects/ars-utils/core.validators/validatorDirective.ts","../../../projects/ars-utils/core.validators/validIfDirective.ts","../../../projects/ars-utils/core.validators/equalsValidatorDirective.ts","../../../projects/ars-utils/core.validators/notEqualValidatorDirective.ts","../../../projects/ars-utils/core.validators/emailsValidatorDirective.ts","../../../projects/ars-utils/core.validators/guidValidatorDirective.ts","../../../projects/ars-utils/core.validators/sqlDateValidatorDirective.ts","../../../projects/ars-utils/core.validators/notFutureValidatorDirective.ts","../../../projects/ars-utils/core.validators/urlValidatorDirective.ts","../../../projects/ars-utils/core.validators/fileSizeValidatorDirective.ts","../../../projects/ars-utils/core.validators/maxTermsValidatorDirective.ts","../../../projects/ars-utils/core.validators/passwordValidatorDirective.ts","../../../projects/ars-utils/core.validators/timeValidatorDirective.ts","../../../projects/ars-utils/core.validators/notEmptyValidatorDirective.ts","../../../projects/ars-utils/core.validators/signals.ts","../../../projects/ars-utils/core.validators/public_api.ts","../../../projects/ars-utils/core.validators/arsedizioni-ars-utils-core.validators.ts"],"sourcesContent":["import { Directive, input } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\n\r\n/**\r\n * Directive that delegates validation to an externally provided validator function.\r\n * Bind `[validator]=\"myFn\"` where `myFn` is `(c: AbstractControl) => ValidationErrors | null`.\r\n */\r\n@Directive({\r\n selector: '[validator]',\r\n providers: [{ provide: NG_VALIDATORS, useExisting: ValidatorDirective, multi: true }],\r\n standalone: true,\r\n})\r\nexport class ValidatorDirective implements Validator {\r\n\r\n /** The custom validator function to apply. */\r\n readonly validator = input<((control: AbstractControl) => ValidationErrors | null) | undefined>(undefined);\r\n\r\n /**\r\n * Invokes the provided validator function against the given control.\r\n * Returns `null` (valid) when no function is bound.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const fn = this.validator();\r\n return fn ? fn(control) : null;\r\n }\r\n}\r\n","import { Directive, forwardRef, input } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\nimport { Validated } from '@arsedizioni/ars-utils/core';\r\n\r\n/**\r\n * Directive that validates a control using the host object's `isValid()` method\r\n * or a boolean expression passed via `[validIf]`.\r\n */\r\n@Directive({\r\n selector: \"[validIf]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => ValidIfDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class ValidIfDirective implements Validator {\r\n\r\n /** When `true`, the control is considered valid regardless of the bound value. */\r\n readonly validIf = input<boolean>(false);\r\n\r\n /**\r\n * Validates the control value against a boolean flag or the value's own `isValid()` method.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n let isValid = false;\r\n const c = control.value ? (control.value as Validated) : null;\r\n if (!c) {\r\n isValid = this.validIf() === true;\r\n } else {\r\n try {\r\n isValid = c.isValid();\r\n } catch { }\r\n }\r\n return isValid ? null : { validIf: \"Non valido.\" };\r\n }\r\n}\r\n","import { DestroyRef, Directive, effect, forwardRef, inject, input } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\nimport { Subscription } from \"rxjs\";\n\n/**\n * Directive that validates that the host control's value equals the value of another control.\n * Bind `[equals]=\"otherControl\"`.\n *\n * The host control is re-validated whenever the OTHER control's value changes:\n * without this, typing a new password AFTER the confirmation field was filled\n * left the form incorrectly valid (the classic password/confirm bug).\n *\n * IMPORTANT (reciprocal-binding safety): the re-validation triggered from the\n * other control's `valueChanges` runs with `{ emitEvent: false }`. Calling\n * Angular's `onValidatorChange` instead would re-emit valueChanges, so a\n * reciprocal setup (A [equals]=B and B [equals]=A) would overflow the stack.\n */\n@Directive({\n selector: \"[equals]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => EqualsValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class EqualsValidatorDirective implements Validator {\n\n /** The control whose value must match the host control's value. */\n readonly equals = input<AbstractControl | undefined>(undefined);\n\n /** The host control, captured on the first validate() call. */\n private hostControl?: AbstractControl;\n\n /** Subscription to the other control's valueChanges. */\n private subscription?: Subscription;\n\n constructor() {\n // Re-subscribe whenever the [equals] binding points to a different control,\n // and re-validate the host on every change of the other control.\n effect(() => {\n const other = this.equals();\n this.subscription?.unsubscribe();\n this.subscription = other?.valueChanges.subscribe(() =>\n // emitEvent:false breaks the reciprocal valueChanges loop (see class doc).\n this.hostControl?.updateValueAndValidity({ emitEvent: false })\n );\n // Re-validate the host when the bound control itself is swapped.\n this.hostControl?.updateValueAndValidity({ emitEvent: false });\n });\n inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());\n }\n\n /**\n * Validates that the host control value equals the bound control's value.\n * Returns `null` (valid) when no control is bound.\n * @param control - The form control to validate.\n * @returns `null` when valid, `{ equals: ... }` otherwise.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n this.hostControl = control;\n const eq = this.equals();\n if (!eq) return null;\n return eq.value === control.value ? null : { equals: \"Non valido.\" };\n }\n}\n","import { DestroyRef, Directive, effect, forwardRef, inject, input } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\nimport { Subscription } from \"rxjs\";\n\n/**\n * Directive that validates that the host control's value is different from another control's value.\n * Bind `[notEqual]=\"otherControl\"`.\n *\n * The host control is re-validated whenever the OTHER control's value changes,\n * so editing either field keeps both error states consistent.\n *\n * IMPORTANT (reciprocal-binding safety): the re-validation triggered from the\n * other control's `valueChanges` is run with `{ emitEvent: false }`. Using\n * Angular's `onValidatorChange` here instead would call `host.updateValueAndValidity()`\n * WITH events, so a reciprocal setup (A [notEqual]=B and B [notEqual]=A) would\n * ping-pong valueChanges between the two controls and overflow the stack.\n */\n@Directive({\n selector: \"[notEqual]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => NotEqualValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class NotEqualValidatorDirective implements Validator {\n\n /** The control whose value must differ from the host control's value. */\n readonly notEqual = input<AbstractControl | undefined>(undefined);\n\n /** The host control, captured on the first validate() call. */\n private hostControl?: AbstractControl;\n\n /** Subscription to the other control's valueChanges. */\n private subscription?: Subscription;\n\n constructor() {\n effect(() => {\n const other = this.notEqual();\n this.subscription?.unsubscribe();\n this.subscription = other?.valueChanges.subscribe(() =>\n // Re-validate the host WITHOUT emitting valueChanges, otherwise a\n // reciprocal binding would loop forever (see class doc).\n this.hostControl?.updateValueAndValidity({ emitEvent: false })\n );\n // Re-validate the host when the bound control itself is swapped.\n this.hostControl?.updateValueAndValidity({ emitEvent: false });\n });\n inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());\n }\n\n /**\n * Validates that the host control value is not equal to the bound control's value.\n * Also clears the `notequal` error on the other control when the host becomes valid.\n * Returns `null` (valid) when no control is bound.\n * @param control - The form control to validate.\n * @returns `null` when valid, `{ notequal: true }` otherwise.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n this.hostControl = control;\n\n const notEqual = this.notEqual();\n if (!notEqual) return null;\n\n const isValid = (!notEqual.value && !control.value) || (notEqual.value !== control.value);\n const errors: ValidationErrors | null = isValid ? null : { notequal: true };\n\n if (errors) {\n control.markAsTouched();\n } else if (notEqual.hasError('notequal')) {\n const { notequal: _removed, ...rest } = notEqual.errors ?? {};\n // emitEvent:false on both: clearing the partner's error must not feed\n // back through valueChanges/statusChanges into this validator.\n notEqual.setErrors(Object.keys(rest).length > 0 ? rest : null, { emitEvent: false });\n notEqual.updateValueAndValidity({ onlySelf: true, emitEvent: false });\n notEqual.markAsTouched();\n notEqual.markAsDirty();\n }\n return errors;\n }\n}\n","import { Directive, forwardRef } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\r\n\r\n/**\r\n * Directive that validates a semicolon-separated list of email addresses.\r\n * Apply `emails` to a text input containing one or more addresses separated by `;`.\r\n */\r\n@Directive({\r\n selector: \"[emails]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => EmailsValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class EmailsValidatorDirective implements Validator {\r\n\r\n /**\r\n * Validates each address in a semicolon-separated email list.\r\n * Returns `null` when the control is empty.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input: string = control.value;\r\n if (!input || input.length === 0) return null;\r\n const parts = input.replaceAll(/\\r\\n/g, '').split(';');\r\n const isValid = parts.every(part => part.length === 0 || !!SystemUtils.parseEmail(part));\r\n return isValid ? null : { emails: \"Elenco non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\r\n\r\n/**\r\n * Directive that validates a control value as a GUID / UUID string.\r\n * Apply `guid` to a text input that expects a valid UUID.\r\n */\r\n@Directive({\r\n selector: \"[guid]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => GuidValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class GuidValidatorDirective implements Validator {\r\n\r\n /**\r\n * Validates that the control value is a well-formed GUID / UUID.\r\n * Returns `null` when the control is empty.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input: string = control.value;\r\n if (!input || input.length === 0) return null;\r\n return SystemUtils.parseUUID(input) ? null : { guid: \"Non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\nimport { endOfDay } from 'date-fns';\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\n\n/**\n * Directive that validates a control value as a parseable SQL-compatible date string.\n * Apply `sqlDate` to a text input that expects a date after year 1750.\n */\n@Directive({\n selector: \"[sqlDate]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => SqlDateValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class SqlDateValidatorDirective implements Validator {\n\n /**\n * Validates that the control value can be parsed as a date after 1750.\n * Returns `null` when the control is empty.\n * @param control - The form control to validate.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n const input: string = control.value;\n if (!input || input.length === 0) return null;\n const parsed = SystemUtils.parseDate(input);\n if (!parsed) return { sqlDate: \"Non valido.\" };\n const d = endOfDay(parsed);\n return d.getFullYear() > 1750 ? null : { sqlDate: \"Non valido.\" };\n }\n}\n","import { Directive, forwardRef } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\nimport { endOfDay } from 'date-fns';\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\n\n/**\n * Directive that validates that a control value is not a future date.\n * Apply `notFuture` to a text input that expects a date on or before today.\n */\n@Directive({\n selector: \"[notFuture]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => NotFutureValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class NotFutureValidatorDirective implements Validator {\n\n /**\n * Validates that the control value represents a date that is not in the future.\n * Returns `null` when the control is empty.\n * @param control - The form control to validate.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n const input: string = control.value;\n if (!input || input.length === 0) return null;\n const parsed = SystemUtils.parseDate(input);\n if (!parsed) return { notFuture: \"Non valido.\" };\n const today = endOfDay(new Date());\n const d = endOfDay(parsed);\n return d <= today ? null : { notFuture: \"Non valido.\" };\n }\n}\n","import { Directive, forwardRef } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\r\n\r\n/**\r\n * Directive that validates a control value as a well-formed URL.\r\n * Apply `url` to a text input that expects a URL.\r\n */\r\n@Directive({\r\n selector: \"[url]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => UrlValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class UrlValidatorDirective implements Validator {\r\n\r\n /**\r\n * Validates that the control value is a well-formed URL.\r\n * Returns `null` (valid) when the control is empty.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input: string = control.value;\r\n if (!input || input.length === 0) return null;\r\n return SystemUtils.parseUrl(input) ? null : { url: \"Non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef, input } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\n\r\n/**\r\n * Directive that validates a file size against configurable minimum and maximum bounds.\r\n * Bind `[fileSize]` together with `[size]=\"fileSizeInMb\"`, `[maxSizeMb]`, and `[minSizeMb]`.\r\n */\r\n@Directive({\r\n selector: \"[fileSize]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => FileSizeValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class FileSizeValidatorDirective implements Validator {\r\n\r\n /** Maximum allowed file size in megabytes. Defaults to 5. */\r\n readonly maxSizeMb = input<number>(5);\r\n\r\n /** Minimum required file size in megabytes. Defaults to 0. */\r\n readonly minSizeMb = input<number>(0);\r\n\r\n /** The actual file size in megabytes to validate against the bounds. */\r\n readonly size = input<number | undefined>(undefined);\r\n\r\n /**\r\n * Validates that the bound file size falls within the configured min/max range.\r\n * Returns `null` when no control value is present.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input = control.value;\r\n if (!input) return null;\r\n const s = this.size() ?? 0;\r\n const isValid = s <= this.maxSizeMb() && s >= this.minSizeMb();\r\n return isValid ? null : { fileSize: \"Non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef, input } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\n\r\n/**\r\n * Directive that validates that a control value does not exceed a maximum word count.\r\n * Bind `[maxTerms]=\"10\"` to allow at most 10 whitespace-separated terms.\r\n */\r\n@Directive({\r\n selector: \"[maxTerms]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => MaxTermsValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class MaxTermsValidatorDirective implements Validator {\r\n\r\n /** The maximum number of whitespace-separated terms allowed. */\r\n readonly maxTerms = input<number>(0);\r\n\r\n /**\r\n * Validates that the control value contains no more than the configured number of terms.\r\n * Returns `null` when the control is empty.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input: string = control.value;\r\n if (!input) return null;\r\n const terms = input.match(/\\S+/g)?.length ?? 0;\r\n return terms <= this.maxTerms() ? null : { maxTerms: \"Non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\r\n\r\n/**\r\n * Directive that validates a control value as a sufficiently strong password.\r\n * Apply `password` to a password input.\r\n */\r\n@Directive({\r\n selector: \"[password]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => PasswordValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class PasswordValidatorDirective implements Validator {\r\n\r\n /**\r\n * Validates that the control value meets the minimum password-strength requirements.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input: string = control.value ?? '';\r\n const strength = SystemUtils.calculatePasswordStrength(input);\r\n return strength.isValid ? null : { password: \"Non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef, input } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\n\n/**\n * Directive that validates a time string against optional allowed time slot ranges.\n * Bind `[time]` and optionally `[slots]=\"'08:00-12:00|14:00-18:00'\"` (pipe-separated ranges).\n */\n@Directive({\n selector: \"[time]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => TimeValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class TimeValidatorDirective implements Validator {\n\n /** Optional pipe-separated list of allowed time ranges, e.g. `\"08:00-12:00|14:00-18:00\"`. */\n readonly slots = input<string | undefined>(undefined);\n\n /**\n * Parses a `\"HH:MM\"` time string into a comparable integer (e.g. `\"09:30\"` -> `930`).\n * Returns `-1` when the string is not a valid time.\n * @param value - The time string to parse.\n */\n private getTime(value: string): number {\n const p = value.split(':');\n if (p.length !== 2) return -1;\n const hh = parseInt(p[0], 10);\n if (isNaN(hh) || hh < 0 || hh > 23) return -1;\n const mm = parseInt(p[1], 10);\n if (isNaN(mm) || mm < 0 || mm > 59) return -1;\n return hh * 100 + mm;\n }\n\n /**\n * Validates that the control value is a valid time string and, when slots are configured,\n * that it falls within at least one of the allowed ranges.\n * Returns `null` when the control is empty.\n * @param control - The form control to validate.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n const input: string = control.value;\n if (!input || input.length === 0) return null;\n\n const t = this.getTime(input);\n if (t === -1) return { time: \"Non valido.\" };\n\n const slotsValue = this.slots();\n if (slotsValue) {\n const isValid = slotsValue.split('|').some(s => {\n const t1 = this.getTime(s.substring(0, 5));\n const t2 = this.getTime(s.substring(6));\n return t1 !== -1 && t2 !== -1 && t1 <= t && t2 >= t;\n });\n return isValid ? null : { time: \"Non valido.\" };\n }\n\n return null;\n }\n}\n","import { Directive, forwardRef } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\n\r\n/**\r\n * Directive that validates that a string control value is not blank (whitespace-only).\r\n * Apply `notEmpty` to a text input where non-blank content is required.\r\n */\r\n@Directive({\r\n selector: \"[notEmpty]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => NotEmptyValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class NotEmptyValidatorDirective implements Validator {\r\n\r\n /**\r\n * Validates that the control value is a non-blank string.\r\n * Returns `null` when the control is empty or not a string.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input = control?.value;\r\n if (!input || typeof input !== 'string' || input.length === 0) return null;\r\n return input.trim().length > 0 ? null : { notEmpty: true };\r\n }\r\n}\r\n","import { LogicFn, PathKind, SchemaPath, SchemaPathRules, validate } from '@angular/forms/signals';\r\nimport { SystemUtils, Validated } from '@arsedizioni/ars-utils/core';\r\nimport { endOfDay } from 'date-fns';\r\n\r\n/**\r\n * Options shared by the ARS signal-form validators.\r\n *\r\n * Mirrors the `config` argument of the Angular built-ins (`required`, `email`, ...) but carries\r\n * only what these validators need: the message shown to the user in place of the default one.\r\n */\r\nexport interface ArsValidatorConfig<TValue = string, TPathKind extends PathKind = PathKind.Root> {\r\n /** Message attached to the error, in place of the default Italian text. */\r\n message?: string;\r\n /**\r\n * Applies the rule only while this returns `true`, exactly like the `when` of `required()`\r\n * and of the other Angular built-ins.\r\n *\r\n * It exists because these validators are meant to be paired with `required()` on the same\r\n * field, and a field that is only required in one mode of a dialog must only be validated in\r\n * that mode: without this, a leftover value would keep a form invalid in a mode where the\r\n * field is not even shown.\r\n */\r\n when?: NoInfer<LogicFn<TValue, boolean, TPathKind>>;\r\n}\r\n\r\n/**\r\n * Default texts of the rules declared here, in one place so that the validators and the fallback\r\n * map of `SignalsUtils.getFieldErrorMessage` cannot drift apart: a rule added below without a\r\n * message here would show \"Errore\", and one renamed here without touching the validator would\r\n * leave the map with a kind nobody produces.\r\n */\r\n/**\r\n * Earliest date {@link date} and {@link dateRange} accept: 1 January 1970.\r\n *\r\n * Everything this application stores — events, certificates, payments, communications — happened\r\n * after it, so an earlier value is always a typo (a two-digit year, a slipped keystroke) and never\r\n * real data. The floor is deliberately higher than the one of {@link sqlDate}, which only asks\r\n * what SQL Server can physically store.\r\n */\r\nexport const MIN_VALID_YEAR = 1970;\r\n\r\nexport const ARS_VALIDATOR_MESSAGES: Record<string, string> = {\r\n guid: 'Ticket non riconosciuto',\r\n password: 'Password non sufficientemente robusta',\r\n notEmpty: 'Non può contenere solo spazi',\r\n notEqual: 'Deve essere diverso dall\\'altro valore',\r\n sqlDate: 'Data non valida',\r\n date: 'Data non valida',\r\n dateRange: 'Intervallo non valido',\r\n notFuture: 'La data non può essere futura',\r\n url: 'Indirizzo non valido',\r\n maxTerms: 'Troppe parole',\r\n fileSize: 'Dimensione del file non ammessa',\r\n validIf: 'Non valido',\r\n emails: 'Elenco non valido',\r\n time: 'Orario non valido',\r\n equals: 'I due valori non coincidono',\r\n otp: 'Codice non valido',\r\n};\r\n\r\n/**\r\n * Requires the value to be a well-formed GUID / UUID.\r\n *\r\n * The signal-form counterpart of `GuidValidatorDirective`, sharing its rule down to the empty\r\n * case: an empty value is NOT an error here, because saying \"obbligatorio\" is the job of\r\n * `required()` and two errors on one empty field only ever read as noise.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param config - Optional message override.\r\n * @returns void\r\n * @example\r\n * const f = form(this.model, p => { required(p.serial); guid(p.serial); });\r\n */\r\nexport function guid<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const input = ctx.value();\r\n if (!input || input.length === 0) return null;\r\n return SystemUtils.parseUUID(input)\r\n ? null\r\n : { kind: 'guid', message: config?.message ?? ARS_VALIDATOR_MESSAGES['guid'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to be a password strong enough for {@link SystemUtils.calculatePasswordStrength}.\r\n *\r\n * The signal-form counterpart of `PasswordValidatorDirective`. Unlike {@link guid} it does judge\r\n * the empty value, because an empty password IS a weak one and the directive behaved the same way.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param config - Optional message override.\r\n * @returns void\r\n */\r\nexport function password<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const strength = SystemUtils.calculatePasswordStrength(ctx.value() ?? '');\r\n return strength.isValid\r\n ? null\r\n : { kind: 'password', message: config?.message ?? ARS_VALIDATOR_MESSAGES['password'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value not to be made of whitespace alone.\r\n *\r\n * The signal-form counterpart of `NotEmptyValidatorDirective`, with its exact semantics: an empty\r\n * value passes. That is not an oversight — saying \"obbligatorio\" belongs to `required()`, and a\r\n * field that is merely blank would otherwise raise two errors that mean the same thing. Pair the\r\n * two when a field must be both present and non-blank.\r\n *\r\n * Replaces the `pattern(p.x, /\\S/)` workaround: same rule, but the intent is in the name and the\r\n * error kind is `notEmpty` rather than `pattern`.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param config - Optional message override.\r\n * @returns void\r\n * @example\r\n * const f = form(this.model, p => { required(p.city); notEmpty(p.city); });\r\n */\r\nexport function notEmpty<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const input = ctx.value();\r\n if (!input || typeof input !== 'string' || input.length === 0) return null;\r\n return input.trim().length > 0\r\n ? null\r\n : { kind: 'notEmpty', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notEmpty'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to differ from the value of another field of the same form.\r\n *\r\n * The signal-form counterpart of `NotEqualValidatorDirective`, with its exact rule: two empty\r\n * values are considered different, so an untouched pair of fields does not start out in error.\r\n * Reactive on both fields — editing either one re-validates this one, which is what the\r\n * directive needed a `valueChanges` subscription (and a re-entrancy guard) to achieve.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param other - Path of the field whose value must differ.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function notEqual<TValue, TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\r\n other: SchemaPath<TValue, SchemaPathRules.Supported>,\r\n config?: ArsValidatorConfig<TValue, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const mine = ctx.value();\r\n const theirs = ctx.valueOf(other);\r\n const isValid = (!theirs && !mine) || theirs !== mine;\r\n return isValid ? null : { kind: 'notEqual', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notEqual'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to be a date the backend can store: parseable, and after 1750.\r\n *\r\n * The signal-form counterpart of `SqlDateValidatorDirective`. The year floor is not arbitrary —\r\n * it is what separates a real date from the 01/01/0001 that a mistyped year produces, which SQL\r\n * Server rejects with an error nobody can read.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function sqlDate<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const input = ctx.value();\r\n if (!input || input.length === 0) return null;\r\n const parsed = SystemUtils.parseDate(input);\r\n const invalid = { kind: 'sqlDate', message: config?.message ?? ARS_VALIDATOR_MESSAGES['sqlDate'] };\r\n if (!parsed) return invalid;\r\n return endOfDay(parsed).getFullYear() > 1750 ? null : invalid;\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to be a real date, as {@link SystemUtils.parseDate} understands one.\r\n *\r\n * This is the rule for anything a user picks or types as a date: it accepts both the `Date` a\r\n * Material datepicker or timepicker writes into the model and the text of a plain input, since\r\n * `parseDate` handles the shapes this codebase produces (ISO, `dd/MM/yyyy`, `yyyy-MM-dd`, and the\r\n * shorthand forms). Empty passes — saying \"obbligatorio\" is the job of `required()`.\r\n *\r\n * A date earlier than {@link MIN_VALID_YEAR} (1 January 1970) is rejected: nothing this\r\n * application stores predates it, so an earlier value is a typo rather than data.\r\n *\r\n * Distinct from {@link sqlDate} on purpose: that one is about what the DATABASE can store (the\r\n * 1750 floor), this one is about whether the value is a date at all. Pair them when both matter.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n * @example\r\n * const f = form(this.model, p => { required(p.expiry); date(p.expiry); });\r\n */\r\nexport function date<TValue extends string | Date | null | undefined,\r\n TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\r\n config?: ArsValidatorConfig<TValue, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const input = ctx.value();\r\n if (input === undefined || input === null || input === '') return null;\r\n const parsed = SystemUtils.parseDate(input);\r\n return parsed && parsed.getFullYear() >= MIN_VALID_YEAR\r\n ? null\r\n : { kind: 'date', message: config?.message ?? ARS_VALIDATOR_MESSAGES['date'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the two ends of a date range to be real dates and to be in order.\r\n *\r\n * Written for the two inputs of a `mat-date-range-input`, whose start and end live in two\r\n * separate fields of the model. Each end is checked with the same rule as {@link date}, and the\r\n * ordering is checked only when BOTH ends are filled in — a half-open range (\"from today\r\n * onwards\") is a legitimate filter, not an error. The 1 January 1970 floor of {@link date}\r\n * applies to both ends.\r\n *\r\n * The rule is bound to BOTH paths, so the error appears on whichever end the user is looking at\r\n * and a single `<mat-error>` under the range can read either one. Comparison is made on the end\r\n * of the day, so picking the same day for both ends is valid.\r\n *\r\n * @param from - Path of the field holding the start of the range.\r\n * @param to - Path of the field holding the end of the range.\r\n * @param config - Optional message override (used for the ordering error) and `when` condition.\r\n * @returns void\r\n * @example\r\n * const f = form(this.model, p => { dateRange(p.sentFrom, p.sentTo); });\r\n */\r\nexport function dateRange<TValue extends string | Date | null | undefined,\r\n TPathKind extends PathKind = PathKind.Root>(\r\n from: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\r\n to: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\r\n config?: ArsValidatorConfig<TValue, TPathKind>\r\n): void {\r\n date(from, config);\r\n date(to, config);\r\n\r\n /**\r\n * Compares the two ends of the range once both of them are filled in.\r\n * @param startValue - Raw value of the start field.\r\n * @param endValue - Raw value of the end field.\r\n * @returns The ordering error, or `null` when the pair is acceptable.\r\n */\r\n const checkOrder = (startValue: TValue, endValue: TValue) => {\r\n const start = SystemUtils.parseDate(startValue ?? undefined);\r\n const end = SystemUtils.parseDate(endValue ?? undefined);\r\n // A half-open range is legitimate: nothing to compare until both ends are there. An end that\r\n // is not a valid date is already reported by the `date` rule bound above, so it is skipped\r\n // here rather than reported twice.\r\n if (!start || !end) return null;\r\n if (start.getFullYear() < MIN_VALID_YEAR || end.getFullYear() < MIN_VALID_YEAR) return null;\r\n return endOfDay(start) <= endOfDay(end)\r\n ? null\r\n : { kind: 'dateRange', message: config?.message ?? ARS_VALIDATOR_MESSAGES['dateRange'] };\r\n };\r\n\r\n // Reading the opposite end through `valueOf` keeps each rule reactive on the other field, so\r\n // filling in one end re-validates the other.\r\n validate(from, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n return checkOrder(ctx.value(), ctx.valueOf(to));\r\n });\r\n validate(to, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n return checkOrder(ctx.valueOf(from), ctx.value());\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to be a date that is not in the future.\r\n *\r\n * The signal-form counterpart of `NotFutureValidatorDirective`. Today counts as valid: the\r\n * comparison is made on the end of the day, so a date entered this morning does not become\r\n * invalid because the clock says 09:00.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function notFuture<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const input = ctx.value();\r\n if (!input || input.length === 0) return null;\r\n const parsed = SystemUtils.parseDate(input);\r\n const invalid = { kind: 'notFuture', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notFuture'] };\r\n if (!parsed) return invalid;\r\n return endOfDay(parsed) <= endOfDay(new Date()) ? null : invalid;\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to be a well-formed URL. An empty value passes, as everywhere else here.\r\n *\r\n * The signal-form counterpart of `UrlValidatorDirective`.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function url<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const input = ctx.value();\r\n if (!input || input.length === 0) return null;\r\n return SystemUtils.parseUrl(input)\r\n ? null\r\n : { kind: 'url', message: config?.message ?? ARS_VALIDATOR_MESSAGES['url'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to hold no more than `max` whitespace-separated terms.\r\n *\r\n * The signal-form counterpart of `MaxTermsValidatorDirective`, used on the search boxes where\r\n * the backend refuses a query past a certain number of words.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param max - The maximum number of terms, as a number or a reactive function.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function maxTerms<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n max: number | (() => number),\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const input = ctx.value();\r\n if (!input) return null;\r\n const terms = input.match(/\\S+/g)?.length ?? 0;\r\n return terms <= (typeof max === 'function' ? max() : max)\r\n ? null\r\n : { kind: 'maxTerms', message: config?.message ?? ARS_VALIDATOR_MESSAGES['maxTerms'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the size of the picked file to fall within the allowed range.\r\n *\r\n * The signal-form counterpart of `FileSizeValidatorDirective`, and it keeps its shape: the field\r\n * itself holds the file NAME, while the size arrives from outside — the control that picked the\r\n * file knows it, the form does not. An empty field passes, so \"no file\" is `required()`'s call\r\n * and not a size error.\r\n *\r\n * @param path - Path of the field holding the file name.\r\n * @param sizeMb - The size of the picked file in megabytes, as a reactive function.\r\n * @param maxSizeMb - The maximum allowed size in megabytes. Defaults to `5`.\r\n * @param minSizeMb - The minimum required size in megabytes. Defaults to `0`.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function fileSize<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n sizeMb: () => number | undefined,\r\n maxSizeMb: number | (() => number) = 5,\r\n minSizeMb: number | (() => number) = 0,\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n if (!ctx.value()) return null;\r\n const size = sizeMb() ?? 0;\r\n const max = typeof maxSizeMb === 'function' ? maxSizeMb() : maxSizeMb;\r\n const min = typeof minSizeMb === 'function' ? minSizeMb() : minSizeMb;\r\n return size <= max && size >= min\r\n ? null\r\n : { kind: 'fileSize', message: config?.message ?? ARS_VALIDATOR_MESSAGES['fileSize'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to declare itself valid.\r\n *\r\n * The signal-form counterpart of `ValidIfDirective`: when the field holds an object implementing\r\n * `Validated` the verdict is its own `isValid()`, and when the field is empty the verdict is the\r\n * `flag`. It is the escape hatch for the composite controls whose validity only they can judge.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param flag - Verdict used while the field is empty, as a boolean or a reactive function.\r\n * Defaults to `false`.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function validIf<TValue extends Partial<Validated>, TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\r\n flag: boolean | (() => boolean) = false,\r\n config?: ArsValidatorConfig<TValue, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const value = ctx.value();\r\n let isValid: boolean;\r\n if (!value) {\r\n isValid = (typeof flag === 'function' ? flag() : flag) === true;\r\n } else {\r\n try {\r\n isValid = value.isValid?.() === true;\r\n } catch {\r\n isValid = false;\r\n }\r\n }\r\n return isValid ? null : { kind: 'validIf', message: config?.message ?? ARS_VALIDATOR_MESSAGES['validIf'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to be a semicolon-separated list of valid e-mail addresses.\r\n *\r\n * The signal-form counterpart of `EmailsValidatorDirective`. An empty value passes, and so does\r\n * an empty entry between two semicolons: the list is typed by hand and a trailing `;` is not a\r\n * mistake worth an error.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function emails<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const input = ctx.value();\r\n if (!input || input.length === 0) return null;\r\n const parts = input.replaceAll(/\\r\\n/g, '').split(';');\r\n const isValid = parts.every(part => part.length === 0 || !!SystemUtils.parseEmail(part));\r\n return isValid ? null : { kind: 'emails', message: config?.message ?? ARS_VALIDATOR_MESSAGES['emails'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to be a `\"HH:MM\"` time and, when slots are given, to fall inside one of them.\r\n *\r\n * The signal-form counterpart of `TimeValidatorDirective`. An empty value passes.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param slots - Optional reactive function returning the pipe-separated allowed ranges\r\n * (e.g. `\"08:00-12:00|14:00-18:00\"`), or `undefined` for no restriction.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function time<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n slots?: () => string | undefined,\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n /**\r\n * Turns `\"HH:MM\"` into a comparable integer (`\"09:30\"` -> `930`).\r\n * @param value - The time string to parse.\r\n * @returns The comparable integer, or `-1` when the string is not a valid time.\r\n */\r\n const getTime = (value: string): number => {\r\n const p = value.split(':');\r\n if (p.length !== 2) return -1;\r\n const hh = parseInt(p[0], 10);\r\n if (isNaN(hh) || hh < 0 || hh > 23) return -1;\r\n const mm = parseInt(p[1], 10);\r\n if (isNaN(mm) || mm < 0 || mm > 59) return -1;\r\n return hh * 100 + mm;\r\n };\r\n\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const input = ctx.value();\r\n if (!input || input.length === 0) return null;\r\n const invalid = { kind: 'time', message: config?.message ?? ARS_VALIDATOR_MESSAGES['time'] };\r\n const t = getTime(input);\r\n if (t === -1) return invalid;\r\n const slotsValue = slots?.();\r\n if (slotsValue) {\r\n const inSlot = slotsValue.split('|').some(s => {\r\n const from = getTime(s.substring(0, 5));\r\n const to = getTime(s.substring(6));\r\n return from !== -1 && to !== -1 && from <= t && to >= t;\r\n });\r\n if (!inSlot) return invalid;\r\n }\r\n return null;\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to equal the value of another field of the same form.\r\n *\r\n * The signal-form counterpart of `EqualsValidatorDirective`. Reactive on both fields, which is\r\n * what the directive needed a `valueChanges` subscription to obtain: retyping the first password\r\n * re-validates the confirmation without anyone wiring the two together.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param other - Path of the field whose value must match.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function equals<TValue, TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\r\n other: SchemaPath<TValue, SchemaPathRules.Supported>,\r\n config?: ArsValidatorConfig<TValue, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n return ctx.valueOf(other) === ctx.value()\r\n ? null\r\n : { kind: 'equals', message: config?.message ?? ARS_VALIDATOR_MESSAGES['equals'] };\r\n });\r\n}\r\n\r\n/**\r\n * Requires the value to be either empty or a complete six-digit one-time code.\r\n *\r\n * The schema-level counterpart of the validator inside `OtpInputComponent`: a partial code is an\r\n * error, an empty one is `required()`'s business.\r\n *\r\n * @param path - Path of the field to validate.\r\n * @param config - Optional message override and `when` condition.\r\n * @returns void\r\n */\r\nexport function otp<TPathKind extends PathKind = PathKind.Root>(\r\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\r\n config?: ArsValidatorConfig<string, TPathKind>\r\n): void {\r\n validate(path, ctx => {\r\n if (config?.when && !config.when(ctx)) return null;\r\n const input = ctx.value() ?? '';\r\n if (input.length === 0) return null;\r\n return /^\\d{6}$/.test(input)\r\n ? null\r\n : { kind: 'otp', message: config?.message ?? ARS_VALIDATOR_MESSAGES['otp'] };\r\n });\r\n}\r\n\r\n/** Helpers around signal forms that are not validators themselves. */\r\nexport class SignalsUtils {\r\n\r\n /**\r\n * Builds the error text for a signal-forms field.\r\n *\r\n * Deliberately dumb: the wording lives in the schema, next to the rule that produces it\r\n * (`required(p.x, { message: ... })`), so a field says what is wrong with it in one place\r\n * instead of here in a switch that has to guess from the error kind. The map below is only\r\n * the safety net for the rules declared without a message — the Angular built-ins, plus\r\n * {@link ARS_VALIDATOR_MESSAGES} for the ones declared in this file.\r\n * @param errors - The errors currently on the field, from `f.x().errors()`.\r\n * @param message - Optional override applied to every error of the field.\r\n * @returns The first relevant error text, or `undefined` when the field has no errors.\r\n */\r\n public static getFieldErrorMessage(\r\n errors: readonly { kind: string; message?: string }[],\r\n message?: string\r\n ): string | undefined {\r\n if (!errors || errors.length === 0) return undefined;\r\n\r\n const fallback: Record<string, string> = {\r\n // Angular built-ins declared without a message of their own.\r\n required: 'Obbligatorio',\r\n min: 'Valore troppo basso',\r\n max: 'Valore troppo alto',\r\n minLength: 'Testo troppo corto',\r\n maxLength: 'Testo troppo lungo',\r\n pattern: 'Formato non valido',\r\n email: 'Indirizzo email non valido',\r\n minDate: 'Data troppo indietro',\r\n maxDate: 'Data troppo avanti',\r\n parse: 'Valore non valido',\r\n matDatepickerParse: 'Data non valida',\r\n matDatepickerMin: 'Data troppo indietro',\r\n matDatepickerMax: 'Data troppo avanti',\r\n matDatepickerFilter: 'Data non selezionabile',\r\n matStartDateInvalid: 'Intervallo non valido',\r\n matEndDateInvalid: 'Intervallo non valido',\r\n matTimepickerParse: 'Orario non valido',\r\n matTimepickerMin: 'Orario troppo presto',\r\n matTimepickerMax: 'Orario troppo tardi',\r\n // The rules of this file, from the single table above: adding a validator there is enough,\r\n // and this map can never fall behind it.\r\n ...ARS_VALIDATOR_MESSAGES,\r\n };\r\n\r\n\r\n message = message ?? errors[0].message ?? fallback[errors[0].kind] ?? '';\r\n return message.length > 0 ? message : 'Non valido';\r\n }\r\n}\r\n","/*\n * Public API Surface of @arsedizioni/ars-utils/core.validators\n *\n * Template-driven form validators. Kept OUT of `core` on purpose: every one of them pulls in\n * `@angular/forms` (53 KB), and `core` is on the boot path of every application through\n * `ThemeService`, `BroadcastService` and friends. Importing a validator now costs `@angular/forms`\n * only to the lazy chunk that actually uses one.\n */\nexport * from './validators';\n\n// Signal-form flavour of the same rules. Lives here and not in a separate entry point because\n// `@angular/forms/signals` depends on `@angular/forms` anyway, so the two never travel apart.\nexport * from './signals';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"arsedizioni-ars-utils-core.validators.mjs","sources":["../../../projects/ars-utils/core.validators/validatorDirective.ts","../../../projects/ars-utils/core.validators/validIfDirective.ts","../../../projects/ars-utils/core.validators/equalsValidatorDirective.ts","../../../projects/ars-utils/core.validators/notEqualValidatorDirective.ts","../../../projects/ars-utils/core.validators/emailsValidatorDirective.ts","../../../projects/ars-utils/core.validators/guidValidatorDirective.ts","../../../projects/ars-utils/core.validators/sqlDateValidatorDirective.ts","../../../projects/ars-utils/core.validators/notFutureValidatorDirective.ts","../../../projects/ars-utils/core.validators/urlValidatorDirective.ts","../../../projects/ars-utils/core.validators/fileSizeValidatorDirective.ts","../../../projects/ars-utils/core.validators/maxTermsValidatorDirective.ts","../../../projects/ars-utils/core.validators/passwordValidatorDirective.ts","../../../projects/ars-utils/core.validators/timeValidatorDirective.ts","../../../projects/ars-utils/core.validators/emptiness.ts","../../../projects/ars-utils/core.validators/notEmptyValidatorDirective.ts","../../../projects/ars-utils/core.validators/requiredNotEmptyValidatorDirective.ts","../../../projects/ars-utils/core.validators/signals.ts","../../../projects/ars-utils/core.validators/public_api.ts","../../../projects/ars-utils/core.validators/arsedizioni-ars-utils-core.validators.ts"],"sourcesContent":["import { Directive, input } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\n\r\n/**\r\n * Directive that delegates validation to an externally provided validator function.\r\n * Bind `[validator]=\"myFn\"` where `myFn` is `(c: AbstractControl) => ValidationErrors | null`.\r\n */\r\n@Directive({\r\n selector: '[validator]',\r\n providers: [{ provide: NG_VALIDATORS, useExisting: ValidatorDirective, multi: true }],\r\n standalone: true,\r\n})\r\nexport class ValidatorDirective implements Validator {\r\n\r\n /** The custom validator function to apply. */\r\n readonly validator = input<((control: AbstractControl) => ValidationErrors | null) | undefined>(undefined);\r\n\r\n /**\r\n * Invokes the provided validator function against the given control.\r\n * Returns `null` (valid) when no function is bound.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const fn = this.validator();\r\n return fn ? fn(control) : null;\r\n }\r\n}\r\n","import { Directive, forwardRef, input } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\nimport { Validated } from '@arsedizioni/ars-utils/core';\r\n\r\n/**\r\n * Directive that validates a control using the host object's `isValid()` method\r\n * or a boolean expression passed via `[validIf]`.\r\n */\r\n@Directive({\r\n selector: \"[validIf]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => ValidIfDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class ValidIfDirective implements Validator {\r\n\r\n /** When `true`, the control is considered valid regardless of the bound value. */\r\n readonly validIf = input<boolean>(false);\r\n\r\n /**\r\n * Validates the control value against a boolean flag or the value's own `isValid()` method.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n let isValid = false;\r\n const c = control.value ? (control.value as Validated) : null;\r\n if (!c) {\r\n isValid = this.validIf() === true;\r\n } else {\r\n try {\r\n isValid = c.isValid();\r\n } catch { }\r\n }\r\n return isValid ? null : { validIf: \"Non valido.\" };\r\n }\r\n}\r\n","import { DestroyRef, Directive, effect, forwardRef, inject, input } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\nimport { Subscription } from \"rxjs\";\n\n/**\n * Directive that validates that the host control's value equals the value of another control.\n * Bind `[equals]=\"otherControl\"`.\n *\n * The host control is re-validated whenever the OTHER control's value changes:\n * without this, typing a new password AFTER the confirmation field was filled\n * left the form incorrectly valid (the classic password/confirm bug).\n *\n * IMPORTANT (reciprocal-binding safety): the re-validation triggered from the\n * other control's `valueChanges` runs with `{ emitEvent: false }`. Calling\n * Angular's `onValidatorChange` instead would re-emit valueChanges, so a\n * reciprocal setup (A [equals]=B and B [equals]=A) would overflow the stack.\n */\n@Directive({\n selector: \"[equals]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => EqualsValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class EqualsValidatorDirective implements Validator {\n\n /** The control whose value must match the host control's value. */\n readonly equals = input<AbstractControl | undefined>(undefined);\n\n /** The host control, captured on the first validate() call. */\n private hostControl?: AbstractControl;\n\n /** Subscription to the other control's valueChanges. */\n private subscription?: Subscription;\n\n constructor() {\n // Re-subscribe whenever the [equals] binding points to a different control,\n // and re-validate the host on every change of the other control.\n effect(() => {\n const other = this.equals();\n this.subscription?.unsubscribe();\n this.subscription = other?.valueChanges.subscribe(() =>\n // emitEvent:false breaks the reciprocal valueChanges loop (see class doc).\n this.hostControl?.updateValueAndValidity({ emitEvent: false })\n );\n // Re-validate the host when the bound control itself is swapped.\n this.hostControl?.updateValueAndValidity({ emitEvent: false });\n });\n inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());\n }\n\n /**\n * Validates that the host control value equals the bound control's value.\n * Returns `null` (valid) when no control is bound.\n * @param control - The form control to validate.\n * @returns `null` when valid, `{ equals: ... }` otherwise.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n this.hostControl = control;\n const eq = this.equals();\n if (!eq) return null;\n return eq.value === control.value ? null : { equals: \"Non valido.\" };\n }\n}\n","import { DestroyRef, Directive, effect, forwardRef, inject, input } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\nimport { Subscription } from \"rxjs\";\n\n/**\n * Directive that validates that the host control's value is different from another control's value.\n * Bind `[notEqual]=\"otherControl\"`.\n *\n * The host control is re-validated whenever the OTHER control's value changes,\n * so editing either field keeps both error states consistent.\n *\n * IMPORTANT (reciprocal-binding safety): the re-validation triggered from the\n * other control's `valueChanges` is run with `{ emitEvent: false }`. Using\n * Angular's `onValidatorChange` here instead would call `host.updateValueAndValidity()`\n * WITH events, so a reciprocal setup (A [notEqual]=B and B [notEqual]=A) would\n * ping-pong valueChanges between the two controls and overflow the stack.\n */\n@Directive({\n selector: \"[notEqual]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => NotEqualValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class NotEqualValidatorDirective implements Validator {\n\n /** The control whose value must differ from the host control's value. */\n readonly notEqual = input<AbstractControl | undefined>(undefined);\n\n /** The host control, captured on the first validate() call. */\n private hostControl?: AbstractControl;\n\n /** Subscription to the other control's valueChanges. */\n private subscription?: Subscription;\n\n constructor() {\n effect(() => {\n const other = this.notEqual();\n this.subscription?.unsubscribe();\n this.subscription = other?.valueChanges.subscribe(() =>\n // Re-validate the host WITHOUT emitting valueChanges, otherwise a\n // reciprocal binding would loop forever (see class doc).\n this.hostControl?.updateValueAndValidity({ emitEvent: false })\n );\n // Re-validate the host when the bound control itself is swapped.\n this.hostControl?.updateValueAndValidity({ emitEvent: false });\n });\n inject(DestroyRef).onDestroy(() => this.subscription?.unsubscribe());\n }\n\n /**\n * Validates that the host control value is not equal to the bound control's value.\n * Also clears the `notequal` error on the other control when the host becomes valid.\n * Returns `null` (valid) when no control is bound.\n * @param control - The form control to validate.\n * @returns `null` when valid, `{ notequal: true }` otherwise.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n this.hostControl = control;\n\n const notEqual = this.notEqual();\n if (!notEqual) return null;\n\n const isValid = (!notEqual.value && !control.value) || (notEqual.value !== control.value);\n const errors: ValidationErrors | null = isValid ? null : { notequal: true };\n\n if (errors) {\n control.markAsTouched();\n } else if (notEqual.hasError('notequal')) {\n const { notequal: _removed, ...rest } = notEqual.errors ?? {};\n // emitEvent:false on both: clearing the partner's error must not feed\n // back through valueChanges/statusChanges into this validator.\n notEqual.setErrors(Object.keys(rest).length > 0 ? rest : null, { emitEvent: false });\n notEqual.updateValueAndValidity({ onlySelf: true, emitEvent: false });\n notEqual.markAsTouched();\n notEqual.markAsDirty();\n }\n return errors;\n }\n}\n","import { Directive, forwardRef } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\r\n\r\n/**\r\n * Directive that validates a semicolon-separated list of email addresses.\r\n * Apply `emails` to a text input containing one or more addresses separated by `;`.\r\n */\r\n@Directive({\r\n selector: \"[emails]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => EmailsValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class EmailsValidatorDirective implements Validator {\r\n\r\n /**\r\n * Validates each address in a semicolon-separated email list.\r\n * Returns `null` when the control is empty.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input: string = control.value;\r\n if (!input || input.length === 0) return null;\r\n const parts = input.replaceAll(/\\r\\n/g, '').split(';');\r\n const isValid = parts.every(part => part.length === 0 || !!SystemUtils.parseEmail(part));\r\n return isValid ? null : { emails: \"Elenco non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\r\n\r\n/**\r\n * Directive that validates a control value as a GUID / UUID string.\r\n * Apply `guid` to a text input that expects a valid UUID.\r\n */\r\n@Directive({\r\n selector: \"[guid]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => GuidValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class GuidValidatorDirective implements Validator {\r\n\r\n /**\r\n * Validates that the control value is a well-formed GUID / UUID.\r\n * Returns `null` when the control is empty.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input: string = control.value;\r\n if (!input || input.length === 0) return null;\r\n return SystemUtils.parseUUID(input) ? null : { guid: \"Non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\nimport { endOfDay } from 'date-fns';\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\n\n/**\n * Directive that validates a control value as a parseable SQL-compatible date string.\n * Apply `sqlDate` to a text input that expects a date after year 1750.\n */\n@Directive({\n selector: \"[sqlDate]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => SqlDateValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class SqlDateValidatorDirective implements Validator {\n\n /**\n * Validates that the control value can be parsed as a date after 1750.\n * Returns `null` when the control is empty.\n * @param control - The form control to validate.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n const input: string = control.value;\n if (!input || input.length === 0) return null;\n const parsed = SystemUtils.parseDate(input);\n if (!parsed) return { sqlDate: \"Non valido.\" };\n const d = endOfDay(parsed);\n return d.getFullYear() > 1750 ? null : { sqlDate: \"Non valido.\" };\n }\n}\n","import { Directive, forwardRef } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\nimport { endOfDay } from 'date-fns';\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\n\n/**\n * Directive that validates that a control value is not a future date.\n * Apply `notFuture` to a text input that expects a date on or before today.\n */\n@Directive({\n selector: \"[notFuture]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => NotFutureValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class NotFutureValidatorDirective implements Validator {\n\n /**\n * Validates that the control value represents a date that is not in the future.\n * Returns `null` when the control is empty.\n * @param control - The form control to validate.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n const input: string = control.value;\n if (!input || input.length === 0) return null;\n const parsed = SystemUtils.parseDate(input);\n if (!parsed) return { notFuture: \"Non valido.\" };\n const today = endOfDay(new Date());\n const d = endOfDay(parsed);\n return d <= today ? null : { notFuture: \"Non valido.\" };\n }\n}\n","import { Directive, forwardRef } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\r\n\r\n/**\r\n * Directive that validates a control value as a well-formed URL.\r\n * Apply `url` to a text input that expects a URL.\r\n */\r\n@Directive({\r\n selector: \"[url]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => UrlValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class UrlValidatorDirective implements Validator {\r\n\r\n /**\r\n * Validates that the control value is a well-formed URL.\r\n * Returns `null` (valid) when the control is empty.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input: string = control.value;\r\n if (!input || input.length === 0) return null;\r\n return SystemUtils.parseUrl(input) ? null : { url: \"Non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef, input } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\n\r\n/**\r\n * Directive that validates a file size against configurable minimum and maximum bounds.\r\n * Bind `[fileSize]` together with `[size]=\"fileSizeInMb\"`, `[maxSizeMb]`, and `[minSizeMb]`.\r\n */\r\n@Directive({\r\n selector: \"[fileSize]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => FileSizeValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class FileSizeValidatorDirective implements Validator {\r\n\r\n /** Maximum allowed file size in megabytes. Defaults to 5. */\r\n readonly maxSizeMb = input<number>(5);\r\n\r\n /** Minimum required file size in megabytes. Defaults to 0. */\r\n readonly minSizeMb = input<number>(0);\r\n\r\n /** The actual file size in megabytes to validate against the bounds. */\r\n readonly size = input<number | undefined>(undefined);\r\n\r\n /**\r\n * Validates that the bound file size falls within the configured min/max range.\r\n * Returns `null` when no control value is present.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input = control.value;\r\n if (!input) return null;\r\n const s = this.size() ?? 0;\r\n const isValid = s <= this.maxSizeMb() && s >= this.minSizeMb();\r\n return isValid ? null : { fileSize: \"Non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef, input } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\n\r\n/**\r\n * Directive that validates that a control value does not exceed a maximum word count.\r\n * Bind `[maxTerms]=\"10\"` to allow at most 10 whitespace-separated terms.\r\n */\r\n@Directive({\r\n selector: \"[maxTerms]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => MaxTermsValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class MaxTermsValidatorDirective implements Validator {\r\n\r\n /** The maximum number of whitespace-separated terms allowed. */\r\n readonly maxTerms = input<number>(0);\r\n\r\n /**\r\n * Validates that the control value contains no more than the configured number of terms.\r\n * Returns `null` when the control is empty.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input: string = control.value;\r\n if (!input) return null;\r\n const terms = input.match(/\\S+/g)?.length ?? 0;\r\n return terms <= this.maxTerms() ? null : { maxTerms: \"Non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef } from \"@angular/core\";\r\nimport {\r\n AbstractControl,\r\n NG_VALIDATORS,\r\n ValidationErrors,\r\n Validator,\r\n} from \"@angular/forms\";\r\nimport { SystemUtils } from \"@arsedizioni/ars-utils/core\";\r\n\r\n/**\r\n * Directive that validates a control value as a sufficiently strong password.\r\n * Apply `password` to a password input.\r\n */\r\n@Directive({\r\n selector: \"[password]\",\r\n providers: [\r\n {\r\n provide: NG_VALIDATORS,\r\n useExisting: forwardRef(() => PasswordValidatorDirective),\r\n multi: true,\r\n },\r\n ],\r\n standalone: true,\r\n})\r\nexport class PasswordValidatorDirective implements Validator {\r\n\r\n /**\r\n * Validates that the control value meets the minimum password-strength requirements.\r\n * @param control - The form control to validate.\r\n */\r\n validate(control: AbstractControl): ValidationErrors | null {\r\n const input: string = control.value ?? '';\r\n const strength = SystemUtils.calculatePasswordStrength(input);\r\n return strength.isValid ? null : { password: \"Non valido.\" };\r\n }\r\n}\r\n","import { Directive, forwardRef, input } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\n\n/**\n * Directive that validates a time string against optional allowed time slot ranges.\n * Bind `[time]` and optionally `[slots]=\"'08:00-12:00|14:00-18:00'\"` (pipe-separated ranges).\n */\n@Directive({\n selector: \"[time]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => TimeValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class TimeValidatorDirective implements Validator {\n\n /** Optional pipe-separated list of allowed time ranges, e.g. `\"08:00-12:00|14:00-18:00\"`. */\n readonly slots = input<string | undefined>(undefined);\n\n /**\n * Parses a `\"HH:MM\"` time string into a comparable integer (e.g. `\"09:30\"` -> `930`).\n * Returns `-1` when the string is not a valid time.\n * @param value - The time string to parse.\n */\n private getTime(value: string): number {\n const p = value.split(':');\n if (p.length !== 2) return -1;\n const hh = parseInt(p[0], 10);\n if (isNaN(hh) || hh < 0 || hh > 23) return -1;\n const mm = parseInt(p[1], 10);\n if (isNaN(mm) || mm < 0 || mm > 59) return -1;\n return hh * 100 + mm;\n }\n\n /**\n * Validates that the control value is a valid time string and, when slots are configured,\n * that it falls within at least one of the allowed ranges.\n * Returns `null` when the control is empty.\n * @param control - The form control to validate.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n const input: string = control.value;\n if (!input || input.length === 0) return null;\n\n const t = this.getTime(input);\n if (t === -1) return { time: \"Non valido.\" };\n\n const slotsValue = this.slots();\n if (slotsValue) {\n const isValid = slotsValue.split('|').some(s => {\n const t1 = this.getTime(s.substring(0, 5));\n const t2 = this.getTime(s.substring(6));\n return t1 !== -1 && t2 !== -1 && t1 <= t && t2 >= t;\n });\n return isValid ? null : { time: \"Non valido.\" };\n }\n\n return null;\n }\n}\n","/**\n * @file emptiness.ts\n *\n * The single definition of \"empty\" shared by the `notEmpty` / `requiredNotEmpty` rules, in both\n * their flavours: the template-driven directives and the signal-form validators. It lives apart\n * from either of them so that the two faces of the same rule cannot drift, and it pulls in\n * nothing — not `@angular/forms`, not `@angular/core`.\n */\n\n/**\n * Tells whether a value carries nothing at all.\n *\n * Nullish, the empty string and the empty array all count as missing; anything else does not,\n * including `0` and `false`, which are legitimate values a form can hold.\n *\n * @param value - The value to inspect.\n * @returns `true` when the value is absent, an empty string or an empty array.\n */\nexport function isMissingValue(value: unknown): boolean {\n if (value === undefined || value === null) return true;\n if (typeof value === 'string') return value.length === 0;\n if (Array.isArray(value)) return value.length === 0;\n return false;\n}\n\n/**\n * Tells whether a value is what the `notEmpty` rule rejects: a string made of whitespace alone,\n * or an array with no elements.\n *\n * An absent value and an empty string are deliberately NOT rejected: declaring a field mandatory\n * is the job of `required()` (or of `requiredNotEmpty`), and a blank field would otherwise raise\n * two errors saying the same thing. The empty array is the one exception, because there it IS the\n * only shape emptiness can take — a multi-select never holds `''`.\n *\n * @param value - The value to inspect.\n * @returns `true` when the value is a whitespace-only string or an empty array.\n */\nexport function isBlankValue(value: unknown): boolean {\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value !== 'string') return false;\n return value.length > 0 && value.trim().length === 0;\n}\n","import { Directive, forwardRef } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\nimport { isBlankValue } from \"./emptiness\";\n\n/**\n * Directive that validates that a control value is not blank: neither a whitespace-only string\n * nor an empty array. Apply `notEmpty` to a text input where non-blank content is required, or\n * to a multi-value control that must carry at least one entry.\n *\n * A value that is simply absent passes: saying \"obbligatorio\" is the job of `required`, or of\n * `requiredNotEmpty` when both rules belong on the same control.\n */\n@Directive({\n selector: \"[notEmpty]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => NotEmptyValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class NotEmptyValidatorDirective implements Validator {\n\n /**\n * Validates that the control value carries content.\n * Returns `null` when the control is absent or holds a type this rule says nothing about.\n * @param control - The form control to validate.\n * @returns `{ notEmpty: true }` when the value is a blank string or an empty array, `null` otherwise.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n return isBlankValue(control?.value) ? { notEmpty: true } : null;\n }\n}\n","import { Directive, forwardRef } from \"@angular/core\";\nimport {\n AbstractControl,\n NG_VALIDATORS,\n ValidationErrors,\n Validator,\n} from \"@angular/forms\";\nimport { isBlankValue, isMissingValue } from \"./emptiness\";\n\n/**\n * Directive that validates that a control carries actual content: present AND not blank.\n * Apply `requiredNotEmpty` where `required notEmpty` would otherwise be spelled out together.\n *\n * It raises the very errors those two rules raise — `required` when the value is missing, an\n * empty string or an empty array, `notEmpty` when a value is there but made of whitespace alone —\n * so existing error messages and `getFieldErrorMessage` keep working untouched, and the user\n * still reads \"Obbligatorio\" rather than the vaguer \"Non può contenere solo spazi\".\n */\n@Directive({\n selector: \"[requiredNotEmpty]\",\n providers: [\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => RequiredNotEmptyValidatorDirective),\n multi: true,\n },\n ],\n standalone: true,\n})\nexport class RequiredNotEmptyValidatorDirective implements Validator {\n\n /**\n * Validates that the control value is present and carries content.\n * @param control - The form control to validate.\n * @returns `{ required: true }` when nothing was entered, `{ notEmpty: true }` when the value\n * is blank, `null` when the value is acceptable.\n */\n validate(control: AbstractControl): ValidationErrors | null {\n const input = control?.value;\n if (isMissingValue(input)) return { required: true };\n return isBlankValue(input) ? { notEmpty: true } : null;\n }\n}\n","import { LogicFn, PathKind, SchemaPath, SchemaPathRules, validate } from '@angular/forms/signals';\nimport { SystemUtils, Validated } from '@arsedizioni/ars-utils/core';\nimport { endOfDay } from 'date-fns';\nimport { isBlankValue, isMissingValue } from './emptiness';\n\n/**\n * Options shared by the ARS signal-form validators.\n *\n * Mirrors the `config` argument of the Angular built-ins (`required`, `email`, ...) but carries\n * only what these validators need: the message shown to the user in place of the default one.\n */\nexport interface ArsValidatorConfig<TValue = string, TPathKind extends PathKind = PathKind.Root> {\n /** Message attached to the error, in place of the default Italian text. */\n message?: string;\n /**\n * Applies the rule only while this returns `true`, exactly like the `when` of `required()`\n * and of the other Angular built-ins.\n *\n * It exists because these validators are meant to be paired with `required()` on the same\n * field, and a field that is only required in one mode of a dialog must only be validated in\n * that mode: without this, a leftover value would keep a form invalid in a mode where the\n * field is not even shown.\n */\n when?: NoInfer<LogicFn<TValue, boolean, TPathKind>>;\n}\n\n/**\n * Default texts of the rules declared here, in one place so that the validators and the fallback\n * map of `SignalsUtils.getFieldErrorMessage` cannot drift apart: a rule added below without a\n * message here would show \"Errore\", and one renamed here without touching the validator would\n * leave the map with a kind nobody produces.\n */\n/**\n * Earliest date {@link date} and {@link dateRange} accept: 1 January 1970.\n *\n * Everything this application stores — events, certificates, payments, communications — happened\n * after it, so an earlier value is always a typo (a two-digit year, a slipped keystroke) and never\n * real data. The floor is deliberately higher than the one of {@link sqlDate}, which only asks\n * what SQL Server can physically store.\n */\nexport const MIN_VALID_YEAR = 1970;\n\nexport const ARS_VALIDATOR_MESSAGES: Record<string, string> = {\n // Produced by the Angular built-in `required()` and by {@link requiredNotEmpty}. It sits here,\n // and no longer among the built-in fallbacks below, so that the text exists exactly once.\n required: 'Obbligatorio',\n guid: 'Ticket non riconosciuto',\n password: 'Password non sufficientemente robusta',\n notEmpty: 'Non può contenere solo spazi',\n notEqual: 'Deve essere diverso dall\\'altro valore',\n sqlDate: 'Data non valida',\n date: 'Data non valida',\n dateRange: 'Intervallo non valido',\n notFuture: 'La data non può essere futura',\n url: 'Indirizzo non valido',\n maxTerms: 'Troppe parole',\n fileSize: 'Dimensione del file non ammessa',\n validIf: 'Non valido',\n emails: 'Elenco non valido',\n time: 'Orario non valido',\n equals: 'I due valori non coincidono',\n otp: 'Codice non valido',\n};\n\n/**\n * Requires the value to be a well-formed GUID / UUID.\n *\n * The signal-form counterpart of `GuidValidatorDirective`, sharing its rule down to the empty\n * case: an empty value is NOT an error here, because saying \"obbligatorio\" is the job of\n * `required()` and two errors on one empty field only ever read as noise.\n *\n * @param path - Path of the field to validate.\n * @param config - Optional message override.\n * @returns void\n * @example\n * const f = form(this.model, p => { required(p.serial); guid(p.serial); });\n */\nexport function guid<TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<string, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const input = ctx.value();\n if (!input || input.length === 0) return null;\n return SystemUtils.parseUUID(input)\n ? null\n : { kind: 'guid', message: config?.message ?? ARS_VALIDATOR_MESSAGES['guid'] };\n });\n}\n\n/**\n * Requires the value to be a password strong enough for {@link SystemUtils.calculatePasswordStrength}.\n *\n * The signal-form counterpart of `PasswordValidatorDirective`. Unlike {@link guid} it does judge\n * the empty value, because an empty password IS a weak one and the directive behaved the same way.\n *\n * @param path - Path of the field to validate.\n * @param config - Optional message override.\n * @returns void\n */\nexport function password<TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<string, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const strength = SystemUtils.calculatePasswordStrength(ctx.value() ?? '');\n return strength.isValid\n ? null\n : { kind: 'password', message: config?.message ?? ARS_VALIDATOR_MESSAGES['password'] };\n });\n}\n\n/**\n * Requires the value not to be made of whitespace alone, and a collection not to be empty.\n *\n * The signal-form counterpart of `NotEmptyValidatorDirective`, sharing its predicate through\n * {@link isBlankValue}: a blank string and an empty array are errors, an absent value is not.\n * That last part is not an oversight — saying \"obbligatorio\" belongs to `required()`, and a field\n * that is merely blank would otherwise raise two errors that mean the same thing. Pair the two,\n * or reach for {@link requiredNotEmpty}, when a field must be both present and non-blank.\n *\n * Replaces the `pattern(p.x, /\\S/)` workaround: same rule, but the intent is in the name and the\n * error kind is `notEmpty` rather than `pattern`.\n *\n * @param path - Path of the field to validate.\n * @param config - Optional message override.\n * @returns void\n * @example\n * const f = form(this.model, p => { required(p.city); notEmpty(p.city); });\n * @example\n * const f = form(this.model, p => { notEmpty(p.tags); }); // at least one tag\n */\nexport function notEmpty<TValue extends string | readonly unknown[] | undefined,\n TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<TValue, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n return isBlankValue(ctx.value())\n ? { kind: 'notEmpty', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notEmpty'] }\n : null;\n });\n}\n\n/**\n * Requires the value to be both present and made of something: the two rules a mandatory text\n * field almost always needs together, declared once.\n *\n * The signal-form counterpart of `RequiredNotEmptyValidatorDirective`. It raises the errors the\n * two rules raise on their own rather than a kind of its own — `required` when nothing was\n * entered (nullish, empty string, empty array), `notEmpty` when a value is there but blank — so\n * the message stays as precise as it was and nothing downstream needs to learn a new kind.\n *\n * Not a wrapper around Angular's `required()`: that one would have to be declared on the same\n * path anyway, and the pair would then report two errors on an empty field.\n *\n * @param path - Path of the field to validate.\n * @param config - Optional message override, applied to whichever of the two errors is raised.\n * @returns void\n * @example\n * const f = form(this.model, p => { requiredNotEmpty(p.city); });\n */\nexport function requiredNotEmpty<TValue extends string | readonly unknown[] | undefined,\n TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<TValue, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const input = ctx.value();\n if (isMissingValue(input)) {\n return { kind: 'required', message: config?.message ?? ARS_VALIDATOR_MESSAGES['required'] };\n }\n return isBlankValue(input)\n ? { kind: 'notEmpty', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notEmpty'] }\n : null;\n });\n}\n\n/**\n * Requires the value to differ from the value of another field of the same form.\n *\n * The signal-form counterpart of `NotEqualValidatorDirective`, with its exact rule: two empty\n * values are considered different, so an untouched pair of fields does not start out in error.\n * Reactive on both fields — editing either one re-validates this one, which is what the\n * directive needed a `valueChanges` subscription (and a re-entrancy guard) to achieve.\n *\n * @param path - Path of the field to validate.\n * @param other - Path of the field whose value must differ.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function notEqual<TValue, TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\n other: SchemaPath<TValue, SchemaPathRules.Supported>,\n config?: ArsValidatorConfig<TValue, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const mine = ctx.value();\n const theirs = ctx.valueOf(other);\n const isValid = (!theirs && !mine) || theirs !== mine;\n return isValid ? null : { kind: 'notEqual', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notEqual'] };\n });\n}\n\n/**\n * Requires the value to be a date the backend can store: parseable, and after 1750.\n *\n * The signal-form counterpart of `SqlDateValidatorDirective`. The year floor is not arbitrary —\n * it is what separates a real date from the 01/01/0001 that a mistyped year produces, which SQL\n * Server rejects with an error nobody can read.\n *\n * @param path - Path of the field to validate.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function sqlDate<TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<string, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const input = ctx.value();\n if (!input || input.length === 0) return null;\n const parsed = SystemUtils.parseDate(input);\n const invalid = { kind: 'sqlDate', message: config?.message ?? ARS_VALIDATOR_MESSAGES['sqlDate'] };\n if (!parsed) return invalid;\n return endOfDay(parsed).getFullYear() > 1750 ? null : invalid;\n });\n}\n\n/**\n * Requires the value to be a real date, as {@link SystemUtils.parseDate} understands one.\n *\n * This is the rule for anything a user picks or types as a date: it accepts both the `Date` a\n * Material datepicker or timepicker writes into the model and the text of a plain input, since\n * `parseDate` handles the shapes this codebase produces (ISO, `dd/MM/yyyy`, `yyyy-MM-dd`, and the\n * shorthand forms). Empty passes — saying \"obbligatorio\" is the job of `required()`.\n *\n * A date earlier than {@link MIN_VALID_YEAR} (1 January 1970) is rejected: nothing this\n * application stores predates it, so an earlier value is a typo rather than data.\n *\n * Distinct from {@link sqlDate} on purpose: that one is about what the DATABASE can store (the\n * 1750 floor), this one is about whether the value is a date at all. Pair them when both matter.\n *\n * @param path - Path of the field to validate.\n * @param config - Optional message override and `when` condition.\n * @returns void\n * @example\n * const f = form(this.model, p => { required(p.expiry); date(p.expiry); });\n */\nexport function date<TValue extends string | Date | null | undefined,\n TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<TValue, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const input = ctx.value();\n if (input === undefined || input === null || input === '') return null;\n const parsed = SystemUtils.parseDate(input);\n return parsed && parsed.getFullYear() >= MIN_VALID_YEAR\n ? null\n : { kind: 'date', message: config?.message ?? ARS_VALIDATOR_MESSAGES['date'] };\n });\n}\n\n/**\n * Requires the two ends of a date range to be real dates and to be in order.\n *\n * Written for the two inputs of a `mat-date-range-input`, whose start and end live in two\n * separate fields of the model. Each end is checked with the same rule as {@link date}, and the\n * ordering is checked only when BOTH ends are filled in — a half-open range (\"from today\n * onwards\") is a legitimate filter, not an error. The 1 January 1970 floor of {@link date}\n * applies to both ends.\n *\n * The rule is bound to BOTH paths, so the error appears on whichever end the user is looking at\n * and a single `<mat-error>` under the range can read either one. Comparison is made on the end\n * of the day, so picking the same day for both ends is valid.\n *\n * @param from - Path of the field holding the start of the range.\n * @param to - Path of the field holding the end of the range.\n * @param config - Optional message override (used for the ordering error) and `when` condition.\n * @returns void\n * @example\n * const f = form(this.model, p => { dateRange(p.sentFrom, p.sentTo); });\n */\nexport function dateRange<TValue extends string | Date | null | undefined,\n TPathKind extends PathKind = PathKind.Root>(\n from: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\n to: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<TValue, TPathKind>\n): void {\n date(from, config);\n date(to, config);\n\n /**\n * Compares the two ends of the range once both of them are filled in.\n * @param startValue - Raw value of the start field.\n * @param endValue - Raw value of the end field.\n * @returns The ordering error, or `null` when the pair is acceptable.\n */\n const checkOrder = (startValue: TValue, endValue: TValue) => {\n const start = SystemUtils.parseDate(startValue ?? undefined);\n const end = SystemUtils.parseDate(endValue ?? undefined);\n // A half-open range is legitimate: nothing to compare until both ends are there. An end that\n // is not a valid date is already reported by the `date` rule bound above, so it is skipped\n // here rather than reported twice.\n if (!start || !end) return null;\n if (start.getFullYear() < MIN_VALID_YEAR || end.getFullYear() < MIN_VALID_YEAR) return null;\n return endOfDay(start) <= endOfDay(end)\n ? null\n : { kind: 'dateRange', message: config?.message ?? ARS_VALIDATOR_MESSAGES['dateRange'] };\n };\n\n // Reading the opposite end through `valueOf` keeps each rule reactive on the other field, so\n // filling in one end re-validates the other.\n validate(from, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n return checkOrder(ctx.value(), ctx.valueOf(to));\n });\n validate(to, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n return checkOrder(ctx.valueOf(from), ctx.value());\n });\n}\n\n/**\n * Requires the value to be a date that is not in the future.\n *\n * The signal-form counterpart of `NotFutureValidatorDirective`. Today counts as valid: the\n * comparison is made on the end of the day, so a date entered this morning does not become\n * invalid because the clock says 09:00.\n *\n * @param path - Path of the field to validate.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function notFuture<TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<string, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const input = ctx.value();\n if (!input || input.length === 0) return null;\n const parsed = SystemUtils.parseDate(input);\n const invalid = { kind: 'notFuture', message: config?.message ?? ARS_VALIDATOR_MESSAGES['notFuture'] };\n if (!parsed) return invalid;\n return endOfDay(parsed) <= endOfDay(new Date()) ? null : invalid;\n });\n}\n\n/**\n * Requires the value to be a well-formed URL. An empty value passes, as everywhere else here.\n *\n * The signal-form counterpart of `UrlValidatorDirective`.\n *\n * @param path - Path of the field to validate.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function url<TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<string, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const input = ctx.value();\n if (!input || input.length === 0) return null;\n return SystemUtils.parseUrl(input)\n ? null\n : { kind: 'url', message: config?.message ?? ARS_VALIDATOR_MESSAGES['url'] };\n });\n}\n\n/**\n * Requires the value to hold no more than `max` whitespace-separated terms.\n *\n * The signal-form counterpart of `MaxTermsValidatorDirective`, used on the search boxes where\n * the backend refuses a query past a certain number of words.\n *\n * @param path - Path of the field to validate.\n * @param max - The maximum number of terms, as a number or a reactive function.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function maxTerms<TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\n max: number | (() => number),\n config?: ArsValidatorConfig<string, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const input = ctx.value();\n if (!input) return null;\n const terms = input.match(/\\S+/g)?.length ?? 0;\n return terms <= (typeof max === 'function' ? max() : max)\n ? null\n : { kind: 'maxTerms', message: config?.message ?? ARS_VALIDATOR_MESSAGES['maxTerms'] };\n });\n}\n\n/**\n * Requires the size of the picked file to fall within the allowed range.\n *\n * The signal-form counterpart of `FileSizeValidatorDirective`, and it keeps its shape: the field\n * itself holds the file NAME, while the size arrives from outside — the control that picked the\n * file knows it, the form does not. An empty field passes, so \"no file\" is `required()`'s call\n * and not a size error.\n *\n * @param path - Path of the field holding the file name.\n * @param sizeMb - The size of the picked file in megabytes, as a reactive function.\n * @param maxSizeMb - The maximum allowed size in megabytes. Defaults to `5`.\n * @param minSizeMb - The minimum required size in megabytes. Defaults to `0`.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function fileSize<TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\n sizeMb: () => number | undefined,\n maxSizeMb: number | (() => number) = 5,\n minSizeMb: number | (() => number) = 0,\n config?: ArsValidatorConfig<string, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n if (!ctx.value()) return null;\n const size = sizeMb() ?? 0;\n const max = typeof maxSizeMb === 'function' ? maxSizeMb() : maxSizeMb;\n const min = typeof minSizeMb === 'function' ? minSizeMb() : minSizeMb;\n return size <= max && size >= min\n ? null\n : { kind: 'fileSize', message: config?.message ?? ARS_VALIDATOR_MESSAGES['fileSize'] };\n });\n}\n\n/**\n * Requires the value to declare itself valid.\n *\n * The signal-form counterpart of `ValidIfDirective`: when the field holds an object implementing\n * `Validated` the verdict is its own `isValid()`, and when the field is empty the verdict is the\n * `flag`. It is the escape hatch for the composite controls whose validity only they can judge.\n *\n * @param path - Path of the field to validate.\n * @param flag - Verdict used while the field is empty, as a boolean or a reactive function.\n * Defaults to `false`.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function validIf<TValue extends Partial<Validated>, TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\n flag: boolean | (() => boolean) = false,\n config?: ArsValidatorConfig<TValue, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const value = ctx.value();\n let isValid: boolean;\n if (!value) {\n isValid = (typeof flag === 'function' ? flag() : flag) === true;\n } else {\n try {\n isValid = value.isValid?.() === true;\n } catch {\n isValid = false;\n }\n }\n return isValid ? null : { kind: 'validIf', message: config?.message ?? ARS_VALIDATOR_MESSAGES['validIf'] };\n });\n}\n\n/**\n * Requires the value to be a semicolon-separated list of valid e-mail addresses.\n *\n * The signal-form counterpart of `EmailsValidatorDirective`. An empty value passes, and so does\n * an empty entry between two semicolons: the list is typed by hand and a trailing `;` is not a\n * mistake worth an error.\n *\n * @param path - Path of the field to validate.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function emails<TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<string, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const input = ctx.value();\n if (!input || input.length === 0) return null;\n const parts = input.replaceAll(/\\r\\n/g, '').split(';');\n const isValid = parts.every(part => part.length === 0 || !!SystemUtils.parseEmail(part));\n return isValid ? null : { kind: 'emails', message: config?.message ?? ARS_VALIDATOR_MESSAGES['emails'] };\n });\n}\n\n/**\n * Requires the value to be a `\"HH:MM\"` time and, when slots are given, to fall inside one of them.\n *\n * The signal-form counterpart of `TimeValidatorDirective`. An empty value passes.\n *\n * @param path - Path of the field to validate.\n * @param slots - Optional reactive function returning the pipe-separated allowed ranges\n * (e.g. `\"08:00-12:00|14:00-18:00\"`), or `undefined` for no restriction.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function time<TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\n slots?: () => string | undefined,\n config?: ArsValidatorConfig<string, TPathKind>\n): void {\n /**\n * Turns `\"HH:MM\"` into a comparable integer (`\"09:30\"` -> `930`).\n * @param value - The time string to parse.\n * @returns The comparable integer, or `-1` when the string is not a valid time.\n */\n const getTime = (value: string): number => {\n const p = value.split(':');\n if (p.length !== 2) return -1;\n const hh = parseInt(p[0], 10);\n if (isNaN(hh) || hh < 0 || hh > 23) return -1;\n const mm = parseInt(p[1], 10);\n if (isNaN(mm) || mm < 0 || mm > 59) return -1;\n return hh * 100 + mm;\n };\n\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const input = ctx.value();\n if (!input || input.length === 0) return null;\n const invalid = { kind: 'time', message: config?.message ?? ARS_VALIDATOR_MESSAGES['time'] };\n const t = getTime(input);\n if (t === -1) return invalid;\n const slotsValue = slots?.();\n if (slotsValue) {\n const inSlot = slotsValue.split('|').some(s => {\n const from = getTime(s.substring(0, 5));\n const to = getTime(s.substring(6));\n return from !== -1 && to !== -1 && from <= t && to >= t;\n });\n if (!inSlot) return invalid;\n }\n return null;\n });\n}\n\n/**\n * Requires the value to equal the value of another field of the same form.\n *\n * The signal-form counterpart of `EqualsValidatorDirective`. Reactive on both fields, which is\n * what the directive needed a `valueChanges` subscription to obtain: retyping the first password\n * re-validates the confirmation without anyone wiring the two together.\n *\n * @param path - Path of the field to validate.\n * @param other - Path of the field whose value must match.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function equals<TValue, TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,\n other: SchemaPath<TValue, SchemaPathRules.Supported>,\n config?: ArsValidatorConfig<TValue, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n return ctx.valueOf(other) === ctx.value()\n ? null\n : { kind: 'equals', message: config?.message ?? ARS_VALIDATOR_MESSAGES['equals'] };\n });\n}\n\n/**\n * Requires the value to be either empty or a complete six-digit one-time code.\n *\n * The schema-level counterpart of the validator inside `OtpInputComponent`: a partial code is an\n * error, an empty one is `required()`'s business.\n *\n * @param path - Path of the field to validate.\n * @param config - Optional message override and `when` condition.\n * @returns void\n */\nexport function otp<TPathKind extends PathKind = PathKind.Root>(\n path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>,\n config?: ArsValidatorConfig<string, TPathKind>\n): void {\n validate(path, ctx => {\n if (config?.when && !config.when(ctx)) return null;\n const input = ctx.value() ?? '';\n if (input.length === 0) return null;\n return /^\\d{6}$/.test(input)\n ? null\n : { kind: 'otp', message: config?.message ?? ARS_VALIDATOR_MESSAGES['otp'] };\n });\n}\n\n/** Helpers around signal forms that are not validators themselves. */\nexport class SignalsUtils {\n\n /**\n * Builds the error text for a signal-forms field.\n *\n * Deliberately dumb: the wording lives in the schema, next to the rule that produces it\n * (`required(p.x, { message: ... })`), so a field says what is wrong with it in one place\n * instead of here in a switch that has to guess from the error kind. The map below is only\n * the safety net for the rules declared without a message — the Angular built-ins, plus\n * {@link ARS_VALIDATOR_MESSAGES} for the ones declared in this file.\n * @param errors - The errors currently on the field, from `f.x().errors()`.\n * @param message - Optional override applied to every error of the field.\n * @returns The first relevant error text, or `undefined` when the field has no errors.\n */\n public static getFieldErrorMessage(\n errors: readonly { kind: string; message?: string }[],\n message?: string\n ): string | undefined {\n if (!errors || errors.length === 0) return undefined;\n\n const fallback: Record<string, string> = {\n // Angular built-ins declared without a message of their own.\n min: 'Valore troppo basso',\n max: 'Valore troppo alto',\n minLength: 'Testo troppo corto',\n maxLength: 'Testo troppo lungo',\n pattern: 'Formato non valido',\n email: 'Indirizzo email non valido',\n minDate: 'Data troppo indietro',\n maxDate: 'Data troppo avanti',\n parse: 'Valore non valido',\n matDatepickerParse: 'Data non valida',\n matDatepickerMin: 'Data troppo indietro',\n matDatepickerMax: 'Data troppo avanti',\n matDatepickerFilter: 'Data non selezionabile',\n matStartDateInvalid: 'Intervallo non valido',\n matEndDateInvalid: 'Intervallo non valido',\n matTimepickerParse: 'Orario non valido',\n matTimepickerMin: 'Orario troppo presto',\n matTimepickerMax: 'Orario troppo tardi',\n // The rules of this file, from the single table above: adding a validator there is enough,\n // and this map can never fall behind it.\n ...ARS_VALIDATOR_MESSAGES,\n };\n\n\n message = message ?? errors[0].message ?? fallback[errors[0].kind] ?? '';\n return message.length > 0 ? message : 'Non valido';\n }\n}\n","/*\n * Public API Surface of @arsedizioni/ars-utils/core.validators\n *\n * Template-driven form validators. Kept OUT of `core` on purpose: every one of them pulls in\n * `@angular/forms` (53 KB), and `core` is on the boot path of every application through\n * `ThemeService`, `BroadcastService` and friends. Importing a validator now costs `@angular/forms`\n * only to the lazy chunk that actually uses one.\n */\nexport * from './validators';\n\n// Signal-form flavour of the same rules. Lives here and not in a separate entry point because\n// `@angular/forms/signals` depends on `@angular/forms` anyway, so the two never travel apart.\nexport * from './signals';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
@@ -361,10 +361,24 @@ class TinymceEditorDirective {
361
361
  base_url: this.loader.baseUrl,
362
362
  inline,
363
363
  setup: (editor) => {
364
- // Typing, toolbar commands, undo/redo and programmatic inserts all have to
365
- // reach the form; the guard keeps our own writes from bouncing back.
364
+ /*
365
+ * Typing, toolbar commands, undo/redo and programmatic inserts all have to reach
366
+ * the form; the two guards keep everything else out.
367
+ *
368
+ * `writingValue` keeps our own writes from bouncing back. `!this.editor` — which
369
+ * stays unset until the `init` handler below — keeps out the one content event
370
+ * that fires BEFORE the editor exists, and it is the one that made an editor
371
+ * impossible to fill: TinyMCE's own `loadInitialContent` reads the textarea and
372
+ * calls `setContent(..., { initial: true })`, which dispatches `SetContent`
373
+ * because only `no_events` suppresses it. The textarea is empty — the form
374
+ * writes through the ControlValueAccessor, never into the DOM element — so this
375
+ * handler took that empty string for a user edit, overwrote the value the form
376
+ * had already handed us, and reported '' back to the model. `init` then applied
377
+ * the value it had just destroyed, and the editor came up blank whatever was
378
+ * passed to it. Saving from there stored the empty string as well.
379
+ */
366
380
  editor.on('change input undo redo SetContent', () => {
367
- if (this.writingValue)
381
+ if (this.writingValue || !this.editor)
368
382
  return;
369
383
  this.value = editor.getContent();
370
384
  this.onChange(this.value);
@@ -387,6 +401,9 @@ class TinymceEditorDirective {
387
401
  this.exitFullscreen();
388
402
  });
389
403
  editor.on('init', () => {
404
+ // Assigned BEFORE applying the value, and that order is the contract with
405
+ // the guard above: from here on content events are genuine, and the one
406
+ // raised by `applyValue` itself is covered by `writingValue`.
390
407
  this.editor = editor;
391
408
  this.applyValue(this.value);
392
409
  this.applyDisabled(this.disabled);
@@ -568,6 +585,17 @@ class TinyMceEditorComponent {
568
585
  /** Whether the editor is in read-only mode. */
569
586
  this.disabled = signal(false, /* @ts-ignore */
570
587
  ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
588
+ /**
589
+ * Why the editor could not be shown, when it could not.
590
+ *
591
+ * Without it a failure looked exactly like an empty document: the directive reported it on its
592
+ * `failed` output, nothing was listening, and the user was left with a blank box and no reason
593
+ * for it. The message is the directive's own — the bundle did not load, or TinyMCE refused to
594
+ * start — and it also goes to the console, because that is where whoever is asked about it will
595
+ * look first.
596
+ */
597
+ this.error = signal(undefined, /* @ts-ignore */
598
+ ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
571
599
  /** Current editor content. */
572
600
  this.text = signal('', /* @ts-ignore */
573
601
  ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
@@ -591,6 +619,15 @@ class TinyMceEditorComponent {
591
619
  this.tinymceConfig.toolbar = ['undo redo | quickimage insertgroup | formatgroup paragraphgroup | code'];
592
620
  this.disabled.set(data.disabled ?? false);
593
621
  }
622
+ /**
623
+ * Records that the editor could not be shown.
624
+ * @param error - What the directive could not do.
625
+ * @returns void
626
+ */
627
+ failed(error) {
628
+ console.error('[TinyMceEditorComponent] editor non disponibile', error);
629
+ this.error.set(error?.message || 'Editor non disponibile.');
630
+ }
594
631
  /**
595
632
  * Save the current editor content and close the dialog.
596
633
  */
@@ -601,12 +638,12 @@ class TinyMceEditorComponent {
601
638
  }, 500);
602
639
  }
603
640
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: TinyMceEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
604
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: TinyMceEditorComponent, isStandalone: true, selector: "ng-component", outputs: { saving: "saving" }, ngImport: i0, template: "<mat-dialog-content style=\"padding: 10px 10px 0 10px\">\n <textarea tinymceEditor class=\"full-screen-editor\" [tinymceConfig]=\"tinymceConfig\"\n [formField]=\"textForm\"></textarea>\n</mat-dialog-content>\n<mat-dialog-actions>\n <div fxLayout=\"row\" fxLayoutGap=\"10px\" fxLayoutAlign=\"start center\" fxFill>\n <div fxFlex=\"50\">\n @if(dialogData().onShowInfo) {\n <button mat-stroked-button (click)=\"dialogData().onShowInfo()\">{{dialogData().infoButtonLabel ?? 'Informazioni'}}\n </button>\n }\n </div>\n <div fxFlex=\"50\" fxLayoutAlign=\"end\">\n @if (disabled()) {\n <button mat-stroked-button [mat-dialog-close]=\"true\">Chiudi</button>\n } @else {\n <button mat-flat-button (click)=\"ok()\">Salva</button>\n <button mat-stroked-button [mat-dialog-close]=\"true\">Annulla</button>\n }\n </div>\n </div>\n</mat-dialog-actions>\n", styles: [".mat-mdc-dialog-content{height:calc(100% - 52px)!important;max-height:calc(100% - 52px)!important}::ng-deep .full-screen-editor+.tox-tinymce{height:100%!important}\n"], dependencies: [{ kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: TinymceEditorDirective, selector: "textarea[tinymceEditor], div[tinymceEditor]", inputs: ["tinymceConfig", "tinymceToolbarMode", "tinymceImageUploader"], outputs: ["ready", "failed"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "ngmodule", type: FlexLayoutModule }, { kind: "directive", type: i1.FxLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg] ", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i1.FxFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg] ", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i1.FxLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg] ", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i1.FxLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg] ", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i1.FxFlexFillDirective, selector: " [fxFlexFill], [fxFill], [fxFlexFill.xs], [fxFlexFill.sm], [fxFlexFill.md], [fxFlexFill.lg], [fxFlexFill.xl], [fxFlexFill.lt-sm], [fxFlexFill.lt-md], [fxFlexFill.lt-lg], [fxFlexFill.lt-xl], [fxFlexFill.gt-xs], [fxFlexFill.gt-sm], [fxFlexFill.gt-md], [fxFlexFill.gt-lg] ", inputs: ["fxFlexFill", "fxFill", "fxFlexFill.xs", "fxFlexFill.sm", "fxFlexFill.md", "fxFlexFill.lg", "fxFlexFill.xl", "fxFlexFill.lt-sm", "fxFlexFill.lt-md", "fxFlexFill.lt-lg", "fxFlexFill.lt-xl", "fxFlexFill.gt-xs", "fxFlexFill.gt-sm", "fxFlexFill.gt-md", "fxFlexFill.gt-lg"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
641
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: TinyMceEditorComponent, isStandalone: true, selector: "ng-component", outputs: { saving: "saving" }, ngImport: i0, template: "<mat-dialog-content style=\"padding: 10px 10px 0 10px\">\n @if (error()) {\n <!-- The textarea is gone with the editor that could not replace it: left in place it would be a\n plain box the form does not write into, which is the empty editor this message exists to\n explain. -->\n <div class=\"editor-error\">\n <div class=\"editor-error-title\">Non \u00E8 stato possibile aprire l'editor.</div>\n <div class=\"editor-error-detail\">{{ error() }}</div>\n <div class=\"editor-error-detail\">Il testo non \u00E8 stato modificato: chiudi e riprova.</div>\n </div>\n } @else {\n <textarea tinymceEditor class=\"full-screen-editor\" [tinymceConfig]=\"tinymceConfig\"\n [formField]=\"textForm\" (failed)=\"failed($event)\"></textarea>\n }\n</mat-dialog-content>\n<mat-dialog-actions>\n <div fxLayout=\"row\" fxLayoutGap=\"10px\" fxLayoutAlign=\"start center\" fxFill>\n <div fxFlex=\"50\">\n @if(dialogData().onShowInfo) {\n <button mat-stroked-button (click)=\"dialogData().onShowInfo()\">{{dialogData().infoButtonLabel ?? 'Informazioni'}}\n </button>\n }\n </div>\n <div fxFlex=\"50\" fxLayoutAlign=\"end\">\n <!-- Nothing to save when there was no editor: the only way out is the one that changes\n nothing. -->\n @if (disabled() || error()) {\n <button mat-stroked-button [mat-dialog-close]=\"true\">Chiudi</button>\n } @else {\n <button mat-flat-button (click)=\"ok()\">Salva</button>\n <button mat-stroked-button [mat-dialog-close]=\"true\">Annulla</button>\n }\n </div>\n </div>\n</mat-dialog-actions>\n", styles: [".mat-mdc-dialog-content{height:calc(100% - 52px)!important;max-height:calc(100% - 52px)!important}::ng-deep .full-screen-editor+.tox-tinymce{height:100%!important}.editor-error{display:flex;flex-direction:column;gap:6px;justify-content:center;align-items:center;height:100%;min-height:120px;padding:24px;text-align:center}.editor-error .editor-error-title{font-weight:500}.editor-error .editor-error-detail{font-size:small;opacity:.8}\n"], dependencies: [{ kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: TinymceEditorDirective, selector: "textarea[tinymceEditor], div[tinymceEditor]", inputs: ["tinymceConfig", "tinymceToolbarMode", "tinymceImageUploader"], outputs: ["ready", "failed"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"], exportAs: ["formField"] }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "ngmodule", type: FlexLayoutModule }, { kind: "directive", type: i1.FxLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg] ", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i1.FxFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg] ", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i1.FxLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg] ", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i1.FxLayoutGapDirective, selector: " [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg] ", inputs: ["fxLayoutGap", "fxLayoutGap.xs", "fxLayoutGap.sm", "fxLayoutGap.md", "fxLayoutGap.lg", "fxLayoutGap.xl", "fxLayoutGap.lt-sm", "fxLayoutGap.lt-md", "fxLayoutGap.lt-lg", "fxLayoutGap.lt-xl", "fxLayoutGap.gt-xs", "fxLayoutGap.gt-sm", "fxLayoutGap.gt-md", "fxLayoutGap.gt-lg"] }, { kind: "directive", type: i1.FxFlexFillDirective, selector: " [fxFlexFill], [fxFill], [fxFlexFill.xs], [fxFlexFill.sm], [fxFlexFill.md], [fxFlexFill.lg], [fxFlexFill.xl], [fxFlexFill.lt-sm], [fxFlexFill.lt-md], [fxFlexFill.lt-lg], [fxFlexFill.lt-xl], [fxFlexFill.gt-xs], [fxFlexFill.gt-sm], [fxFlexFill.gt-md], [fxFlexFill.gt-lg] ", inputs: ["fxFlexFill", "fxFill", "fxFlexFill.xs", "fxFlexFill.sm", "fxFlexFill.md", "fxFlexFill.lg", "fxFlexFill.xl", "fxFlexFill.lt-sm", "fxFlexFill.lt-md", "fxFlexFill.lt-lg", "fxFlexFill.lt-xl", "fxFlexFill.gt-xs", "fxFlexFill.gt-sm", "fxFlexFill.gt-md", "fxFlexFill.gt-lg"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
605
642
  }
606
643
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: TinyMceEditorComponent, decorators: [{
607
644
  type: Component,
608
645
  args: [{ standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatDialogContent, TinymceEditorDirective, FormField, MatDialogActions, FlexLayoutModule,
609
- MatButtonModule, MatDialogClose], template: "<mat-dialog-content style=\"padding: 10px 10px 0 10px\">\n <textarea tinymceEditor class=\"full-screen-editor\" [tinymceConfig]=\"tinymceConfig\"\n [formField]=\"textForm\"></textarea>\n</mat-dialog-content>\n<mat-dialog-actions>\n <div fxLayout=\"row\" fxLayoutGap=\"10px\" fxLayoutAlign=\"start center\" fxFill>\n <div fxFlex=\"50\">\n @if(dialogData().onShowInfo) {\n <button mat-stroked-button (click)=\"dialogData().onShowInfo()\">{{dialogData().infoButtonLabel ?? 'Informazioni'}}\n </button>\n }\n </div>\n <div fxFlex=\"50\" fxLayoutAlign=\"end\">\n @if (disabled()) {\n <button mat-stroked-button [mat-dialog-close]=\"true\">Chiudi</button>\n } @else {\n <button mat-flat-button (click)=\"ok()\">Salva</button>\n <button mat-stroked-button [mat-dialog-close]=\"true\">Annulla</button>\n }\n </div>\n </div>\n</mat-dialog-actions>\n", styles: [".mat-mdc-dialog-content{height:calc(100% - 52px)!important;max-height:calc(100% - 52px)!important}::ng-deep .full-screen-editor+.tox-tinymce{height:100%!important}\n"] }]
646
+ MatButtonModule, MatDialogClose], template: "<mat-dialog-content style=\"padding: 10px 10px 0 10px\">\n @if (error()) {\n <!-- The textarea is gone with the editor that could not replace it: left in place it would be a\n plain box the form does not write into, which is the empty editor this message exists to\n explain. -->\n <div class=\"editor-error\">\n <div class=\"editor-error-title\">Non \u00E8 stato possibile aprire l'editor.</div>\n <div class=\"editor-error-detail\">{{ error() }}</div>\n <div class=\"editor-error-detail\">Il testo non \u00E8 stato modificato: chiudi e riprova.</div>\n </div>\n } @else {\n <textarea tinymceEditor class=\"full-screen-editor\" [tinymceConfig]=\"tinymceConfig\"\n [formField]=\"textForm\" (failed)=\"failed($event)\"></textarea>\n }\n</mat-dialog-content>\n<mat-dialog-actions>\n <div fxLayout=\"row\" fxLayoutGap=\"10px\" fxLayoutAlign=\"start center\" fxFill>\n <div fxFlex=\"50\">\n @if(dialogData().onShowInfo) {\n <button mat-stroked-button (click)=\"dialogData().onShowInfo()\">{{dialogData().infoButtonLabel ?? 'Informazioni'}}\n </button>\n }\n </div>\n <div fxFlex=\"50\" fxLayoutAlign=\"end\">\n <!-- Nothing to save when there was no editor: the only way out is the one that changes\n nothing. -->\n @if (disabled() || error()) {\n <button mat-stroked-button [mat-dialog-close]=\"true\">Chiudi</button>\n } @else {\n <button mat-flat-button (click)=\"ok()\">Salva</button>\n <button mat-stroked-button [mat-dialog-close]=\"true\">Annulla</button>\n }\n </div>\n </div>\n</mat-dialog-actions>\n", styles: [".mat-mdc-dialog-content{height:calc(100% - 52px)!important;max-height:calc(100% - 52px)!important}::ng-deep .full-screen-editor+.tox-tinymce{height:100%!important}.editor-error{display:flex;flex-direction:column;gap:6px;justify-content:center;align-items:center;height:100%;min-height:120px;padding:24px;text-align:center}.editor-error .editor-error-title{font-weight:500}.editor-error .editor-error-detail{font-size:small;opacity:.8}\n"] }]
610
647
  }], ctorParameters: () => [], propDecorators: { saving: [{ type: i0.Output, args: ["saving"] }] } });
611
648
 
612
649
  /*
@@ -1 +1 @@
1
- {"version":3,"file":"arsedizioni-ars-utils-ui.tinymce.mjs","sources":["../../../projects/ars-utils/ui.tinymce/utils.ts","../../../projects/ars-utils/ui.tinymce/tinymce-loader.service.ts","../../../projects/ars-utils/ui.tinymce/tinymce-editor.directive.ts","../../../projects/ars-utils/ui.tinymce/editor/editor.component.ts","../../../projects/ars-utils/ui.tinymce/editor/editor.component.html","../../../projects/ars-utils/ui.tinymce/public_api.ts","../../../projects/ars-utils/ui.tinymce/arsedizioni-ars-utils-ui.tinymce.ts"],"sourcesContent":["import type { RawEditorOptions } from 'tinymce';\n\n/**\n * The editor profiles the applications ask for, ready to be handed to\n * `[tinymceConfig]` on {@link TinymceEditorDirective}.\n *\n * They describe **what the editor offers** — plugins, toolbar, formats, link and image\n * behaviour — and nothing else. Everything about *loading* TinyMCE (`base_url`, `suffix`,\n * `language`, `language_url`, `license_key`) and about the *theme* (`skin`, `content_css`)\n * belongs to `TinymceLoaderService` and to the directive, which resolve them against the\n * document base href and against `ThemeService`: a preset repeating them could only get them\n * wrong, and used to — the old ones pinned a relative `assets/tinymce` that broke under a\n * sub-path, and read the skin from `prefers-color-scheme` instead of the theme the user chose.\n *\n * Uploads are the same story: `automatic_uploads`, `paste_data_images` and `file_picker_types`\n * follow the `tinymceImageUploader` input, so an editor without a handler cannot end up\n * offering an upload tab that leads nowhere.\n *\n * Each accessor returns a **fresh deep copy**: a caller that tweaks a returned object — as the\n * editor dialog does with its toolbar — cannot corrupt the preset for everyone else.\n */\nexport class TinymceUtils {\n\n /**\n * Everything TinyMCE 8 open source has to offer, for a full-page editor.\n *\n * Adapted from the TinyMCE 5 profile the library used to ship: `paste`, `print`, `hr`,\n * `textpattern` and the `fullpage_*` options no longer exist (paste and text patterns moved\n * into the core, `fullpage` and `print` were dropped in v6), and `checklist`,\n * `openCodeMirrorButton` and `insertMediaButton` are premium or application-specific buttons\n * that a self-hosted GPL build has no way to render.\n */\n private static readonly FULL: RawEditorOptions = {\n height: 500,\n width: '100%',\n min_height: 250,\n onboarding: false,\n browser_spellcheck: true,\n custom_undo_redo_levels: 50,\n // Three &nbsp; per TAB, and no wrapping of the inserted spaces.\n nonbreaking_force_tab: true,\n nonbreaking_wrap: false,\n help_tabs: ['shortcuts', 'keyboardnav', 'versions'],\n menubar: false,\n plugins: 'advlist anchor autolink autosave charmap code fullscreen help image insertdatetime'\n + ' link lists media nonbreaking pagebreak preview quickbars searchreplace table'\n + ' visualblocks visualchars',\n toolbar: [\n 'fullscreen | undo redo searchreplace | code preview | link image media charmap nonbreaking | table tableprops tabledelete',\n 'bold italic superscript subscript forecolor backcolor | alignleft aligncenter alignright alignjustify | removeformat | bullist numlist'\n ],\n quickbars_insert_toolbar: false,\n quickbars_selection_toolbar: 'removeformat | bold italic | superscript subscript | quicklink h2 h3 blockquote',\n style_formats: [\n {\n title: 'Immagini float', items: [\n { title: 'Immagine a SX', selector: 'img', styles: { float: 'left', margin: '0 10px 0 10px' } },\n { title: 'Immagine a DX', selector: 'img', styles: { float: 'right', margin: '0 10px 0 10px' } }\n ]\n },\n {\n title: 'Formati', items: [\n { title: 'Grassetto', format: 'bold' },\n { title: 'Corsivo', format: 'italic' },\n { title: 'Sottolineato', format: 'underline' },\n { title: 'Barrato', format: 'strikethrough' },\n { title: 'Superscript', format: 'superscript' },\n { title: 'Subscript', format: 'subscript' },\n { title: 'Codice', format: 'code' }\n ]\n }\n ],\n // Spans with an inline style rather than <u>/<strike>: the content travels by e-mail, where\n // the presentational tags are the first thing a client strips.\n formats: {\n underline: { inline: 'span', styles: { 'text-decoration': 'underline' }, exact: true },\n strikethrough: { inline: 'span', styles: { 'text-decoration': 'line-through' }, exact: true }\n },\n insertdatetime_formats: ['%d/%m/%Y', '%d %b %Y', '%A, %d %B %Y'],\n link_default_target: '_blank',\n link_title: true,\n link_assume_external_targets: 'https',\n link_class_list: [\n { title: 'Nessuno', value: '' },\n { title: 'Rilevante', value: 'relevant' },\n ],\n link_context_toolbar: true,\n link_quicklink: true,\n image_advtab: true,\n image_caption: true,\n image_title: true,\n };\n\n /**\n * The one for a field inside a form: it grows with the text instead of owning the page, the\n * toolbar sits under it and collapses into groups, and there is no status bar or context menu\n * to compete with the form around it.\n */\n private static readonly COMPACT: RawEditorOptions = {\n ...TinymceUtils.FULL,\n height: 200,\n min_height: 200,\n max_height: 500,\n statusbar: false,\n contextmenu: false,\n toolbar_location: 'bottom',\n plugins: 'advlist anchor autolink autoresize autosave charmap code image insertdatetime'\n + ' link lists media nonbreaking preview quickbars searchreplace table'\n + ' visualblocks visualchars',\n toolbar: ['undo redo | quickimage | formatgroup paragraphgroup'],\n toolbar_groups: {\n formatgroup: {\n icon: 'format',\n tooltip: 'Formattazione',\n items: 'bold italic underline superscript subscript | forecolor backcolor | removeformat'\n },\n paragraphgroup: {\n icon: 'paragraph',\n tooltip: 'Formato paragrafo',\n items: 'h1 h2 h3 | bullist numlist | alignleft aligncenter alignright alignjustify | indent outdent'\n },\n insertgroup: {\n icon: 'plus',\n tooltip: 'Inserisci',\n items: 'quickimage media | link charmap nonbreaking | table tableprops tabledelete'\n }\n },\n quickbars_insert_toolbar: 'quickimage',\n link_class_list: [],\n };\n\n /** The compact one plus full screen, the insert group and the source view. */\n private static readonly COMPACT_EXTENDED: RawEditorOptions = {\n ...TinymceUtils.COMPACT,\n plugins: 'advlist anchor autolink autoresize autosave charmap code fullscreen image'\n + ' insertdatetime link lists media nonbreaking preview quickbars searchreplace table'\n + ' visualblocks visualchars',\n toolbar: ['undo redo | quickimage insertgroup | formatgroup paragraphgroup | code | fullscreen'],\n };\n\n /**\n * The full-page profile.\n * @returns A fresh copy of the configuration, safe to modify.\n */\n static get TinymceConfig(): RawEditorOptions {\n return structuredClone(TinymceUtils.FULL);\n }\n\n /**\n * The in-form profile.\n * @returns A fresh copy of the configuration, safe to modify.\n */\n static get TinymceCompactConfig(): RawEditorOptions {\n return structuredClone(TinymceUtils.COMPACT);\n }\n\n /**\n * The in-form profile with full screen and source view.\n * @returns A fresh copy of the configuration, safe to modify.\n */\n static get TinymceCompactExtendedConfig(): RawEditorOptions {\n return structuredClone(TinymceUtils.COMPACT_EXTENDED);\n }\n}\n","import { Service } from '@angular/core';\nimport type { TinyMCE } from 'tinymce';\n\ndeclare global {\n interface Window {\n tinymce?: TinyMCE;\n }\n}\n\n/**\n * Loads the self-hosted TinyMCE bundle on demand.\n *\n * TinyMCE is deliberately NOT imported by any module: a static import would pull ~500 kB into\n * whichever chunk referenced it, and the editor is needed by exactly one dialog. The library is\n * copied to `assets/tinymce` by the build (see `angular.json`) and injected here as a plain\n * `<script>` the first time an editor is created, so it costs nothing until then and is served\n * from the browser cache afterwards. Loading it this way also lets TinyMCE resolve its own theme,\n * model, plugins and skin relative to `base_url`, which is how the self-hosted distribution\n * expects to work.\n */\n@Service()\nexport class TinymceLoaderService {\n\n /** The in-flight (or completed) load, so concurrent editors share a single script tag. */\n private pending?: Promise<TinyMCE>;\n\n /**\n * The absolute URL of the TinyMCE asset folder, resolved against the document base href so the\n * app keeps working when it is served from a sub-path.\n * @returns The base URL, without a trailing slash.\n */\n get baseUrl(): string {\n return new URL('assets/tinymce', document.baseURI).href.replace(/\\/$/, '');\n }\n\n /**\n * Loads TinyMCE, reusing the script already injected by a previous call.\n * @returns A promise resolving with the global TinyMCE instance.\n */\n load(): Promise<TinyMCE> {\n if (window.tinymce) return Promise.resolve(window.tinymce);\n\n // A failed load clears `pending`, so a later attempt can retry instead of being stuck on the\n // rejected promise forever (e.g. the first open happened while the network was down).\n this.pending ??= new Promise<TinyMCE>((resolve, reject) => {\n const script = document.createElement('script');\n script.src = `${this.baseUrl}/tinymce.min.js`;\n script.async = true;\n script.referrerPolicy = 'origin';\n script.onload = () => {\n if (window.tinymce) {\n resolve(window.tinymce);\n } else {\n this.pending = undefined;\n reject(new Error('TinyMCE caricato ma non disponibile.'));\n }\n };\n script.onerror = () => {\n this.pending = undefined;\n script.remove();\n reject(new Error('Impossibile caricare l\\'editor.'));\n };\n document.head.appendChild(script);\n });\n\n return this.pending;\n }\n}\n","import {\n ChangeDetectorRef,\n Directive,\n ElementRef,\n OnDestroy,\n OnInit,\n forwardRef,\n inject,\n input,\n output\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { ThemeService } from '@arsedizioni/ars-utils/core';\nimport type { Editor, RawEditorOptions } from 'tinymce';\nimport { TinymceLoaderService } from './tinymce-loader.service';\n\n/** Uploads one image and resolves with the URL to reference it by. */\nexport type TinymceImageUploader = (file: File) => Promise<string>;\n\n/**\n * How the editor presents itself.\n *\n * `fixed` is the classic editor: the content lives in an iframe and the toolbar sits above it,\n * pinned so it stays reachable while the surrounding container scrolls.\n *\n * `inline` edits the host element in place, with no iframe and no chrome until the user focuses\n * it, at which point the toolbar floats over the content. It needs an ordinary element to edit —\n * a `<div>` — because there is nothing to render inside a `<textarea>`.\n */\nexport type TinymceToolbarMode = 'fixed' | 'inline';\n\n/**\n * Turns a `<textarea>` into a rich text editor backed by the self-hosted TinyMCE bundle, and wires\n * it to Angular forms as a `ControlValueAccessor`, so `[(ngModel)]`, `required` and the\n * pristine/dirty state keep working exactly as they do on a plain control.\n *\n * The library itself is fetched on demand by <see cref=\"TinymceLoaderService\"/>: nothing about\n * TinyMCE reaches the bundle until an editor is actually created.\n *\n * Usage: `<textarea tinymceEditor [(ngModel)]=\"item.text\" name=\"text\" required></textarea>`\n *\n */\n@Directive({\n // Both hosts are accepted because the two modes need different ones: the classic editor\n // replaces a textarea, the inline editor edits a div in place.\n selector: 'textarea[tinymceEditor], div[tinymceEditor]',\n providers: [{\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => TinymceEditorDirective),\n multi: true\n }]\n})\nexport class TinymceEditorDirective implements ControlValueAccessor, OnInit, OnDestroy {\n\n /** Extra TinyMCE options, merged over (and able to override) the defaults below. */\n readonly tinymceConfig = input<RawEditorOptions>({});\n\n /** Whether the toolbar is pinned above the content (`fixed`) or floats on focus (`inline`). */\n readonly tinymceToolbarMode = input<TinymceToolbarMode>('fixed');\n\n /**\n * Handler invoked for every image dropped, pasted or picked in the editor. When not provided\n * the upload tab is hidden and only images referenced by URL can be inserted.\n */\n readonly tinymceImageUploader = input<TinymceImageUploader | undefined>(undefined);\n\n /** Emitted once the editor is up, for callers that want to enable UI only when it is usable. */\n readonly ready = output<Editor>();\n\n /** Emitted when the editor could not be loaded or initialised. */\n readonly failed = output<Error>();\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly loader = inject(TinymceLoaderService);\n private readonly themeService = inject(ThemeService);\n private readonly changeDetector = inject(ChangeDetectorRef);\n\n private editor?: Editor;\n /** True while the editor is showing itself full screen. */\n private fullscreen = false;\n /** True once the directive has been destroyed, so a late init resolves into a no-op. */\n private destroyed = false;\n /**\n * True while the directive itself is pushing a value into the editor. TinyMCE raises the same\n * content events for a programmatic `setContent` as for a keystroke, so without this flag\n * `writeValue` would immediately echo back through `onChange` and mark a freshly loaded form\n * as dirty.\n */\n private writingValue = false;\n /** The value received before the editor existed, applied as soon as it does. */\n private value = '';\n private disabled = false;\n\n private onChange: (value: string) => void = () => { /* set by Angular forms */ };\n private onTouched: () => void = () => { /* set by Angular forms */ };\n\n /**\n * Leaves full screen on Escape, for the keystrokes that happen outside the content: with the\n * classic editor the content is an iframe, and a keydown in there never reaches this document.\n * Bound on the capture phase and stopped, so a dialog hosting the editor does not take the\n * Escape and close, throwing the edit away when the user only meant to leave full screen.\n */\n private readonly onDocumentKeydown = (event: KeyboardEvent): void => {\n if (!this.shouldEscapeLeaveFullscreen(event)) return;\n event.preventDefault();\n event.stopPropagation();\n this.exitFullscreen();\n };\n\n /**\n * Loads TinyMCE and initialises the editor over the host textarea.\n * @returns A promise that completes once the editor is ready (or has failed).\n */\n async ngOnInit(): Promise<void> {\n try {\n const tinymce = await this.loader.load();\n if (this.destroyed) return;\n\n const dark = this.themeService.getTheme() === 'dark';\n const uploader = this.tinymceImageUploader();\n const inline = this.tinymceToolbarMode() === 'inline';\n\n // Caught here rather than left to TinyMCE, which would fail deep inside its own setup\n // with a message that says nothing about the actual mistake.\n if (inline && this.host.nativeElement.tagName === 'TEXTAREA') {\n throw new Error('La modalità inline richiede un <div>, non un <textarea>.');\n }\n\n // TinyMCE ships its language packs outside the npm package, so `it.js` is committed\n // under `src/assets/tinymce/langs/`: the existing `src/assets` build rule publishes it\n // exactly where TinyMCE looks for it, relative to `base_url`.\n const defaults: RawEditorOptions = {\n // Self-hosting TinyMCE 8 requires an explicit license key: without one the editor\n // refuses to start. 'gpl' selects the GPLv2+ terms.\n license_key: 'gpl',\n language: 'it',\n branding: false,\n promotion: false,\n menubar: false,\n statusbar: false,\n resize: false,\n // Pins the toolbar while the container scrolls. In inline mode it is what keeps\n // the floating toolbar attached to the text instead of drifting off with it.\n toolbar_sticky: true,\n // An inline editor takes the size of the element it edits; only the classic one\n // has a box of its own to dimension.\n ...(inline ? {} : { height: 360 }),\n // The dialog body scrolls, and 'split' is what keeps the toolbar menus anchored\n // to the editor while it does: the popup sink is attached next to the editor, so\n // it shares its scrolling ancestry. It does NOT affect the modal dialogs — those\n // always go to <body> — which is why the CDK overlay has to be kept out of the\n // top layer (see OVERLAY_DEFAULT_CONFIG in app.config.ts).\n ui_mode: 'split',\n skin: dark ? 'oxide-dark' : 'oxide',\n content_css: dark ? 'dark' : 'default',\n // Absolute URLs must survive untouched: the content ends up in an e-mail, where a\n // relative image path resolves against nothing.\n convert_urls: false,\n plugins: 'advlist autolink lists link image table charmap searchreplace code fullscreen',\n toolbar: 'undo redo | blocks | bold italic underline | forecolor backcolor'\n + ' | bullist numlist | link image table | removeformat code fullscreen',\n content_style: 'body { font-family: Arial, Helvetica, sans-serif; font-size: 14px; }',\n // Pasted and dropped images go through the same upload path as the image dialog.\n automatic_uploads: !!uploader,\n paste_data_images: !!uploader,\n images_file_types: 'jpeg,jpg,png,gif,webp',\n file_picker_types: uploader ? 'image' : '',\n images_upload_handler: uploader\n ? (blobInfo) => uploader(new File([blobInfo.blob()], blobInfo.filename(), { type: blobInfo.blob().type }))\n : undefined,\n };\n\n await tinymce.init({\n ...defaults,\n // The caller's profile wins over every default above: that is what the presets in\n // `TinymceUtils` are for.\n ...this.tinymceConfig(),\n // Not negotiable, whatever the profile says. `target` and `base_url` are resolved\n // here and nowhere else, `inline` is the input's job, and replacing `setup` would\n // unhook the editor from the form and leave a ControlValueAccessor that never\n // reports a change.\n target: this.host.nativeElement,\n base_url: this.loader.baseUrl,\n inline,\n setup: (editor: Editor) => {\n // Typing, toolbar commands, undo/redo and programmatic inserts all have to\n // reach the form; the guard keeps our own writes from bouncing back.\n editor.on('change input undo redo SetContent', () => {\n if (this.writingValue) return;\n this.value = editor.getContent();\n this.onChange(this.value);\n this.changeDetector.markForCheck();\n });\n editor.on('blur', () => {\n this.onTouched();\n this.changeDetector.markForCheck();\n });\n editor.on('FullscreenStateChanged', (event) => {\n this.handleFullscreenChanged((event as unknown as { state?: boolean }).state === true);\n });\n // The content of a classic editor lives in an iframe, so its keystrokes are\n // only visible from the editor itself.\n editor.on('keydown', (event) => {\n if (!this.shouldEscapeLeaveFullscreen(event)) return;\n event.preventDefault();\n event.stopPropagation();\n this.exitFullscreen();\n });\n editor.on('init', () => {\n this.editor = editor;\n this.applyValue(this.value);\n this.applyDisabled(this.disabled);\n this.ready.emit(editor);\n this.changeDetector.markForCheck();\n });\n },\n });\n } catch (error) {\n if (this.destroyed) return;\n this.failed.emit(error instanceof Error ? error : new Error(String(error)));\n this.changeDetector.markForCheck();\n }\n }\n\n /**\n * Tears the editor down. TinyMCE keeps global state per instance, so leaving it behind when a\n * dialog closes leaks both DOM and editor registrations.\n * @returns void\n */\n ngOnDestroy(): void {\n this.destroyed = true;\n // Removing the editor does not raise the full-screen event, so the session is closed by\n // hand here: the Escape listener would otherwise stay attached to the document forever.\n this.releaseFullscreen();\n this.editor?.remove();\n this.editor = undefined;\n }\n\n /**\n * Decides whether an Escape press means \"leave full screen\": it does whenever the editor is\n * full screen, full stop. While full screen the editor owns Escape, and the press is stopped\n * here so it can never reach the dialog hosting it — leaving full screen must not also throw\n * away what is being written.\n * @param event The keyboard event, from the document or from the editor's content.\n * @returns True when full screen should be left.\n */\n private shouldEscapeLeaveFullscreen(event: KeyboardEvent): boolean {\n return event.key === 'Escape' && this.fullscreen;\n }\n\n /**\n * Asks the editor to leave full screen. Safe to call when it is not in full screen.\n * @returns void\n */\n private exitFullscreen(): void {\n if (!this.fullscreen) return;\n this.editor?.execCommand('mceFullScreen');\n }\n\n /**\n * Attaches or detaches everything that only makes sense while the editor is full screen.\n * @param state True when the editor has just entered full screen.\n * @returns void\n */\n private handleFullscreenChanged(state: boolean): void {\n if (state === this.fullscreen) return;\n this.fullscreen = state;\n\n if (state) {\n document.addEventListener('keydown', this.onDocumentKeydown, true);\n } else {\n this.releaseFullscreen();\n }\n\n this.changeDetector.markForCheck();\n }\n\n /**\n * Detaches the listener that only makes sense while the editor is full screen.\n * @returns void\n */\n private releaseFullscreen(): void {\n document.removeEventListener('keydown', this.onDocumentKeydown, true);\n this.fullscreen = false;\n }\n\n /**\n * Pushes a value coming from the form into the editor.\n * @param value The new content, or null/undefined for an empty editor.\n * @returns void\n */\n writeValue(value: string | null | undefined): void {\n this.value = value ?? '';\n this.applyValue(this.value);\n }\n\n /**\n * Registers the callback used to report content changes to the form.\n * @param fn The callback supplied by Angular forms.\n * @returns void\n */\n registerOnChange(fn: (value: string) => void): void {\n this.onChange = fn;\n }\n\n /**\n * Registers the callback used to report the first blur to the form.\n * @param fn The callback supplied by Angular forms.\n * @returns void\n */\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n /**\n * Enables or disables editing.\n * @param isDisabled True to switch the editor to read-only.\n * @returns void\n */\n setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n this.applyDisabled(isDisabled);\n }\n\n /**\n * Writes content into the editor when it exists, guarding against the echo described on\n * <see cref=\"writingValue\"/>.\n * @param value The content to write.\n * @returns void\n */\n private applyValue(value: string): void {\n const editor = this.editor;\n if (!editor) return;\n // Comparing with the serialized content avoids resetting the caret on every form patch\n // that did not actually change anything.\n if (editor.getContent() === value) return;\n this.writingValue = true;\n try {\n editor.setContent(value);\n } finally {\n this.writingValue = false;\n }\n }\n\n /**\n * Applies the disabled state to the editor when it exists.\n * @param isDisabled True to switch the editor to read-only.\n * @returns void\n */\n private applyDisabled(isDisabled: boolean): void {\n this.editor?.mode.set(isDisabled ? 'readonly' : 'design');\n }\n}\n","import { ChangeDetectionStrategy, Component, inject, output, signal } from '@angular/core';\nimport { FormField, disabled as fieldDisabled, form } from '@angular/forms/signals';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MAT_DIALOG_DATA, MatDialogActions, MatDialogClose, MatDialogContent, MatDialogRef } from '@angular/material/dialog';\nimport { FlexLayoutModule } from '@arsedizioni/ars-utils/ui';\nimport type { RawEditorOptions } from 'tinymce';\nimport { TinymceEditorDirective } from '../tinymce-editor.directive';\nimport { TinymceUtils } from '../utils';\n\nexport interface TinyMceEditorDialogData {\n text: string;\n configuration: RawEditorOptions;\n infoButtonLabel?: string;\n onShowInfo?: Function,\n disabled?: boolean;\n}\n\n/**\n * A dialog that is nothing but an editor: the caller hands it a text and gets the edited one\n * back through {@link saving}.\n *\n * The editor is {@link TinymceEditorDirective} on a plain `<textarea>`, so this dialog costs\n * exactly what any other editor in the application costs — the TinyMCE bundle is fetched on\n * first use and nothing about it reaches the initial chunk.\n */\n@Component({\n templateUrl: './editor.component.html',\n styleUrls: ['./editor.component.scss'],\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [MatDialogContent, TinymceEditorDirective, FormField, MatDialogActions, FlexLayoutModule,\n MatButtonModule, MatDialogClose]\n})\nexport class TinyMceEditorComponent {\n\n /** Emitted with the edited text when the user saves. */\n readonly saving = output<string>();\n private readonly dialogRef = inject(MatDialogRef<TinyMceEditorComponent>);\n /** Dialog configuration, injected and exposed as a signal. */\n protected readonly dialogData = signal<TinyMceEditorDialogData>((() => {\n const data: TinyMceEditorDialogData = inject(MAT_DIALOG_DATA) ?? {};\n return { ...data, text: data.text ?? '' };\n })());\n /** Whether the editor is in read-only mode. */\n protected readonly disabled = signal<boolean>(false);\n /** Current editor content. */\n protected readonly text = signal<string>('');\n\n /**\n * Signal form bound to the editor textarea. The disabled state is pushed to the\n * TinymceEditorDirective through the ControlValueAccessor interop.\n */\n protected readonly textForm = form(this.text, p => {\n fieldDisabled(p, () => this.disabled());\n });\n /** The profile handed to the editor directive, merged over its defaults. */\n protected tinymceConfig: RawEditorOptions = {};\n\n constructor() {\n const data = this.dialogData();\n this.text.set(data.text);\n // The accessor already returns a private copy, so the toolbar override below cannot leak\n // into the preset shared with the rest of the application.\n this.tinymceConfig = data.configuration\n ? { ...data.configuration }\n : TinymceUtils.TinymceCompactExtendedConfig;\n // No full screen: the editor already owns the whole dialog.\n this.tinymceConfig.toolbar = ['undo redo | quickimage insertgroup | formatgroup paragraphgroup | code'];\n this.disabled.set(data.disabled ?? false);\n }\n\n\n /**\n * Save the current editor content and close the dialog.\n */\n protected ok(): void {\n this.saving.emit(this.text() ?? '');\n setTimeout(() => {\n this.dialogRef.close();\n }, 500);\n }\n}\n","<mat-dialog-content style=\"padding: 10px 10px 0 10px\">\n <textarea tinymceEditor class=\"full-screen-editor\" [tinymceConfig]=\"tinymceConfig\"\n [formField]=\"textForm\"></textarea>\n</mat-dialog-content>\n<mat-dialog-actions>\n <div fxLayout=\"row\" fxLayoutGap=\"10px\" fxLayoutAlign=\"start center\" fxFill>\n <div fxFlex=\"50\">\n @if(dialogData().onShowInfo) {\n <button mat-stroked-button (click)=\"dialogData().onShowInfo()\">{{dialogData().infoButtonLabel ?? 'Informazioni'}}\n </button>\n }\n </div>\n <div fxFlex=\"50\" fxLayoutAlign=\"end\">\n @if (disabled()) {\n <button mat-stroked-button [mat-dialog-close]=\"true\">Chiudi</button>\n } @else {\n <button mat-flat-button (click)=\"ok()\">Salva</button>\n <button mat-stroked-button [mat-dialog-close]=\"true\">Annulla</button>\n }\n </div>\n </div>\n</mat-dialog-actions>\n","/*\n * Public API Surface of @arsedizioni/ars-utils/ui.tinymce\n */\nexport * from './utils';\nexport * from './tinymce-loader.service';\nexport * from './tinymce-editor.directive';\nexport * from './editor/editor.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["fieldDisabled"],"mappings":"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"}
1
+ {"version":3,"file":"arsedizioni-ars-utils-ui.tinymce.mjs","sources":["../../../projects/ars-utils/ui.tinymce/utils.ts","../../../projects/ars-utils/ui.tinymce/tinymce-loader.service.ts","../../../projects/ars-utils/ui.tinymce/tinymce-editor.directive.ts","../../../projects/ars-utils/ui.tinymce/editor/editor.component.ts","../../../projects/ars-utils/ui.tinymce/editor/editor.component.html","../../../projects/ars-utils/ui.tinymce/public_api.ts","../../../projects/ars-utils/ui.tinymce/arsedizioni-ars-utils-ui.tinymce.ts"],"sourcesContent":["import type { RawEditorOptions } from 'tinymce';\n\n/**\n * The editor profiles the applications ask for, ready to be handed to\n * `[tinymceConfig]` on {@link TinymceEditorDirective}.\n *\n * They describe **what the editor offers** — plugins, toolbar, formats, link and image\n * behaviour — and nothing else. Everything about *loading* TinyMCE (`base_url`, `suffix`,\n * `language`, `language_url`, `license_key`) and about the *theme* (`skin`, `content_css`)\n * belongs to `TinymceLoaderService` and to the directive, which resolve them against the\n * document base href and against `ThemeService`: a preset repeating them could only get them\n * wrong, and used to — the old ones pinned a relative `assets/tinymce` that broke under a\n * sub-path, and read the skin from `prefers-color-scheme` instead of the theme the user chose.\n *\n * Uploads are the same story: `automatic_uploads`, `paste_data_images` and `file_picker_types`\n * follow the `tinymceImageUploader` input, so an editor without a handler cannot end up\n * offering an upload tab that leads nowhere.\n *\n * Each accessor returns a **fresh deep copy**: a caller that tweaks a returned object — as the\n * editor dialog does with its toolbar — cannot corrupt the preset for everyone else.\n */\nexport class TinymceUtils {\n\n /**\n * Everything TinyMCE 8 open source has to offer, for a full-page editor.\n *\n * Adapted from the TinyMCE 5 profile the library used to ship: `paste`, `print`, `hr`,\n * `textpattern` and the `fullpage_*` options no longer exist (paste and text patterns moved\n * into the core, `fullpage` and `print` were dropped in v6), and `checklist`,\n * `openCodeMirrorButton` and `insertMediaButton` are premium or application-specific buttons\n * that a self-hosted GPL build has no way to render.\n */\n private static readonly FULL: RawEditorOptions = {\n height: 500,\n width: '100%',\n min_height: 250,\n onboarding: false,\n browser_spellcheck: true,\n custom_undo_redo_levels: 50,\n // Three &nbsp; per TAB, and no wrapping of the inserted spaces.\n nonbreaking_force_tab: true,\n nonbreaking_wrap: false,\n help_tabs: ['shortcuts', 'keyboardnav', 'versions'],\n menubar: false,\n plugins: 'advlist anchor autolink autosave charmap code fullscreen help image insertdatetime'\n + ' link lists media nonbreaking pagebreak preview quickbars searchreplace table'\n + ' visualblocks visualchars',\n toolbar: [\n 'fullscreen | undo redo searchreplace | code preview | link image media charmap nonbreaking | table tableprops tabledelete',\n 'bold italic superscript subscript forecolor backcolor | alignleft aligncenter alignright alignjustify | removeformat | bullist numlist'\n ],\n quickbars_insert_toolbar: false,\n quickbars_selection_toolbar: 'removeformat | bold italic | superscript subscript | quicklink h2 h3 blockquote',\n style_formats: [\n {\n title: 'Immagini float', items: [\n { title: 'Immagine a SX', selector: 'img', styles: { float: 'left', margin: '0 10px 0 10px' } },\n { title: 'Immagine a DX', selector: 'img', styles: { float: 'right', margin: '0 10px 0 10px' } }\n ]\n },\n {\n title: 'Formati', items: [\n { title: 'Grassetto', format: 'bold' },\n { title: 'Corsivo', format: 'italic' },\n { title: 'Sottolineato', format: 'underline' },\n { title: 'Barrato', format: 'strikethrough' },\n { title: 'Superscript', format: 'superscript' },\n { title: 'Subscript', format: 'subscript' },\n { title: 'Codice', format: 'code' }\n ]\n }\n ],\n // Spans with an inline style rather than <u>/<strike>: the content travels by e-mail, where\n // the presentational tags are the first thing a client strips.\n formats: {\n underline: { inline: 'span', styles: { 'text-decoration': 'underline' }, exact: true },\n strikethrough: { inline: 'span', styles: { 'text-decoration': 'line-through' }, exact: true }\n },\n insertdatetime_formats: ['%d/%m/%Y', '%d %b %Y', '%A, %d %B %Y'],\n link_default_target: '_blank',\n link_title: true,\n link_assume_external_targets: 'https',\n link_class_list: [\n { title: 'Nessuno', value: '' },\n { title: 'Rilevante', value: 'relevant' },\n ],\n link_context_toolbar: true,\n link_quicklink: true,\n image_advtab: true,\n image_caption: true,\n image_title: true,\n };\n\n /**\n * The one for a field inside a form: it grows with the text instead of owning the page, the\n * toolbar sits under it and collapses into groups, and there is no status bar or context menu\n * to compete with the form around it.\n */\n private static readonly COMPACT: RawEditorOptions = {\n ...TinymceUtils.FULL,\n height: 200,\n min_height: 200,\n max_height: 500,\n statusbar: false,\n contextmenu: false,\n toolbar_location: 'bottom',\n plugins: 'advlist anchor autolink autoresize autosave charmap code image insertdatetime'\n + ' link lists media nonbreaking preview quickbars searchreplace table'\n + ' visualblocks visualchars',\n toolbar: ['undo redo | quickimage | formatgroup paragraphgroup'],\n toolbar_groups: {\n formatgroup: {\n icon: 'format',\n tooltip: 'Formattazione',\n items: 'bold italic underline superscript subscript | forecolor backcolor | removeformat'\n },\n paragraphgroup: {\n icon: 'paragraph',\n tooltip: 'Formato paragrafo',\n items: 'h1 h2 h3 | bullist numlist | alignleft aligncenter alignright alignjustify | indent outdent'\n },\n insertgroup: {\n icon: 'plus',\n tooltip: 'Inserisci',\n items: 'quickimage media | link charmap nonbreaking | table tableprops tabledelete'\n }\n },\n quickbars_insert_toolbar: 'quickimage',\n link_class_list: [],\n };\n\n /** The compact one plus full screen, the insert group and the source view. */\n private static readonly COMPACT_EXTENDED: RawEditorOptions = {\n ...TinymceUtils.COMPACT,\n plugins: 'advlist anchor autolink autoresize autosave charmap code fullscreen image'\n + ' insertdatetime link lists media nonbreaking preview quickbars searchreplace table'\n + ' visualblocks visualchars',\n toolbar: ['undo redo | quickimage insertgroup | formatgroup paragraphgroup | code | fullscreen'],\n };\n\n /**\n * The full-page profile.\n * @returns A fresh copy of the configuration, safe to modify.\n */\n static get TinymceConfig(): RawEditorOptions {\n return structuredClone(TinymceUtils.FULL);\n }\n\n /**\n * The in-form profile.\n * @returns A fresh copy of the configuration, safe to modify.\n */\n static get TinymceCompactConfig(): RawEditorOptions {\n return structuredClone(TinymceUtils.COMPACT);\n }\n\n /**\n * The in-form profile with full screen and source view.\n * @returns A fresh copy of the configuration, safe to modify.\n */\n static get TinymceCompactExtendedConfig(): RawEditorOptions {\n return structuredClone(TinymceUtils.COMPACT_EXTENDED);\n }\n}\n","import { Service } from '@angular/core';\nimport type { TinyMCE } from 'tinymce';\n\ndeclare global {\n interface Window {\n tinymce?: TinyMCE;\n }\n}\n\n/**\n * Loads the self-hosted TinyMCE bundle on demand.\n *\n * TinyMCE is deliberately NOT imported by any module: a static import would pull ~500 kB into\n * whichever chunk referenced it, and the editor is needed by exactly one dialog. The library is\n * copied to `assets/tinymce` by the build (see `angular.json`) and injected here as a plain\n * `<script>` the first time an editor is created, so it costs nothing until then and is served\n * from the browser cache afterwards. Loading it this way also lets TinyMCE resolve its own theme,\n * model, plugins and skin relative to `base_url`, which is how the self-hosted distribution\n * expects to work.\n */\n@Service()\nexport class TinymceLoaderService {\n\n /** The in-flight (or completed) load, so concurrent editors share a single script tag. */\n private pending?: Promise<TinyMCE>;\n\n /**\n * The absolute URL of the TinyMCE asset folder, resolved against the document base href so the\n * app keeps working when it is served from a sub-path.\n * @returns The base URL, without a trailing slash.\n */\n get baseUrl(): string {\n return new URL('assets/tinymce', document.baseURI).href.replace(/\\/$/, '');\n }\n\n /**\n * Loads TinyMCE, reusing the script already injected by a previous call.\n * @returns A promise resolving with the global TinyMCE instance.\n */\n load(): Promise<TinyMCE> {\n if (window.tinymce) return Promise.resolve(window.tinymce);\n\n // A failed load clears `pending`, so a later attempt can retry instead of being stuck on the\n // rejected promise forever (e.g. the first open happened while the network was down).\n this.pending ??= new Promise<TinyMCE>((resolve, reject) => {\n const script = document.createElement('script');\n script.src = `${this.baseUrl}/tinymce.min.js`;\n script.async = true;\n script.referrerPolicy = 'origin';\n script.onload = () => {\n if (window.tinymce) {\n resolve(window.tinymce);\n } else {\n this.pending = undefined;\n reject(new Error('TinyMCE caricato ma non disponibile.'));\n }\n };\n script.onerror = () => {\n this.pending = undefined;\n script.remove();\n reject(new Error('Impossibile caricare l\\'editor.'));\n };\n document.head.appendChild(script);\n });\n\n return this.pending;\n }\n}\n","import {\n ChangeDetectorRef,\n Directive,\n ElementRef,\n OnDestroy,\n OnInit,\n forwardRef,\n inject,\n input,\n output\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { ThemeService } from '@arsedizioni/ars-utils/core';\nimport type { Editor, RawEditorOptions } from 'tinymce';\nimport { TinymceLoaderService } from './tinymce-loader.service';\n\n/** Uploads one image and resolves with the URL to reference it by. */\nexport type TinymceImageUploader = (file: File) => Promise<string>;\n\n/**\n * How the editor presents itself.\n *\n * `fixed` is the classic editor: the content lives in an iframe and the toolbar sits above it,\n * pinned so it stays reachable while the surrounding container scrolls.\n *\n * `inline` edits the host element in place, with no iframe and no chrome until the user focuses\n * it, at which point the toolbar floats over the content. It needs an ordinary element to edit —\n * a `<div>` — because there is nothing to render inside a `<textarea>`.\n */\nexport type TinymceToolbarMode = 'fixed' | 'inline';\n\n/**\n * Turns a `<textarea>` into a rich text editor backed by the self-hosted TinyMCE bundle, and wires\n * it to Angular forms as a `ControlValueAccessor`, so `[(ngModel)]`, `required` and the\n * pristine/dirty state keep working exactly as they do on a plain control.\n *\n * The library itself is fetched on demand by <see cref=\"TinymceLoaderService\"/>: nothing about\n * TinyMCE reaches the bundle until an editor is actually created.\n *\n * Usage: `<textarea tinymceEditor [(ngModel)]=\"item.text\" name=\"text\" required></textarea>`\n *\n */\n@Directive({\n // Both hosts are accepted because the two modes need different ones: the classic editor\n // replaces a textarea, the inline editor edits a div in place.\n selector: 'textarea[tinymceEditor], div[tinymceEditor]',\n providers: [{\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => TinymceEditorDirective),\n multi: true\n }]\n})\nexport class TinymceEditorDirective implements ControlValueAccessor, OnInit, OnDestroy {\n\n /** Extra TinyMCE options, merged over (and able to override) the defaults below. */\n readonly tinymceConfig = input<RawEditorOptions>({});\n\n /** Whether the toolbar is pinned above the content (`fixed`) or floats on focus (`inline`). */\n readonly tinymceToolbarMode = input<TinymceToolbarMode>('fixed');\n\n /**\n * Handler invoked for every image dropped, pasted or picked in the editor. When not provided\n * the upload tab is hidden and only images referenced by URL can be inserted.\n */\n readonly tinymceImageUploader = input<TinymceImageUploader | undefined>(undefined);\n\n /** Emitted once the editor is up, for callers that want to enable UI only when it is usable. */\n readonly ready = output<Editor>();\n\n /** Emitted when the editor could not be loaded or initialised. */\n readonly failed = output<Error>();\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly loader = inject(TinymceLoaderService);\n private readonly themeService = inject(ThemeService);\n private readonly changeDetector = inject(ChangeDetectorRef);\n\n private editor?: Editor;\n /** True while the editor is showing itself full screen. */\n private fullscreen = false;\n /** True once the directive has been destroyed, so a late init resolves into a no-op. */\n private destroyed = false;\n /**\n * True while the directive itself is pushing a value into the editor. TinyMCE raises the same\n * content events for a programmatic `setContent` as for a keystroke, so without this flag\n * `writeValue` would immediately echo back through `onChange` and mark a freshly loaded form\n * as dirty.\n */\n private writingValue = false;\n /** The value received before the editor existed, applied as soon as it does. */\n private value = '';\n private disabled = false;\n\n private onChange: (value: string) => void = () => { /* set by Angular forms */ };\n private onTouched: () => void = () => { /* set by Angular forms */ };\n\n /**\n * Leaves full screen on Escape, for the keystrokes that happen outside the content: with the\n * classic editor the content is an iframe, and a keydown in there never reaches this document.\n * Bound on the capture phase and stopped, so a dialog hosting the editor does not take the\n * Escape and close, throwing the edit away when the user only meant to leave full screen.\n */\n private readonly onDocumentKeydown = (event: KeyboardEvent): void => {\n if (!this.shouldEscapeLeaveFullscreen(event)) return;\n event.preventDefault();\n event.stopPropagation();\n this.exitFullscreen();\n };\n\n /**\n * Loads TinyMCE and initialises the editor over the host textarea.\n * @returns A promise that completes once the editor is ready (or has failed).\n */\n async ngOnInit(): Promise<void> {\n try {\n const tinymce = await this.loader.load();\n if (this.destroyed) return;\n\n const dark = this.themeService.getTheme() === 'dark';\n const uploader = this.tinymceImageUploader();\n const inline = this.tinymceToolbarMode() === 'inline';\n\n // Caught here rather than left to TinyMCE, which would fail deep inside its own setup\n // with a message that says nothing about the actual mistake.\n if (inline && this.host.nativeElement.tagName === 'TEXTAREA') {\n throw new Error('La modalità inline richiede un <div>, non un <textarea>.');\n }\n\n // TinyMCE ships its language packs outside the npm package, so `it.js` is committed\n // under `src/assets/tinymce/langs/`: the existing `src/assets` build rule publishes it\n // exactly where TinyMCE looks for it, relative to `base_url`.\n const defaults: RawEditorOptions = {\n // Self-hosting TinyMCE 8 requires an explicit license key: without one the editor\n // refuses to start. 'gpl' selects the GPLv2+ terms.\n license_key: 'gpl',\n language: 'it',\n branding: false,\n promotion: false,\n menubar: false,\n statusbar: false,\n resize: false,\n // Pins the toolbar while the container scrolls. In inline mode it is what keeps\n // the floating toolbar attached to the text instead of drifting off with it.\n toolbar_sticky: true,\n // An inline editor takes the size of the element it edits; only the classic one\n // has a box of its own to dimension.\n ...(inline ? {} : { height: 360 }),\n // The dialog body scrolls, and 'split' is what keeps the toolbar menus anchored\n // to the editor while it does: the popup sink is attached next to the editor, so\n // it shares its scrolling ancestry. It does NOT affect the modal dialogs — those\n // always go to <body> — which is why the CDK overlay has to be kept out of the\n // top layer (see OVERLAY_DEFAULT_CONFIG in app.config.ts).\n ui_mode: 'split',\n skin: dark ? 'oxide-dark' : 'oxide',\n content_css: dark ? 'dark' : 'default',\n // Absolute URLs must survive untouched: the content ends up in an e-mail, where a\n // relative image path resolves against nothing.\n convert_urls: false,\n plugins: 'advlist autolink lists link image table charmap searchreplace code fullscreen',\n toolbar: 'undo redo | blocks | bold italic underline | forecolor backcolor'\n + ' | bullist numlist | link image table | removeformat code fullscreen',\n content_style: 'body { font-family: Arial, Helvetica, sans-serif; font-size: 14px; }',\n // Pasted and dropped images go through the same upload path as the image dialog.\n automatic_uploads: !!uploader,\n paste_data_images: !!uploader,\n images_file_types: 'jpeg,jpg,png,gif,webp',\n file_picker_types: uploader ? 'image' : '',\n images_upload_handler: uploader\n ? (blobInfo) => uploader(new File([blobInfo.blob()], blobInfo.filename(), { type: blobInfo.blob().type }))\n : undefined,\n };\n\n await tinymce.init({\n ...defaults,\n // The caller's profile wins over every default above: that is what the presets in\n // `TinymceUtils` are for.\n ...this.tinymceConfig(),\n // Not negotiable, whatever the profile says. `target` and `base_url` are resolved\n // here and nowhere else, `inline` is the input's job, and replacing `setup` would\n // unhook the editor from the form and leave a ControlValueAccessor that never\n // reports a change.\n target: this.host.nativeElement,\n base_url: this.loader.baseUrl,\n inline,\n setup: (editor: Editor) => {\n /*\n * Typing, toolbar commands, undo/redo and programmatic inserts all have to reach\n * the form; the two guards keep everything else out.\n *\n * `writingValue` keeps our own writes from bouncing back. `!this.editor` — which\n * stays unset until the `init` handler below — keeps out the one content event\n * that fires BEFORE the editor exists, and it is the one that made an editor\n * impossible to fill: TinyMCE's own `loadInitialContent` reads the textarea and\n * calls `setContent(..., { initial: true })`, which dispatches `SetContent`\n * because only `no_events` suppresses it. The textarea is empty — the form\n * writes through the ControlValueAccessor, never into the DOM element — so this\n * handler took that empty string for a user edit, overwrote the value the form\n * had already handed us, and reported '' back to the model. `init` then applied\n * the value it had just destroyed, and the editor came up blank whatever was\n * passed to it. Saving from there stored the empty string as well.\n */\n editor.on('change input undo redo SetContent', () => {\n if (this.writingValue || !this.editor) return;\n this.value = editor.getContent();\n this.onChange(this.value);\n this.changeDetector.markForCheck();\n });\n editor.on('blur', () => {\n this.onTouched();\n this.changeDetector.markForCheck();\n });\n editor.on('FullscreenStateChanged', (event) => {\n this.handleFullscreenChanged((event as unknown as { state?: boolean }).state === true);\n });\n // The content of a classic editor lives in an iframe, so its keystrokes are\n // only visible from the editor itself.\n editor.on('keydown', (event) => {\n if (!this.shouldEscapeLeaveFullscreen(event)) return;\n event.preventDefault();\n event.stopPropagation();\n this.exitFullscreen();\n });\n editor.on('init', () => {\n // Assigned BEFORE applying the value, and that order is the contract with\n // the guard above: from here on content events are genuine, and the one\n // raised by `applyValue` itself is covered by `writingValue`.\n this.editor = editor;\n this.applyValue(this.value);\n this.applyDisabled(this.disabled);\n this.ready.emit(editor);\n this.changeDetector.markForCheck();\n });\n },\n });\n } catch (error) {\n if (this.destroyed) return;\n this.failed.emit(error instanceof Error ? error : new Error(String(error)));\n this.changeDetector.markForCheck();\n }\n }\n\n /**\n * Tears the editor down. TinyMCE keeps global state per instance, so leaving it behind when a\n * dialog closes leaks both DOM and editor registrations.\n * @returns void\n */\n ngOnDestroy(): void {\n this.destroyed = true;\n // Removing the editor does not raise the full-screen event, so the session is closed by\n // hand here: the Escape listener would otherwise stay attached to the document forever.\n this.releaseFullscreen();\n this.editor?.remove();\n this.editor = undefined;\n }\n\n /**\n * Decides whether an Escape press means \"leave full screen\": it does whenever the editor is\n * full screen, full stop. While full screen the editor owns Escape, and the press is stopped\n * here so it can never reach the dialog hosting it — leaving full screen must not also throw\n * away what is being written.\n * @param event The keyboard event, from the document or from the editor's content.\n * @returns True when full screen should be left.\n */\n private shouldEscapeLeaveFullscreen(event: KeyboardEvent): boolean {\n return event.key === 'Escape' && this.fullscreen;\n }\n\n /**\n * Asks the editor to leave full screen. Safe to call when it is not in full screen.\n * @returns void\n */\n private exitFullscreen(): void {\n if (!this.fullscreen) return;\n this.editor?.execCommand('mceFullScreen');\n }\n\n /**\n * Attaches or detaches everything that only makes sense while the editor is full screen.\n * @param state True when the editor has just entered full screen.\n * @returns void\n */\n private handleFullscreenChanged(state: boolean): void {\n if (state === this.fullscreen) return;\n this.fullscreen = state;\n\n if (state) {\n document.addEventListener('keydown', this.onDocumentKeydown, true);\n } else {\n this.releaseFullscreen();\n }\n\n this.changeDetector.markForCheck();\n }\n\n /**\n * Detaches the listener that only makes sense while the editor is full screen.\n * @returns void\n */\n private releaseFullscreen(): void {\n document.removeEventListener('keydown', this.onDocumentKeydown, true);\n this.fullscreen = false;\n }\n\n /**\n * Pushes a value coming from the form into the editor.\n * @param value The new content, or null/undefined for an empty editor.\n * @returns void\n */\n writeValue(value: string | null | undefined): void {\n this.value = value ?? '';\n this.applyValue(this.value);\n }\n\n /**\n * Registers the callback used to report content changes to the form.\n * @param fn The callback supplied by Angular forms.\n * @returns void\n */\n registerOnChange(fn: (value: string) => void): void {\n this.onChange = fn;\n }\n\n /**\n * Registers the callback used to report the first blur to the form.\n * @param fn The callback supplied by Angular forms.\n * @returns void\n */\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n /**\n * Enables or disables editing.\n * @param isDisabled True to switch the editor to read-only.\n * @returns void\n */\n setDisabledState(isDisabled: boolean): void {\n this.disabled = isDisabled;\n this.applyDisabled(isDisabled);\n }\n\n /**\n * Writes content into the editor when it exists, guarding against the echo described on\n * <see cref=\"writingValue\"/>.\n * @param value The content to write.\n * @returns void\n */\n private applyValue(value: string): void {\n const editor = this.editor;\n if (!editor) return;\n // Comparing with the serialized content avoids resetting the caret on every form patch\n // that did not actually change anything.\n if (editor.getContent() === value) return;\n this.writingValue = true;\n try {\n editor.setContent(value);\n } finally {\n this.writingValue = false;\n }\n }\n\n /**\n * Applies the disabled state to the editor when it exists.\n * @param isDisabled True to switch the editor to read-only.\n * @returns void\n */\n private applyDisabled(isDisabled: boolean): void {\n this.editor?.mode.set(isDisabled ? 'readonly' : 'design');\n }\n}\n","import { ChangeDetectionStrategy, Component, inject, output, signal } from '@angular/core';\nimport { FormField, disabled as fieldDisabled, form } from '@angular/forms/signals';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MAT_DIALOG_DATA, MatDialogActions, MatDialogClose, MatDialogContent, MatDialogRef } from '@angular/material/dialog';\nimport { FlexLayoutModule } from '@arsedizioni/ars-utils/ui';\nimport type { RawEditorOptions } from 'tinymce';\nimport { TinymceEditorDirective } from '../tinymce-editor.directive';\nimport { TinymceUtils } from '../utils';\n\nexport interface TinyMceEditorDialogData {\n text: string;\n configuration: RawEditorOptions;\n infoButtonLabel?: string;\n onShowInfo?: Function,\n disabled?: boolean;\n}\n\n/**\n * A dialog that is nothing but an editor: the caller hands it a text and gets the edited one\n * back through {@link saving}.\n *\n * The editor is {@link TinymceEditorDirective} on a plain `<textarea>`, so this dialog costs\n * exactly what any other editor in the application costs — the TinyMCE bundle is fetched on\n * first use and nothing about it reaches the initial chunk.\n */\n@Component({\n templateUrl: './editor.component.html',\n styleUrls: ['./editor.component.scss'],\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [MatDialogContent, TinymceEditorDirective, FormField, MatDialogActions, FlexLayoutModule,\n MatButtonModule, MatDialogClose]\n})\nexport class TinyMceEditorComponent {\n\n /** Emitted with the edited text when the user saves. */\n readonly saving = output<string>();\n private readonly dialogRef = inject(MatDialogRef<TinyMceEditorComponent>);\n /** Dialog configuration, injected and exposed as a signal. */\n protected readonly dialogData = signal<TinyMceEditorDialogData>((() => {\n const data: TinyMceEditorDialogData = inject(MAT_DIALOG_DATA) ?? {};\n return { ...data, text: data.text ?? '' };\n })());\n /** Whether the editor is in read-only mode. */\n protected readonly disabled = signal<boolean>(false);\n\n /**\n * Why the editor could not be shown, when it could not.\n *\n * Without it a failure looked exactly like an empty document: the directive reported it on its\n * `failed` output, nothing was listening, and the user was left with a blank box and no reason\n * for it. The message is the directive's own — the bundle did not load, or TinyMCE refused to\n * start — and it also goes to the console, because that is where whoever is asked about it will\n * look first.\n */\n protected readonly error = signal<string | undefined>(undefined);\n /** Current editor content. */\n protected readonly text = signal<string>('');\n\n /**\n * Signal form bound to the editor textarea. The disabled state is pushed to the\n * TinymceEditorDirective through the ControlValueAccessor interop.\n */\n protected readonly textForm = form(this.text, p => {\n fieldDisabled(p, () => this.disabled());\n });\n /** The profile handed to the editor directive, merged over its defaults. */\n protected tinymceConfig: RawEditorOptions = {};\n\n constructor() {\n const data = this.dialogData();\n this.text.set(data.text);\n // The accessor already returns a private copy, so the toolbar override below cannot leak\n // into the preset shared with the rest of the application.\n this.tinymceConfig = data.configuration\n ? { ...data.configuration }\n : TinymceUtils.TinymceCompactExtendedConfig;\n // No full screen: the editor already owns the whole dialog.\n this.tinymceConfig.toolbar = ['undo redo | quickimage insertgroup | formatgroup paragraphgroup | code'];\n this.disabled.set(data.disabled ?? false);\n }\n\n\n /**\n * Records that the editor could not be shown.\n * @param error - What the directive could not do.\n * @returns void\n */\n protected failed(error: Error): void {\n console.error('[TinyMceEditorComponent] editor non disponibile', error);\n this.error.set(error?.message || 'Editor non disponibile.');\n }\n\n /**\n * Save the current editor content and close the dialog.\n */\n protected ok(): void {\n this.saving.emit(this.text() ?? '');\n setTimeout(() => {\n this.dialogRef.close();\n }, 500);\n }\n}\n","<mat-dialog-content style=\"padding: 10px 10px 0 10px\">\n @if (error()) {\n <!-- The textarea is gone with the editor that could not replace it: left in place it would be a\n plain box the form does not write into, which is the empty editor this message exists to\n explain. -->\n <div class=\"editor-error\">\n <div class=\"editor-error-title\">Non è stato possibile aprire l'editor.</div>\n <div class=\"editor-error-detail\">{{ error() }}</div>\n <div class=\"editor-error-detail\">Il testo non è stato modificato: chiudi e riprova.</div>\n </div>\n } @else {\n <textarea tinymceEditor class=\"full-screen-editor\" [tinymceConfig]=\"tinymceConfig\"\n [formField]=\"textForm\" (failed)=\"failed($event)\"></textarea>\n }\n</mat-dialog-content>\n<mat-dialog-actions>\n <div fxLayout=\"row\" fxLayoutGap=\"10px\" fxLayoutAlign=\"start center\" fxFill>\n <div fxFlex=\"50\">\n @if(dialogData().onShowInfo) {\n <button mat-stroked-button (click)=\"dialogData().onShowInfo()\">{{dialogData().infoButtonLabel ?? 'Informazioni'}}\n </button>\n }\n </div>\n <div fxFlex=\"50\" fxLayoutAlign=\"end\">\n <!-- Nothing to save when there was no editor: the only way out is the one that changes\n nothing. -->\n @if (disabled() || error()) {\n <button mat-stroked-button [mat-dialog-close]=\"true\">Chiudi</button>\n } @else {\n <button mat-flat-button (click)=\"ok()\">Salva</button>\n <button mat-stroked-button [mat-dialog-close]=\"true\">Annulla</button>\n }\n </div>\n </div>\n</mat-dialog-actions>\n","/*\n * Public API Surface of @arsedizioni/ars-utils/ui.tinymce\n */\nexport * from './utils';\nexport * from './tinymce-loader.service';\nexport * from './tinymce-editor.directive';\nexport * from './editor/editor.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["fieldDisabled"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arsedizioni/ars-utils",
3
- "version": "22.5.42",
3
+ "version": "22.5.44",
4
4
  "author": {
5
5
  "email": "software@arsedizioni.it",
6
6
  "name": "Fabio Buscaroli, Alberto Doria"
@@ -253,20 +253,46 @@ declare class TimeValidatorDirective implements Validator {
253
253
  }
254
254
 
255
255
  /**
256
- * Directive that validates that a string control value is not blank (whitespace-only).
257
- * Apply `notEmpty` to a text input where non-blank content is required.
256
+ * Directive that validates that a control value is not blank: neither a whitespace-only string
257
+ * nor an empty array. Apply `notEmpty` to a text input where non-blank content is required, or
258
+ * to a multi-value control that must carry at least one entry.
259
+ *
260
+ * A value that is simply absent passes: saying "obbligatorio" is the job of `required`, or of
261
+ * `requiredNotEmpty` when both rules belong on the same control.
258
262
  */
259
263
  declare class NotEmptyValidatorDirective implements Validator {
260
264
  /**
261
- * Validates that the control value is a non-blank string.
262
- * Returns `null` when the control is empty or not a string.
265
+ * Validates that the control value carries content.
266
+ * Returns `null` when the control is absent or holds a type this rule says nothing about.
263
267
  * @param control - The form control to validate.
268
+ * @returns `{ notEmpty: true }` when the value is a blank string or an empty array, `null` otherwise.
264
269
  */
265
270
  validate(control: AbstractControl): ValidationErrors | null;
266
271
  static ɵfac: i0.ɵɵFactoryDeclaration<NotEmptyValidatorDirective, never>;
267
272
  static ɵdir: i0.ɵɵDirectiveDeclaration<NotEmptyValidatorDirective, "[notEmpty]", never, {}, {}, never, never, true, never>;
268
273
  }
269
274
 
275
+ /**
276
+ * Directive that validates that a control carries actual content: present AND not blank.
277
+ * Apply `requiredNotEmpty` where `required notEmpty` would otherwise be spelled out together.
278
+ *
279
+ * It raises the very errors those two rules raise — `required` when the value is missing, an
280
+ * empty string or an empty array, `notEmpty` when a value is there but made of whitespace alone —
281
+ * so existing error messages and `getFieldErrorMessage` keep working untouched, and the user
282
+ * still reads "Obbligatorio" rather than the vaguer "Non può contenere solo spazi".
283
+ */
284
+ declare class RequiredNotEmptyValidatorDirective implements Validator {
285
+ /**
286
+ * Validates that the control value is present and carries content.
287
+ * @param control - The form control to validate.
288
+ * @returns `{ required: true }` when nothing was entered, `{ notEmpty: true }` when the value
289
+ * is blank, `null` when the value is acceptable.
290
+ */
291
+ validate(control: AbstractControl): ValidationErrors | null;
292
+ static ɵfac: i0.ɵɵFactoryDeclaration<RequiredNotEmptyValidatorDirective, never>;
293
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RequiredNotEmptyValidatorDirective, "[requiredNotEmpty]", never, {}, {}, never, never, true, never>;
294
+ }
295
+
270
296
  /**
271
297
  * Options shared by the ARS signal-form validators.
272
298
  *
@@ -329,12 +355,13 @@ declare function guid<TPathKind extends PathKind = PathKind.Root>(path: SchemaPa
329
355
  */
330
356
  declare function password<TPathKind extends PathKind = PathKind.Root>(path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>, config?: ArsValidatorConfig<string, TPathKind>): void;
331
357
  /**
332
- * Requires the value not to be made of whitespace alone.
358
+ * Requires the value not to be made of whitespace alone, and a collection not to be empty.
333
359
  *
334
- * The signal-form counterpart of `NotEmptyValidatorDirective`, with its exact semantics: an empty
335
- * value passes. That is not an oversight saying "obbligatorio" belongs to `required()`, and a
336
- * field that is merely blank would otherwise raise two errors that mean the same thing. Pair the
337
- * two when a field must be both present and non-blank.
360
+ * The signal-form counterpart of `NotEmptyValidatorDirective`, sharing its predicate through
361
+ * {@link isBlankValue}: a blank string and an empty array are errors, an absent value is not.
362
+ * That last part is not an oversight saying "obbligatorio" belongs to `required()`, and a field
363
+ * that is merely blank would otherwise raise two errors that mean the same thing. Pair the two,
364
+ * or reach for {@link requiredNotEmpty}, when a field must be both present and non-blank.
338
365
  *
339
366
  * Replaces the `pattern(p.x, /\S/)` workaround: same rule, but the intent is in the name and the
340
367
  * error kind is `notEmpty` rather than `pattern`.
@@ -344,8 +371,29 @@ declare function password<TPathKind extends PathKind = PathKind.Root>(path: Sche
344
371
  * @returns void
345
372
  * @example
346
373
  * const f = form(this.model, p => { required(p.city); notEmpty(p.city); });
374
+ * @example
375
+ * const f = form(this.model, p => { notEmpty(p.tags); }); // at least one tag
376
+ */
377
+ declare function notEmpty<TValue extends string | readonly unknown[] | undefined, TPathKind extends PathKind = PathKind.Root>(path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>, config?: ArsValidatorConfig<TValue, TPathKind>): void;
378
+ /**
379
+ * Requires the value to be both present and made of something: the two rules a mandatory text
380
+ * field almost always needs together, declared once.
381
+ *
382
+ * The signal-form counterpart of `RequiredNotEmptyValidatorDirective`. It raises the errors the
383
+ * two rules raise on their own rather than a kind of its own — `required` when nothing was
384
+ * entered (nullish, empty string, empty array), `notEmpty` when a value is there but blank — so
385
+ * the message stays as precise as it was and nothing downstream needs to learn a new kind.
386
+ *
387
+ * Not a wrapper around Angular's `required()`: that one would have to be declared on the same
388
+ * path anyway, and the pair would then report two errors on an empty field.
389
+ *
390
+ * @param path - Path of the field to validate.
391
+ * @param config - Optional message override, applied to whichever of the two errors is raised.
392
+ * @returns void
393
+ * @example
394
+ * const f = form(this.model, p => { requiredNotEmpty(p.city); });
347
395
  */
348
- declare function notEmpty<TPathKind extends PathKind = PathKind.Root>(path: SchemaPath<string, SchemaPathRules.Supported, TPathKind>, config?: ArsValidatorConfig<string, TPathKind>): void;
396
+ declare function requiredNotEmpty<TValue extends string | readonly unknown[] | undefined, TPathKind extends PathKind = PathKind.Root>(path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>, config?: ArsValidatorConfig<TValue, TPathKind>): void;
349
397
  /**
350
398
  * Requires the value to differ from the value of another field of the same form.
351
399
  *
@@ -546,5 +594,5 @@ declare class SignalsUtils {
546
594
  }[], message?: string): string | undefined;
547
595
  }
548
596
 
549
- export { ARS_VALIDATOR_MESSAGES, EmailsValidatorDirective, EqualsValidatorDirective, FileSizeValidatorDirective, GuidValidatorDirective, MIN_VALID_YEAR, MaxTermsValidatorDirective, NotEmptyValidatorDirective, NotEqualValidatorDirective, NotFutureValidatorDirective, PasswordValidatorDirective, SignalsUtils, SqlDateValidatorDirective, TimeValidatorDirective, UrlValidatorDirective, ValidIfDirective, ValidatorDirective, date, dateRange, emails, equals, fileSize, guid, maxTerms, notEmpty, notEqual, notFuture, otp, password, sqlDate, time, url, validIf };
597
+ export { ARS_VALIDATOR_MESSAGES, EmailsValidatorDirective, EqualsValidatorDirective, FileSizeValidatorDirective, GuidValidatorDirective, MIN_VALID_YEAR, MaxTermsValidatorDirective, NotEmptyValidatorDirective, NotEqualValidatorDirective, NotFutureValidatorDirective, PasswordValidatorDirective, RequiredNotEmptyValidatorDirective, SignalsUtils, SqlDateValidatorDirective, TimeValidatorDirective, UrlValidatorDirective, ValidIfDirective, ValidatorDirective, date, dateRange, emails, equals, fileSize, guid, maxTerms, notEmpty, notEqual, notFuture, otp, password, requiredNotEmpty, sqlDate, time, url, validIf };
550
598
  export type { ArsValidatorConfig };
@@ -259,6 +259,16 @@ declare class TinyMceEditorComponent {
259
259
  protected readonly dialogData: _angular_core.WritableSignal<TinyMceEditorDialogData>;
260
260
  /** Whether the editor is in read-only mode. */
261
261
  protected readonly disabled: _angular_core.WritableSignal<boolean>;
262
+ /**
263
+ * Why the editor could not be shown, when it could not.
264
+ *
265
+ * Without it a failure looked exactly like an empty document: the directive reported it on its
266
+ * `failed` output, nothing was listening, and the user was left with a blank box and no reason
267
+ * for it. The message is the directive's own — the bundle did not load, or TinyMCE refused to
268
+ * start — and it also goes to the console, because that is where whoever is asked about it will
269
+ * look first.
270
+ */
271
+ protected readonly error: _angular_core.WritableSignal<string>;
262
272
  /** Current editor content. */
263
273
  protected readonly text: _angular_core.WritableSignal<string>;
264
274
  /**
@@ -269,6 +279,12 @@ declare class TinyMceEditorComponent {
269
279
  /** The profile handed to the editor directive, merged over its defaults. */
270
280
  protected tinymceConfig: RawEditorOptions;
271
281
  constructor();
282
+ /**
283
+ * Records that the editor could not be shown.
284
+ * @param error - What the directive could not do.
285
+ * @returns void
286
+ */
287
+ protected failed(error: Error): void;
272
288
  /**
273
289
  * Save the current editor content and close the dialog.
274
290
  */