@arsedizioni/ars-utils 22.5.7 → 22.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/fesm2022/arsedizioni-ars-utils-core.validators.mjs +42 -42
- package/fesm2022/arsedizioni-ars-utils-core.validators.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-ui.shell.mjs +23 -5
- package/fesm2022/arsedizioni-ars-utils-ui.shell.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/ui.colors.scss +25 -23
- package/types/arsedizioni-ars-utils-clipper.ui.d.ts +1 -1
- package/types/arsedizioni-ars-utils-core.validators.d.ts +15 -15
- package/types/arsedizioni-ars-utils-ui.shell.d.ts +15 -1
package/README.md
CHANGED
|
@@ -100,7 +100,7 @@ clipper.ui (+ clipper.common, ui.controls, ui.files, ui.dialogs.select)
|
|
|
100
100
|
Nel top layer l'ordine e' quello di promozione, l'ultimo promosso sta sopra. Da qui le tre
|
|
101
101
|
regole esplicite: `setBusy()` ripromuove il messaggio dopo aver alzato il busy,
|
|
102
102
|
`DialogService.open()` chiama `raiseMessage()` dopo aver aperto un dialog, e chiama
|
|
103
|
-
`clearBusy(true)` senza periodo di grazia. La coppia `--ars-shell-z-index`/`--ars-busy-z-index`
|
|
103
|
+
`clearBusy(true)` senza periodo di grazia. La coppia `--ars-shell-dialog-z-index`/`--ars-shell-busy-z-index`
|
|
104
104
|
(1100/1090) resta valida e serve ancora: e' quello che ordina gli overlay sui browser senza
|
|
105
105
|
Popover API, dove nemmeno il CDK la usa. Se un'applicazione avesse bisogno del vecchio
|
|
106
106
|
comportamento puo' spegnere la Popover API del CDK con
|
|
@@ -155,6 +155,10 @@ iniettato e nient'altro.
|
|
|
155
155
|
- `PaginatorIntl` non sta piu' in `ui`: sta in `ui.paginator`.
|
|
156
156
|
- Le direttive validator non stanno piu' in `core`: stanno in `core.validators`, che e' l'unico
|
|
157
157
|
entry point del nucleo a dipendere da `@angular/forms`.
|
|
158
|
+
- I token CSS della shell stanno tutti sotto `--ars-shell-dialog-*` e `--ars-shell-busy-*`: prima
|
|
159
|
+
erano `--ars-dialog-*`, `--ars-scrim-color`, `--ars-busy-*` e `--ars-progress-track-color`, che si
|
|
160
|
+
confondevano con `--ars-dialog-item-*`, cioe' i dialog Material veri. Un'applicazione che ne
|
|
161
|
+
sovrascriveva qualcuno deve rinominarlo.
|
|
158
162
|
- La shell non deve piu' iniettare `DialogService` per mostrare un errore: c'e' `ShellService` in `ui.shell`.
|
|
159
163
|
- `info`, `error`, `busy`, `busySpinner`, `busyHourglass`, `wait`, `busyTimer` e `clearBusy` sono
|
|
160
164
|
passati a `ShellService`. `DialogService` li eredita, quindi nessuna chiamata cambia.
|
|
@@ -155,6 +155,48 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
155
155
|
}]
|
|
156
156
|
}], ctorParameters: () => [], propDecorators: { equals: [{ type: i0.Input, args: [{ isSignal: true, alias: "equals", required: false }] }] } });
|
|
157
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Directive that validates a semicolon-separated list of email addresses.
|
|
160
|
+
* Apply `emails` to a text input containing one or more addresses separated by `;`.
|
|
161
|
+
*/
|
|
162
|
+
class EmailsValidatorDirective {
|
|
163
|
+
/**
|
|
164
|
+
* Validates each address in a semicolon-separated email list.
|
|
165
|
+
* Returns `null` when the control is empty.
|
|
166
|
+
* @param control - The form control to validate.
|
|
167
|
+
*/
|
|
168
|
+
validate(control) {
|
|
169
|
+
const input = control.value;
|
|
170
|
+
if (!input || input.length === 0)
|
|
171
|
+
return null;
|
|
172
|
+
const parts = input.replaceAll(/\r\n/g, '').split(';');
|
|
173
|
+
const isValid = parts.every(part => part.length === 0 || !!SystemUtils.parseEmail(part));
|
|
174
|
+
return isValid ? null : { emails: "Elenco non valido." };
|
|
175
|
+
}
|
|
176
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EmailsValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
177
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: EmailsValidatorDirective, isStandalone: true, selector: "[emails]", providers: [
|
|
178
|
+
{
|
|
179
|
+
provide: NG_VALIDATORS,
|
|
180
|
+
useExisting: forwardRef(() => EmailsValidatorDirective),
|
|
181
|
+
multi: true,
|
|
182
|
+
},
|
|
183
|
+
], ngImport: i0 }); }
|
|
184
|
+
}
|
|
185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EmailsValidatorDirective, decorators: [{
|
|
186
|
+
type: Directive,
|
|
187
|
+
args: [{
|
|
188
|
+
selector: "[emails]",
|
|
189
|
+
providers: [
|
|
190
|
+
{
|
|
191
|
+
provide: NG_VALIDATORS,
|
|
192
|
+
useExisting: forwardRef(() => EmailsValidatorDirective),
|
|
193
|
+
multi: true,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
standalone: true,
|
|
197
|
+
}]
|
|
198
|
+
}] });
|
|
199
|
+
|
|
158
200
|
/**
|
|
159
201
|
* Directive that validates that the host control's value is different from another control's value.
|
|
160
202
|
* Bind `[notEqual]="otherControl"`.
|
|
@@ -237,48 +279,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
237
279
|
}]
|
|
238
280
|
}], ctorParameters: () => [], propDecorators: { notEqual: [{ type: i0.Input, args: [{ isSignal: true, alias: "notEqual", required: false }] }] } });
|
|
239
281
|
|
|
240
|
-
/**
|
|
241
|
-
* Directive that validates a semicolon-separated list of email addresses.
|
|
242
|
-
* Apply `emails` to a text input containing one or more addresses separated by `;`.
|
|
243
|
-
*/
|
|
244
|
-
class EmailsValidatorDirective {
|
|
245
|
-
/**
|
|
246
|
-
* Validates each address in a semicolon-separated email list.
|
|
247
|
-
* Returns `null` when the control is empty.
|
|
248
|
-
* @param control - The form control to validate.
|
|
249
|
-
*/
|
|
250
|
-
validate(control) {
|
|
251
|
-
const input = control.value;
|
|
252
|
-
if (!input || input.length === 0)
|
|
253
|
-
return null;
|
|
254
|
-
const parts = input.replaceAll(/\r\n/g, '').split(';');
|
|
255
|
-
const isValid = parts.every(part => part.length === 0 || !!SystemUtils.parseEmail(part));
|
|
256
|
-
return isValid ? null : { emails: "Elenco non valido." };
|
|
257
|
-
}
|
|
258
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EmailsValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
259
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: EmailsValidatorDirective, isStandalone: true, selector: "[emails]", providers: [
|
|
260
|
-
{
|
|
261
|
-
provide: NG_VALIDATORS,
|
|
262
|
-
useExisting: forwardRef(() => EmailsValidatorDirective),
|
|
263
|
-
multi: true,
|
|
264
|
-
},
|
|
265
|
-
], ngImport: i0 }); }
|
|
266
|
-
}
|
|
267
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EmailsValidatorDirective, decorators: [{
|
|
268
|
-
type: Directive,
|
|
269
|
-
args: [{
|
|
270
|
-
selector: "[emails]",
|
|
271
|
-
providers: [
|
|
272
|
-
{
|
|
273
|
-
provide: NG_VALIDATORS,
|
|
274
|
-
useExisting: forwardRef(() => EmailsValidatorDirective),
|
|
275
|
-
multi: true,
|
|
276
|
-
},
|
|
277
|
-
],
|
|
278
|
-
standalone: true,
|
|
279
|
-
}]
|
|
280
|
-
}] });
|
|
281
|
-
|
|
282
282
|
/**
|
|
283
283
|
* Directive that validates a control value as a GUID / UUID string.
|
|
284
284
|
* Apply `guid` to a text input that expects a valid UUID.
|
|
@@ -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/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","/*\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 * 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/emailsValidatorDirective.ts","../../../projects/ars-utils/core.validators/notEqualValidatorDirective.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/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 { 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 { 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 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","/*\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 * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":";;;;;;AAQA;;;AAGG;MAMU,kBAAkB,CAAA;AAL/B,IAAA,WAAA,GAAA;;QAQW,IAAA,CAAA,SAAS,GAAG,KAAK,CAAsE,SAAS;sFAAC;AAW3G,IAAA;AATC;;;;AAIG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE;AAC3B,QAAA,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,IAAI;IAChC;8GAbW,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAlB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAHlB,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,kBAAkB,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAG1E,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAL9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,aAAa;AACvB,oBAAA,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAA,kBAAoB,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACrF,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACPD;;;AAGG;MAYU,gBAAgB,CAAA;AAX7B,IAAA,WAAA,GAAA;;QAcW,IAAA,CAAA,OAAO,GAAG,KAAK,CAAU,KAAK;oFAAC;AAkBzC,IAAA;AAhBC;;;AAGG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;QAC/B,IAAI,OAAO,GAAG,KAAK;AACnB,QAAA,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,GAAI,OAAO,CAAC,KAAmB,GAAG,IAAI;QAC7D,IAAI,CAAC,CAAC,EAAE;AACN,YAAA,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI;QACnC;aAAO;AACL,YAAA,IAAI;AACF,gBAAA,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE;YACvB;YAAE,MAAM,EAAE;QACZ;AACA,QAAA,OAAO,OAAO,GAAG,IAAI,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE;IACpD;8GApBW,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAhB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,gBAAgB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAThB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,gBAAgB,CAAC;AAC/C,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAX5B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,WAAW;AACrB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,sBAAsB,CAAC;AAC/C,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACdD;;;;;;;;;;;;AAYG;MAYU,wBAAwB,CAAA;AAWnC,IAAA,WAAA,GAAA;;QARS,IAAA,CAAA,MAAM,GAAG,KAAK,CAA8B,SAAS;mFAAC;;;QAW7D,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE;AAC3B,YAAA,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE;YAChC,IAAI,CAAC,YAAY,GAAG,KAAK,EAAE,YAAY,CAAC,SAAS,CAAC;;AAEhD,YAAA,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAC/D;;YAED,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAChE,QAAA,CAAC,CAAC;AACF,QAAA,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,CAAC;IACtE;AAEA;;;;;AAKG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,IAAI,CAAC,WAAW,GAAG,OAAO;AAC1B,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE;AACxB,QAAA,IAAI,CAAC,EAAE;AAAE,YAAA,OAAO,IAAI;AACpB,QAAA,OAAO,EAAE,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,MAAM,EAAE,aAAa,EAAE;IACtE;8GAtCW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAxB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,wBAAwB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EATxB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,wBAAwB,CAAC;AACvD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBAXpC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,UAAU;AACpB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,8BAA8B,CAAC;AACvD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACvBD;;;AAGG;MAYU,wBAAwB,CAAA;AAEnC;;;;AAIG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAW,OAAO,CAAC,KAAK;AACnC,QAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;AAC7C,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;QACtD,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACxF,QAAA,OAAO,OAAO,GAAG,IAAI,GAAG,EAAE,MAAM,EAAE,oBAAoB,EAAE;IAC1D;8GAbW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAxB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,wBAAwB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,UAAA,EAAA,SAAA,EATxB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,wBAAwB,CAAC;AACvD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBAXpC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,UAAU;AACpB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,8BAA8B,CAAC;AACvD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACdD;;;;;;;;;;;;AAYG;MAYU,0BAA0B,CAAA;AAWrC,IAAA,WAAA,GAAA;;QARS,IAAA,CAAA,QAAQ,GAAG,KAAK,CAA8B,SAAS;qFAAC;QAS/D,MAAM,CAAC,MAAK;AACV,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC7B,YAAA,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE;YAChC,IAAI,CAAC,YAAY,GAAG,KAAK,EAAE,YAAY,CAAC,SAAS,CAAC;;;AAGhD,YAAA,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAC/D;;YAED,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAChE,QAAA,CAAC,CAAC;AACF,QAAA,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE,CAAC;IACtE;AAEA;;;;;;AAMG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,IAAI,CAAC,WAAW,GAAG,OAAO;AAE1B,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE;AAChC,QAAA,IAAI,CAAC,QAAQ;AAAE,YAAA,OAAO,IAAI;QAE1B,MAAM,OAAO,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,MAAM,QAAQ,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,CAAC;AACzF,QAAA,MAAM,MAAM,GAA4B,OAAO,GAAG,IAAI,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE;QAE3E,IAAI,MAAM,EAAE;YACV,OAAO,CAAC,aAAa,EAAE;QACzB;AAAO,aAAA,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;AACxC,YAAA,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC,MAAM,IAAI,EAAE;;;AAG7D,YAAA,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AACpF,YAAA,QAAQ,CAAC,sBAAsB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YACrE,QAAQ,CAAC,aAAa,EAAE;YACxB,QAAQ,CAAC,WAAW,EAAE;QACxB;AACA,QAAA,OAAO,MAAM;IACf;8GAtDW,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAA1B,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAT1B;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,0BAA0B,CAAC;AACzD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAXtC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,YAAY;AACtB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,gCAAgC,CAAC;AACzD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACvBD;;;AAGG;MAYU,sBAAsB,CAAA;AAEjC;;;;AAIG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAW,OAAO,CAAC,KAAK;AACnC,QAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;AAC7C,QAAA,OAAO,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE;IACtE;8GAXW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAtB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,QAAA,EAAA,SAAA,EATtB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,sBAAsB,CAAC;AACrD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAXlC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,QAAQ;AAClB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,4BAA4B,CAAC;AACrD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACbD;;;AAGG;MAYU,yBAAyB,CAAA;AAEpC;;;;AAIG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAW,OAAO,CAAC,KAAK;AACnC,QAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;QAC7C,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC;AAC3C,QAAA,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE;AAC9C,QAAA,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;AAC1B,QAAA,OAAO,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE;IACnE;8GAdW,yBAAyB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAzB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,yBAAyB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,WAAA,EAAA,SAAA,EATzB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,yBAAyB,CAAC;AACxD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,yBAAyB,EAAA,UAAA,EAAA,CAAA;kBAXrC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,WAAW;AACrB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,+BAA+B,CAAC;AACxD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACdD;;;AAGG;MAYU,2BAA2B,CAAA;AAEtC;;;;AAIG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAW,OAAO,CAAC,KAAK;AACnC,QAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;QAC7C,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC;AAC3C,QAAA,IAAI,CAAC,MAAM;AAAE,YAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE;QAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;AAClC,QAAA,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;AAC1B,QAAA,OAAO,CAAC,IAAI,KAAK,GAAG,IAAI,GAAG,EAAE,SAAS,EAAE,aAAa,EAAE;IACzD;8GAfW,2BAA2B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAA3B,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,2BAA2B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,aAAA,EAAA,SAAA,EAT3B;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,2BAA2B,CAAC;AAC1D,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,2BAA2B,EAAA,UAAA,EAAA,CAAA;kBAXvC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,aAAa;AACvB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,iCAAiC,CAAC;AAC1D,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACfD;;;AAGG;MAYU,qBAAqB,CAAA;AAEhC;;;;AAIG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAW,OAAO,CAAC,KAAK;AACnC,QAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;AAC7C,QAAA,OAAO,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,aAAa,EAAE;IACpE;8GAXW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAArB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EATrB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,qBAAqB,CAAC;AACpD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBAXjC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,OAAO;AACjB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,2BAA2B,CAAC;AACpD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACfD;;;AAGG;MAYU,0BAA0B,CAAA;AAXvC,IAAA,WAAA,GAAA;;QAcW,IAAA,CAAA,SAAS,GAAG,KAAK,CAAS,CAAC;sFAAC;;QAG5B,IAAA,CAAA,SAAS,GAAG,KAAK,CAAS,CAAC;sFAAC;;QAG5B,IAAA,CAAA,IAAI,GAAG,KAAK,CAAqB,SAAS;iFAAC;AAcrD,IAAA;AAZC;;;;AAIG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK;AAC3B,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,IAAI;QACvB,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;AAC1B,QAAA,MAAM,OAAO,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE;AAC9D,QAAA,OAAO,OAAO,GAAG,IAAI,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE;IACrD;8GAtBW,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAA1B,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAT1B;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,0BAA0B,CAAC;AACzD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAXtC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,YAAY;AACtB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,gCAAgC,CAAC;AACzD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACdD;;;AAGG;MAYU,0BAA0B,CAAA;AAXvC,IAAA,WAAA,GAAA;;QAcW,IAAA,CAAA,QAAQ,GAAG,KAAK,CAAS,CAAC;qFAAC;AAarC,IAAA;AAXC;;;;AAIG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAW,OAAO,CAAC,KAAK;AACnC,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,IAAI;AACvB,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;AAC9C,QAAA,OAAO,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE;IACtE;8GAfW,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAA1B,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAT1B;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,0BAA0B,CAAC;AACzD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAXtC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,YAAY;AACtB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,gCAAgC,CAAC;AACzD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACbD;;;AAGG;MAYU,0BAA0B,CAAA;AAErC;;;AAGG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAW,OAAO,CAAC,KAAK,IAAI,EAAE;QACzC,MAAM,QAAQ,GAAG,WAAW,CAAC,yBAAyB,CAAC,KAAK,CAAC;AAC7D,QAAA,OAAO,QAAQ,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE;IAC9D;8GAVW,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAA1B,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,SAAA,EAT1B;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,0BAA0B,CAAC;AACzD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAXtC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,YAAY;AACtB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,gCAAgC,CAAC;AACzD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACfD;;;AAGG;MAYU,sBAAsB,CAAA;AAXnC,IAAA,WAAA,GAAA;;QAcW,IAAA,CAAA,KAAK,GAAG,KAAK,CAAqB,SAAS;kFAAC;AA0CtD,IAAA;AAxCC;;;;AAIG;AACK,IAAA,OAAO,CAAC,KAAa,EAAA;QAC3B,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;AAC1B,QAAA,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAC7B,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE;YAAE,OAAO,CAAC,CAAC;QAC7C,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE;YAAE,OAAO,CAAC,CAAC;AAC7C,QAAA,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE;IACtB;AAEA;;;;;AAKG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAW,OAAO,CAAC,KAAK;AACnC,QAAA,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;QAE7C,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;QAC7B,IAAI,CAAC,KAAK,CAAC,CAAC;AAAE,YAAA,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE;AAE5C,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,EAAE;QAC/B,IAAI,UAAU,EAAE;AACd,YAAA,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAG;AAC7C,gBAAA,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1C,gBAAA,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACvC,gBAAA,OAAO,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;AACrD,YAAA,CAAC,CAAC;AACF,YAAA,OAAO,OAAO,GAAG,IAAI,GAAG,EAAE,IAAI,EAAE,aAAa,EAAE;QACjD;AAEA,QAAA,OAAO,IAAI;IACb;8GA5CW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAtB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EATtB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,sBAAsB,CAAC;AACrD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAXlC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,QAAQ;AAClB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,4BAA4B,CAAC;AACrD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACdD;;;AAGG;MAYU,0BAA0B,CAAA;AAErC;;;;AAIG;AACH,IAAA,QAAQ,CAAC,OAAwB,EAAA;AAC/B,QAAA,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK;AAC5B,QAAA,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,IAAI;QAC1E,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC5D;8GAXW,0BAA0B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAA1B,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,0BAA0B,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,SAAA,EAT1B;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,0BAA0B,CAAC;AACzD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACF,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA,CAAA;;2FAGU,0BAA0B,EAAA,UAAA,EAAA,CAAA;kBAXtC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,YAAY;AACtB,oBAAA,SAAS,EAAE;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,gCAAgC,CAAC;AACzD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA;AACD,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;;ACtBD;;;;;;;AAOG;;ACPH;;AAEG;;;;"}
|
|
@@ -117,11 +117,11 @@ class ShellBusyComponent {
|
|
|
117
117
|
this.progressMode.set(progress > 0 ? 'determinate' : progressMode);
|
|
118
118
|
}
|
|
119
119
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ShellBusyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
120
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ShellBusyComponent, isStandalone: true, selector: "ars-shell-busy", host: { properties: { "class.ars-hidden": "!visible()", "class.ars-dark": "dark()" } }, ngImport: i0, template: "<div class=\"scrim\"></div>\n\n@if (type() === 'hourglass' || type() === 'wait') {\n<div class=\"bare\">\n <svg class=\"hourglass\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M6 2h12v6l-4 4 4 4v6H6v-6l4-4-4-4zm2 2v3.2l4 4 4-4V4zm0 16h8v-3.2l-4-4-4 4z\" />\n </svg>\n @if (type() === 'hourglass' && message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n</div>\n} @else {\n<div class=\"panel\" role=\"status\" aria-live=\"polite\">\n @if (message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n\n @if (type() === 'bar') {\n <div class=\"bar\" [class.indeterminate]=\"progressMode() === 'indeterminate'\">\n <div class=\"bar-fill\" [style.width.%]=\"progressMode() === 'determinate' ? progress() : null\"></div>\n </div>\n } @else if (type() === 'spinner') {\n <svg class=\"spinner\" [class.indeterminate]=\"progressMode() === 'indeterminate'\" viewBox=\"0 0 70 70\"\n aria-hidden=\"true\">\n <circle class=\"track\" cx=\"35\" cy=\"35\" r=\"31.5\"></circle>\n <circle class=\"arc\" cx=\"35\" cy=\"35\" r=\"31.5\" [style.stroke-dasharray]=\"circumference\"\n [style.stroke-dashoffset]=\"progressMode() === 'determinate' ? dashOffset() : null\"></circle>\n </svg>\n }\n\n @if (progress() > 0) {\n <div class=\"percent\"><b>{{ progress() }}%</b></div>\n }\n</div>\n}\n", styles: [":host{--_surface: var(--ars-dialog-background-color, var(--mat-sys-surface-container-high, #e6eae8));--_on-surface: var(--ars-color-text, var(--mat-sys-on-surface, #191c1b));--_scrim: var(--ars-busy-scrim-color, rgba(0, 0, 0, .28));--_primary: var(--ars-color-primary, var(--mat-sys-primary, #00a293));--_track: var(--ars-
|
|
120
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ShellBusyComponent, isStandalone: true, selector: "ars-shell-busy", host: { properties: { "class.ars-hidden": "!visible()", "class.ars-dark": "dark()" } }, ngImport: i0, template: "<div class=\"scrim\"></div>\n\n@if (type() === 'hourglass' || type() === 'wait') {\n<div class=\"bare\">\n <svg class=\"hourglass\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M6 2h12v6l-4 4 4 4v6H6v-6l4-4-4-4zm2 2v3.2l4 4 4-4V4zm0 16h8v-3.2l-4-4-4 4z\" />\n </svg>\n @if (type() === 'hourglass' && message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n</div>\n} @else {\n<div class=\"panel\" role=\"status\" aria-live=\"polite\">\n @if (message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n\n @if (type() === 'bar') {\n <div class=\"bar\" [class.indeterminate]=\"progressMode() === 'indeterminate'\">\n <div class=\"bar-fill\" [style.width.%]=\"progressMode() === 'determinate' ? progress() : null\"></div>\n </div>\n } @else if (type() === 'spinner') {\n <svg class=\"spinner\" [class.indeterminate]=\"progressMode() === 'indeterminate'\" viewBox=\"0 0 70 70\"\n aria-hidden=\"true\">\n <circle class=\"track\" cx=\"35\" cy=\"35\" r=\"31.5\"></circle>\n <circle class=\"arc\" cx=\"35\" cy=\"35\" r=\"31.5\" [style.stroke-dasharray]=\"circumference\"\n [style.stroke-dashoffset]=\"progressMode() === 'determinate' ? dashOffset() : null\"></circle>\n </svg>\n }\n\n @if (progress() > 0) {\n <div class=\"percent\"><b>{{ progress() }}%</b></div>\n }\n</div>\n}\n", styles: [":host{--_surface: var(--ars-shell-dialog-background-color, var(--mat-sys-surface-container-high, #e6eae8));--_on-surface: var(--ars-color-text, var(--mat-sys-on-surface, #191c1b));--_scrim: var(--ars-shell-busy-scrim-color, rgba(0, 0, 0, .28));--_primary: var(--ars-color-primary, var(--mat-sys-primary, #00a293));--_track: var(--ars-shell-busy-track-color, var(--mat-sys-surface-container-highest, #d5dbd8));--_bare: var(--ars-shell-busy-bare-color, #ffffff);color-scheme:light;margin:0;border:0;padding:0;background:none;color:inherit;overflow:visible;width:100%;height:100%;position:fixed;inset:0;z-index:var(--ars-shell-busy-z-index, 1090);display:flex;align-items:center;justify-content:center;font-family:var(--mat-sys-body-medium-font, Roboto, sans-serif);color:var(--_on-surface)}:host(.ars-dark){--_surface: var(--ars-shell-dialog-background-color, var(--mat-sys-surface-container-high, #282a29));--_on-surface: var(--ars-color-text, var(--mat-sys-on-surface, #e0e2e5));--_scrim: var(--ars-shell-busy-scrim-color, rgba(0, 0, 0, .45));--_primary: var(--ars-color-primary, var(--mat-sys-primary, #53dbc9));--_track: var(--ars-shell-busy-track-color, var(--mat-sys-surface-container-highest, #3a3d3c));color-scheme:dark}:host::backdrop{display:none}:host(.ars-hidden){display:none}.scrim{position:absolute;inset:0;background:var(--_scrim);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:ars-busy-fade .2s cubic-bezier(0,0,.2,1)}@keyframes ars-busy-fade{0%{opacity:0}to{opacity:1}}.panel{position:relative;min-width:250px;max-width:calc(100% - 24px);margin:12px;padding:24px;border-radius:var(--ars-shell-dialog-radius, 24px);background:var(--_surface);box-shadow:var(--ars-shell-dialog-elevation, 0 4px 8px 0 rgba(0, 0, 0, .2), 0 6px 20px 0 rgba(0, 0, 0, .19));text-align:center}.bare{position:relative;display:flex;flex-direction:column;align-items:center;color:var(--_bare)}.message{font-size:larger;font-weight:600;padding-bottom:15px;text-align:center}.bare .message{padding-top:15px;padding-bottom:0}.percent{padding-top:8px;font-size:smaller}.bar{position:relative;max-width:350px;height:4px;margin:15px auto 0;overflow:hidden;border-radius:2px;background:var(--_track)}.bar-fill{position:absolute;inset:0 auto 0 0;width:0;border-radius:inherit;background:var(--_primary);transition:width .12s linear}.bar.indeterminate .bar-fill{width:40%;transition:none;animation:ars-busy-bar 1.6s cubic-bezier(.65,.02,.35,1) infinite}@keyframes ars-busy-bar{0%{left:-40%}to{left:100%}}.spinner{display:block;width:70px;height:70px;margin:15px auto 0;transform:rotate(-90deg)}.spinner circle{fill:none;stroke-width:7;stroke-linecap:round}.spinner .track{stroke:var(--_track)}.spinner .arc{stroke:var(--_primary);transition:stroke-dashoffset .12s linear}.spinner.indeterminate{animation:ars-busy-rotate 1.4s linear infinite}.spinner.indeterminate .arc{transition:none;stroke-dashoffset:0;animation:ars-busy-dash 1.4s ease-in-out infinite}@keyframes ars-busy-rotate{0%{transform:rotate(-90deg)}to{transform:rotate(270deg)}}@keyframes ars-busy-dash{0%{stroke-dasharray:15 183}50%{stroke-dasharray:145 53}to{stroke-dasharray:15 183}}.hourglass{width:80px;height:80px;fill:currentColor;animation:ars-busy-hourglass 3s linear infinite}@keyframes ars-busy-hourglass{0%{transform:rotate(360deg)}to{transform:rotate(0)}}@media(prefers-reduced-motion:reduce){.scrim{animation:none}.bar.indeterminate .bar-fill,.spinner.indeterminate,.spinner.indeterminate .arc,.hourglass{animation-duration:4s}}\n"], dependencies: [{ kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
121
121
|
}
|
|
122
122
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ShellBusyComponent, decorators: [{
|
|
123
123
|
type: Component,
|
|
124
|
-
args: [{ selector: 'ars-shell-busy', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SafeHtmlPipe], host: { '[class.ars-hidden]': '!visible()', '[class.ars-dark]': 'dark()' }, template: "<div class=\"scrim\"></div>\n\n@if (type() === 'hourglass' || type() === 'wait') {\n<div class=\"bare\">\n <svg class=\"hourglass\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M6 2h12v6l-4 4 4 4v6H6v-6l4-4-4-4zm2 2v3.2l4 4 4-4V4zm0 16h8v-3.2l-4-4-4 4z\" />\n </svg>\n @if (type() === 'hourglass' && message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n</div>\n} @else {\n<div class=\"panel\" role=\"status\" aria-live=\"polite\">\n @if (message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n\n @if (type() === 'bar') {\n <div class=\"bar\" [class.indeterminate]=\"progressMode() === 'indeterminate'\">\n <div class=\"bar-fill\" [style.width.%]=\"progressMode() === 'determinate' ? progress() : null\"></div>\n </div>\n } @else if (type() === 'spinner') {\n <svg class=\"spinner\" [class.indeterminate]=\"progressMode() === 'indeterminate'\" viewBox=\"0 0 70 70\"\n aria-hidden=\"true\">\n <circle class=\"track\" cx=\"35\" cy=\"35\" r=\"31.5\"></circle>\n <circle class=\"arc\" cx=\"35\" cy=\"35\" r=\"31.5\" [style.stroke-dasharray]=\"circumference\"\n [style.stroke-dashoffset]=\"progressMode() === 'determinate' ? dashOffset() : null\"></circle>\n </svg>\n }\n\n @if (progress() > 0) {\n <div class=\"percent\"><b>{{ progress() }}%</b></div>\n }\n</div>\n}\n", styles: [":host{--_surface: var(--ars-dialog-background-color, var(--mat-sys-surface-container-high, #e6eae8));--_on-surface: var(--ars-color-text, var(--mat-sys-on-surface, #191c1b));--_scrim: var(--ars-busy-scrim-color, rgba(0, 0, 0, .28));--_primary: var(--ars-color-primary, var(--mat-sys-primary, #00a293));--_track: var(--ars-
|
|
124
|
+
args: [{ selector: 'ars-shell-busy', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SafeHtmlPipe], host: { '[class.ars-hidden]': '!visible()', '[class.ars-dark]': 'dark()' }, template: "<div class=\"scrim\"></div>\n\n@if (type() === 'hourglass' || type() === 'wait') {\n<div class=\"bare\">\n <svg class=\"hourglass\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M6 2h12v6l-4 4 4 4v6H6v-6l4-4-4-4zm2 2v3.2l4 4 4-4V4zm0 16h8v-3.2l-4-4-4 4z\" />\n </svg>\n @if (type() === 'hourglass' && message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n</div>\n} @else {\n<div class=\"panel\" role=\"status\" aria-live=\"polite\">\n @if (message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n\n @if (type() === 'bar') {\n <div class=\"bar\" [class.indeterminate]=\"progressMode() === 'indeterminate'\">\n <div class=\"bar-fill\" [style.width.%]=\"progressMode() === 'determinate' ? progress() : null\"></div>\n </div>\n } @else if (type() === 'spinner') {\n <svg class=\"spinner\" [class.indeterminate]=\"progressMode() === 'indeterminate'\" viewBox=\"0 0 70 70\"\n aria-hidden=\"true\">\n <circle class=\"track\" cx=\"35\" cy=\"35\" r=\"31.5\"></circle>\n <circle class=\"arc\" cx=\"35\" cy=\"35\" r=\"31.5\" [style.stroke-dasharray]=\"circumference\"\n [style.stroke-dashoffset]=\"progressMode() === 'determinate' ? dashOffset() : null\"></circle>\n </svg>\n }\n\n @if (progress() > 0) {\n <div class=\"percent\"><b>{{ progress() }}%</b></div>\n }\n</div>\n}\n", styles: [":host{--_surface: var(--ars-shell-dialog-background-color, var(--mat-sys-surface-container-high, #e6eae8));--_on-surface: var(--ars-color-text, var(--mat-sys-on-surface, #191c1b));--_scrim: var(--ars-shell-busy-scrim-color, rgba(0, 0, 0, .28));--_primary: var(--ars-color-primary, var(--mat-sys-primary, #00a293));--_track: var(--ars-shell-busy-track-color, var(--mat-sys-surface-container-highest, #d5dbd8));--_bare: var(--ars-shell-busy-bare-color, #ffffff);color-scheme:light;margin:0;border:0;padding:0;background:none;color:inherit;overflow:visible;width:100%;height:100%;position:fixed;inset:0;z-index:var(--ars-shell-busy-z-index, 1090);display:flex;align-items:center;justify-content:center;font-family:var(--mat-sys-body-medium-font, Roboto, sans-serif);color:var(--_on-surface)}:host(.ars-dark){--_surface: var(--ars-shell-dialog-background-color, var(--mat-sys-surface-container-high, #282a29));--_on-surface: var(--ars-color-text, var(--mat-sys-on-surface, #e0e2e5));--_scrim: var(--ars-shell-busy-scrim-color, rgba(0, 0, 0, .45));--_primary: var(--ars-color-primary, var(--mat-sys-primary, #53dbc9));--_track: var(--ars-shell-busy-track-color, var(--mat-sys-surface-container-highest, #3a3d3c));color-scheme:dark}:host::backdrop{display:none}:host(.ars-hidden){display:none}.scrim{position:absolute;inset:0;background:var(--_scrim);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:ars-busy-fade .2s cubic-bezier(0,0,.2,1)}@keyframes ars-busy-fade{0%{opacity:0}to{opacity:1}}.panel{position:relative;min-width:250px;max-width:calc(100% - 24px);margin:12px;padding:24px;border-radius:var(--ars-shell-dialog-radius, 24px);background:var(--_surface);box-shadow:var(--ars-shell-dialog-elevation, 0 4px 8px 0 rgba(0, 0, 0, .2), 0 6px 20px 0 rgba(0, 0, 0, .19));text-align:center}.bare{position:relative;display:flex;flex-direction:column;align-items:center;color:var(--_bare)}.message{font-size:larger;font-weight:600;padding-bottom:15px;text-align:center}.bare .message{padding-top:15px;padding-bottom:0}.percent{padding-top:8px;font-size:smaller}.bar{position:relative;max-width:350px;height:4px;margin:15px auto 0;overflow:hidden;border-radius:2px;background:var(--_track)}.bar-fill{position:absolute;inset:0 auto 0 0;width:0;border-radius:inherit;background:var(--_primary);transition:width .12s linear}.bar.indeterminate .bar-fill{width:40%;transition:none;animation:ars-busy-bar 1.6s cubic-bezier(.65,.02,.35,1) infinite}@keyframes ars-busy-bar{0%{left:-40%}to{left:100%}}.spinner{display:block;width:70px;height:70px;margin:15px auto 0;transform:rotate(-90deg)}.spinner circle{fill:none;stroke-width:7;stroke-linecap:round}.spinner .track{stroke:var(--_track)}.spinner .arc{stroke:var(--_primary);transition:stroke-dashoffset .12s linear}.spinner.indeterminate{animation:ars-busy-rotate 1.4s linear infinite}.spinner.indeterminate .arc{transition:none;stroke-dashoffset:0;animation:ars-busy-dash 1.4s ease-in-out infinite}@keyframes ars-busy-rotate{0%{transform:rotate(-90deg)}to{transform:rotate(270deg)}}@keyframes ars-busy-dash{0%{stroke-dasharray:15 183}50%{stroke-dasharray:145 53}to{stroke-dasharray:15 183}}.hourglass{width:80px;height:80px;fill:currentColor;animation:ars-busy-hourglass 3s linear infinite}@keyframes ars-busy-hourglass{0%{transform:rotate(360deg)}to{transform:rotate(0)}}@media(prefers-reduced-motion:reduce){.scrim{animation:none}.bar.indeterminate .bar-fill,.spinner.indeterminate,.spinner.indeterminate .arc,.hourglass{animation-duration:4s}}\n"] }]
|
|
125
125
|
}], ctorParameters: () => [] });
|
|
126
126
|
|
|
127
127
|
/**
|
|
@@ -163,6 +163,16 @@ class ShellMessageComponent {
|
|
|
163
163
|
...(ngDevMode ? [{ debugName: "okButton" }] : /* istanbul ignore next */ []));
|
|
164
164
|
/** Unique id tying the panel to its heading for assistive technology. */
|
|
165
165
|
this.titleId = `ars-shell-message-title-${Math.random().toString(36).slice(2, 10)}`;
|
|
166
|
+
/** Unique id tying the details panel to the header that opens it. */
|
|
167
|
+
this.detailsId = `ars-shell-message-details-${Math.random().toString(36).slice(2, 10)}`;
|
|
168
|
+
/**
|
|
169
|
+
* Whether the technical details are open.
|
|
170
|
+
*
|
|
171
|
+
* Closed on arrival, and closed again by every {@link setData}: the message is what the user is
|
|
172
|
+
* meant to read, and a stack trace unfolded under it is noise until they ask for it.
|
|
173
|
+
*/
|
|
174
|
+
this.detailsOpen = signal(false, /* @ts-ignore */
|
|
175
|
+
...(ngDevMode ? [{ debugName: "detailsOpen" }] : /* istanbul ignore next */ []));
|
|
166
176
|
/** Current content, with the defaults the shell relies on already applied. */
|
|
167
177
|
this.data = signal({ message: '', title: 'Informazioni', okCaption: 'Ok', width: 500 }, /* @ts-ignore */
|
|
168
178
|
...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
@@ -197,8 +207,16 @@ class ShellMessageComponent {
|
|
|
197
207
|
*/
|
|
198
208
|
setData(data) {
|
|
199
209
|
this.data.set({ title: 'Informazioni', okCaption: 'Ok', width: 500, ...data });
|
|
210
|
+
this.detailsOpen.set(false);
|
|
200
211
|
this.scheduleDismiss(this.data().dismissAfter);
|
|
201
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Opens or closes the technical details panel.
|
|
215
|
+
* @returns void
|
|
216
|
+
*/
|
|
217
|
+
toggleDetails() {
|
|
218
|
+
this.detailsOpen.update(open => !open);
|
|
219
|
+
}
|
|
202
220
|
/**
|
|
203
221
|
* Dismisses the panel. Safe to call more than once: only the first call is announced.
|
|
204
222
|
* @returns void
|
|
@@ -288,11 +306,11 @@ class ShellMessageComponent {
|
|
|
288
306
|
}
|
|
289
307
|
}
|
|
290
308
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ShellMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
291
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ShellMessageComponent, isStandalone: true, selector: "ars-shell-message", outputs: { closed: "closed" }, host: { listeners: { "document:keydown": "onKeydown($event)" }, properties: { "class.ars-dark": "dark()" } }, viewQueries: [{ propertyName: "panel", first: true, predicate: ["panel"], descendants: true, isSignal: true }, { propertyName: "okButton", first: true, predicate: ["ok"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"scrim\" (click)=\"close()\"></div>\n\n<div #panel class=\"panel\" role=\"alertdialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"titleId\"\n [style.max-width.px]=\"data().width\">\n\n <h2 class=\"title\" [id]=\"titleId\" [innerHTML]=\"data().title | safeHtml\"></h2>\n\n <div class=\"content\">\n @if (data().message) {\n <div class=\"message\" [innerHTML]=\"data().message | safeHtml\"></div>\n }\n @if (data().details) {\n <div class=\"details-box\">\n <
|
|
309
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ShellMessageComponent, isStandalone: true, selector: "ars-shell-message", outputs: { closed: "closed" }, host: { listeners: { "document:keydown": "onKeydown($event)" }, properties: { "class.ars-dark": "dark()" } }, viewQueries: [{ propertyName: "panel", first: true, predicate: ["panel"], descendants: true, isSignal: true }, { propertyName: "okButton", first: true, predicate: ["ok"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"scrim\" (click)=\"close()\"></div>\n\n<div #panel class=\"panel\" role=\"alertdialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"titleId\"\n [style.max-width.px]=\"data().width\">\n\n <h2 class=\"title\" [id]=\"titleId\" [innerHTML]=\"data().title | safeHtml\"></h2>\n\n <div class=\"content\">\n @if (data().message) {\n <div class=\"message\" [innerHTML]=\"data().message | safeHtml\"></div>\n }\n @if (data().details) {\n <div class=\"details-box\" [class.open]=\"detailsOpen()\">\n <button type=\"button\" class=\"details-header\" (click)=\"toggleDetails()\"\n [attr.aria-expanded]=\"detailsOpen()\" [attr.aria-controls]=\"detailsId\">\n <span class=\"details-label\">Dettaglio</span>\n <svg class=\"chevron\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M7.41 8.59 12 13.17l4.59-4.58L18 10l-6 6-6-6z\" />\n </svg>\n </button>\n <div class=\"details-body\">\n <div class=\"details\" [id]=\"detailsId\" [attr.aria-hidden]=\"!detailsOpen()\">\n <div class=\"details-text\" [innerHTML]=\"data().details | safeHtml\"></div>\n </div>\n </div>\n </div>\n }\n </div>\n\n <div class=\"actions\">\n <button type=\"button\" class=\"icon-button\" (click)=\"copy()\"\n [title]=\"copied() ? 'Copiato negli appunti' : 'Copia negli appunti'\" aria-label=\"Copia negli appunti\">\n @if (copied()) {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\" /></svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path\n d=\"M16 1H4a2 2 0 0 0-2 2v14h2V3h12zm3 4H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2m0 16H8V7h11z\" /></svg>\n }\n </button>\n <button #ok type=\"button\" class=\"flat-button\" (click)=\"close()\">{{ data().okCaption }}</button>\n </div>\n</div>\n", styles: [":host{--_surface: var(--ars-shell-dialog-background-color, var(--mat-sys-surface-container-high, #e6eae8));--_on-surface: var(--ars-color-text, var(--mat-sys-on-surface, #191c1b));--_secondary: var(--ars-color-secondary, var(--mat-sys-on-surface-variant, #4a635f));--_divider: var(--ars-color-divider, #757d87);--_scrim: var(--ars-shell-dialog-scrim-color, rgba(0, 0, 0, .24));--_primary: var(--ars-color-primary, var(--mat-sys-primary, #00a293));--_on-primary: var(--ars-color-on-primary, var(--mat-sys-on-primary, #ffffff));--_hover: var(--ars-item-hover-background-color, rgba(0, 0, 0, .08));--_sunken: var(--ars-shell-dialog-sunken-background-color, rgba(0, 0, 0, .05));color-scheme:light;margin:0;border:0;padding:0;background:none;color:inherit;overflow:visible;width:100%;height:100%;position:fixed;inset:0;z-index:var(--ars-shell-dialog-z-index, 1100);display:flex;align-items:center;justify-content:center;box-sizing:border-box}:host(.ars-dark){--_surface: var(--ars-shell-dialog-background-color, var(--mat-sys-surface-container-high, #282a29));--_on-surface: var(--ars-color-text, var(--mat-sys-on-surface, #e0e2e5));--_secondary: var(--ars-color-secondary, var(--mat-sys-on-surface-variant, #b1ccc6));--_scrim: var(--ars-shell-dialog-scrim-color, rgba(0, 0, 0, .45));--_primary: var(--ars-color-primary, var(--mat-sys-primary, #53dbc9));--_on-primary: var(--ars-color-on-primary, var(--mat-sys-on-primary, #00382f));--_hover: var(--ars-item-hover-background-color, rgba(255, 255, 255, .08));--_sunken: var(--ars-shell-dialog-sunken-background-color, rgba(0, 0, 0, .22));color-scheme:dark}:host::backdrop{display:none}.scrim{position:absolute;inset:0;background:var(--_scrim);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:ars-shell-fade .2s cubic-bezier(0,0,.2,1)}.panel{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;margin:12px;max-height:calc(100% - 24px);box-sizing:border-box;border-radius:var(--ars-shell-dialog-radius, 28px);background:var(--_surface);color:var(--_on-surface);box-shadow:var(--ars-shell-dialog-elevation, 0 4px 8px 3px rgba(0, 0, 0, .15), 0 1px 3px 0 rgba(0, 0, 0, .3));font-family:var(--mat-sys-body-medium-font, Roboto, sans-serif);text-align:left;animation:ars-shell-enter .15s cubic-bezier(0,0,.2,1)}.title{margin:0;padding:24px 24px 16px;font:var(--mat-sys-headline-small, 400 24px/32px Roboto, sans-serif);color:inherit}.content{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;padding:0;font:var(--mat-sys-body-medium, 400 14px/20px Roboto, sans-serif)}.message{flex:0 1 auto;min-height:0;padding:0 24px 24px;overflow-y:auto;overscroll-behavior:contain}.details-box{flex:0 1000 auto;min-height:0;display:flex;flex-direction:column;margin:0 16px 4px;border-radius:12px;background:transparent;transition:background-color .2s cubic-bezier(0,0,.2,1)}.details-box.open{background:var(--_sunken)}.details-header{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;height:44px;padding:0 8px;border-radius:12px;background:transparent;color:var(--_secondary);text-align:left}.details-header:hover{background:var(--_hover)}.details-label{font-size:.75em;letter-spacing:.06em;text-transform:uppercase}.chevron{width:20px;height:20px;fill:currentColor;transition:transform .2s cubic-bezier(0,0,.2,1)}.details-box.open .chevron{transform:rotate(180deg)}.details-body{display:grid;grid-template-rows:0fr;min-height:0;max-height:320px;transition:grid-template-rows .2s cubic-bezier(0,0,.2,1)}.details-box.open .details-body{grid-template-rows:1fr}.details{min-height:0;overflow:hidden}.details-box.open .details{overflow-y:auto;overscroll-behavior:contain}.details-text{padding:0 8px 12px;font-size:.85em}.actions{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:16px 24px 24px}button{font-family:inherit;cursor:pointer;border:none}button:focus-visible{outline:3px solid var(--_primary);outline-offset:2px}.icon-button{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;padding:0;border-radius:50%;background:transparent;color:inherit}.icon-button svg{width:24px;height:24px;fill:currentColor}.icon-button:hover{background:var(--_hover)}.flat-button{height:40px;padding:0 24px;border-radius:20px;background:var(--_primary);color:var(--_on-primary);font:var(--mat-sys-label-large, 500 14px/20px Roboto, sans-serif)}.flat-button:hover{filter:brightness(1.08)}@keyframes ars-shell-fade{0%{opacity:0}to{opacity:1}}@keyframes ars-shell-enter{0%{opacity:0;transform:scale(.7)}to{opacity:1;transform:none}}@media(prefers-reduced-motion:reduce){.scrim,.panel{animation:none}.details-box,.details-body,.chevron{transition:none}}\n"], dependencies: [{ kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
292
310
|
}
|
|
293
311
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ShellMessageComponent, decorators: [{
|
|
294
312
|
type: Component,
|
|
295
|
-
args: [{ selector: 'ars-shell-message', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SafeHtmlPipe], host: { '[class.ars-dark]': 'dark()' }, template: "<div class=\"scrim\" (click)=\"close()\"></div>\n\n<div #panel class=\"panel\" role=\"alertdialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"titleId\"\n [style.max-width.px]=\"data().width\">\n\n <h2 class=\"title\" [id]=\"titleId\" [innerHTML]=\"data().title | safeHtml\"></h2>\n\n <div class=\"content\">\n @if (data().message) {\n <div class=\"message\" [innerHTML]=\"data().message | safeHtml\"></div>\n }\n @if (data().details) {\n <div class=\"details-box\">\n <
|
|
313
|
+
args: [{ selector: 'ars-shell-message', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SafeHtmlPipe], host: { '[class.ars-dark]': 'dark()' }, template: "<div class=\"scrim\" (click)=\"close()\"></div>\n\n<div #panel class=\"panel\" role=\"alertdialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"titleId\"\n [style.max-width.px]=\"data().width\">\n\n <h2 class=\"title\" [id]=\"titleId\" [innerHTML]=\"data().title | safeHtml\"></h2>\n\n <div class=\"content\">\n @if (data().message) {\n <div class=\"message\" [innerHTML]=\"data().message | safeHtml\"></div>\n }\n @if (data().details) {\n <div class=\"details-box\" [class.open]=\"detailsOpen()\">\n <button type=\"button\" class=\"details-header\" (click)=\"toggleDetails()\"\n [attr.aria-expanded]=\"detailsOpen()\" [attr.aria-controls]=\"detailsId\">\n <span class=\"details-label\">Dettaglio</span>\n <svg class=\"chevron\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M7.41 8.59 12 13.17l4.59-4.58L18 10l-6 6-6-6z\" />\n </svg>\n </button>\n <div class=\"details-body\">\n <div class=\"details\" [id]=\"detailsId\" [attr.aria-hidden]=\"!detailsOpen()\">\n <div class=\"details-text\" [innerHTML]=\"data().details | safeHtml\"></div>\n </div>\n </div>\n </div>\n }\n </div>\n\n <div class=\"actions\">\n <button type=\"button\" class=\"icon-button\" (click)=\"copy()\"\n [title]=\"copied() ? 'Copiato negli appunti' : 'Copia negli appunti'\" aria-label=\"Copia negli appunti\">\n @if (copied()) {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\" /></svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path\n d=\"M16 1H4a2 2 0 0 0-2 2v14h2V3h12zm3 4H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2m0 16H8V7h11z\" /></svg>\n }\n </button>\n <button #ok type=\"button\" class=\"flat-button\" (click)=\"close()\">{{ data().okCaption }}</button>\n </div>\n</div>\n", styles: [":host{--_surface: var(--ars-shell-dialog-background-color, var(--mat-sys-surface-container-high, #e6eae8));--_on-surface: var(--ars-color-text, var(--mat-sys-on-surface, #191c1b));--_secondary: var(--ars-color-secondary, var(--mat-sys-on-surface-variant, #4a635f));--_divider: var(--ars-color-divider, #757d87);--_scrim: var(--ars-shell-dialog-scrim-color, rgba(0, 0, 0, .24));--_primary: var(--ars-color-primary, var(--mat-sys-primary, #00a293));--_on-primary: var(--ars-color-on-primary, var(--mat-sys-on-primary, #ffffff));--_hover: var(--ars-item-hover-background-color, rgba(0, 0, 0, .08));--_sunken: var(--ars-shell-dialog-sunken-background-color, rgba(0, 0, 0, .05));color-scheme:light;margin:0;border:0;padding:0;background:none;color:inherit;overflow:visible;width:100%;height:100%;position:fixed;inset:0;z-index:var(--ars-shell-dialog-z-index, 1100);display:flex;align-items:center;justify-content:center;box-sizing:border-box}:host(.ars-dark){--_surface: var(--ars-shell-dialog-background-color, var(--mat-sys-surface-container-high, #282a29));--_on-surface: var(--ars-color-text, var(--mat-sys-on-surface, #e0e2e5));--_secondary: var(--ars-color-secondary, var(--mat-sys-on-surface-variant, #b1ccc6));--_scrim: var(--ars-shell-dialog-scrim-color, rgba(0, 0, 0, .45));--_primary: var(--ars-color-primary, var(--mat-sys-primary, #53dbc9));--_on-primary: var(--ars-color-on-primary, var(--mat-sys-on-primary, #00382f));--_hover: var(--ars-item-hover-background-color, rgba(255, 255, 255, .08));--_sunken: var(--ars-shell-dialog-sunken-background-color, rgba(0, 0, 0, .22));color-scheme:dark}:host::backdrop{display:none}.scrim{position:absolute;inset:0;background:var(--_scrim);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:ars-shell-fade .2s cubic-bezier(0,0,.2,1)}.panel{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;margin:12px;max-height:calc(100% - 24px);box-sizing:border-box;border-radius:var(--ars-shell-dialog-radius, 28px);background:var(--_surface);color:var(--_on-surface);box-shadow:var(--ars-shell-dialog-elevation, 0 4px 8px 3px rgba(0, 0, 0, .15), 0 1px 3px 0 rgba(0, 0, 0, .3));font-family:var(--mat-sys-body-medium-font, Roboto, sans-serif);text-align:left;animation:ars-shell-enter .15s cubic-bezier(0,0,.2,1)}.title{margin:0;padding:24px 24px 16px;font:var(--mat-sys-headline-small, 400 24px/32px Roboto, sans-serif);color:inherit}.content{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;padding:0;font:var(--mat-sys-body-medium, 400 14px/20px Roboto, sans-serif)}.message{flex:0 1 auto;min-height:0;padding:0 24px 24px;overflow-y:auto;overscroll-behavior:contain}.details-box{flex:0 1000 auto;min-height:0;display:flex;flex-direction:column;margin:0 16px 4px;border-radius:12px;background:transparent;transition:background-color .2s cubic-bezier(0,0,.2,1)}.details-box.open{background:var(--_sunken)}.details-header{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;height:44px;padding:0 8px;border-radius:12px;background:transparent;color:var(--_secondary);text-align:left}.details-header:hover{background:var(--_hover)}.details-label{font-size:.75em;letter-spacing:.06em;text-transform:uppercase}.chevron{width:20px;height:20px;fill:currentColor;transition:transform .2s cubic-bezier(0,0,.2,1)}.details-box.open .chevron{transform:rotate(180deg)}.details-body{display:grid;grid-template-rows:0fr;min-height:0;max-height:320px;transition:grid-template-rows .2s cubic-bezier(0,0,.2,1)}.details-box.open .details-body{grid-template-rows:1fr}.details{min-height:0;overflow:hidden}.details-box.open .details{overflow-y:auto;overscroll-behavior:contain}.details-text{padding:0 8px 12px;font-size:.85em}.actions{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:16px 24px 24px}button{font-family:inherit;cursor:pointer;border:none}button:focus-visible{outline:3px solid var(--_primary);outline-offset:2px}.icon-button{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;padding:0;border-radius:50%;background:transparent;color:inherit}.icon-button svg{width:24px;height:24px;fill:currentColor}.icon-button:hover{background:var(--_hover)}.flat-button{height:40px;padding:0 24px;border-radius:20px;background:var(--_primary);color:var(--_on-primary);font:var(--mat-sys-label-large, 500 14px/20px Roboto, sans-serif)}.flat-button:hover{filter:brightness(1.08)}@keyframes ars-shell-fade{0%{opacity:0}to{opacity:1}}@keyframes ars-shell-enter{0%{opacity:0;transform:scale(.7)}to{opacity:1;transform:none}}@media(prefers-reduced-motion:reduce){.scrim,.panel{animation:none}.details-box,.details-body,.chevron{transition:none}}\n"] }]
|
|
296
314
|
}], ctorParameters: () => [], propDecorators: { closed: [{ type: i0.Output, args: ["closed"] }], panel: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], okButton: [{ type: i0.ViewChild, args: ['ok', { isSignal: true }] }], onKeydown: [{
|
|
297
315
|
type: HostListener,
|
|
298
316
|
args: ['document:keydown', ['$event']]
|
|
@@ -326,7 +344,7 @@ const CLEAR_BUSY_GRACE = 500;
|
|
|
326
344
|
* a dialog, and it also takes the busy away immediately rather than with the grace period, so a
|
|
327
345
|
* dialog is never drawn under an overlay that is on its way out.
|
|
328
346
|
*
|
|
329
|
-
* The `--ars-shell-z-index` / `--ars-busy-z-index` pair (1100 / 1090, above the CDK's 1000) is
|
|
347
|
+
* The `--ars-shell-dialog-z-index` / `--ars-shell-busy-z-index` pair (1100 / 1090, above the CDK's 1000) is
|
|
330
348
|
* still there and still correct: it is what orders the overlays on a browser without the Popover
|
|
331
349
|
* API, where the CDK does not use it either.
|
|
332
350
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arsedizioni-ars-utils-ui.shell.mjs","sources":["../../../projects/ars-utils/ui.shell/busy-timer.ts","../../../projects/ars-utils/ui.shell/shell-busy/shell-busy.component.ts","../../../projects/ars-utils/ui.shell/shell-busy/shell-busy.component.html","../../../projects/ars-utils/ui.shell/shell-message/shell-message.component.ts","../../../projects/ars-utils/ui.shell/shell-message/shell-message.component.html","../../../projects/ars-utils/ui.shell/shell.service.ts","../../../projects/ars-utils/ui.shell/public_api.ts","../../../projects/ars-utils/ui.shell/arsedizioni-ars-utils-ui.shell.ts"],"sourcesContent":["import { Subscription, timer } from 'rxjs';\nimport { tap } from 'rxjs/operators';\nimport type { ShellService } from './shell.service';\n\n/**\n * Shows the busy overlay only if the operation is still running after a debounce delay, so that\n * an operation that answers in 30 ms never makes the screen flash.\n *\n * Whoever creates one owns it: {@link clear} must be called when the operation ends, otherwise\n * the overlay appears after the fact and stays.\n */\nexport class BusyTimer {\n private readonly subscription: Subscription;\n\n /**\n * Arms the timer.\n * @param shellService - The service that owns the overlay. A `DialogService` is accepted too,\n * since it extends `ShellService`.\n * @param due - Delay in milliseconds before the overlay appears. Defaults to `100`.\n * @param message - Text to display. Defaults to `'Operazione in corso...'`.\n */\n constructor(\n private readonly shellService: ShellService,\n due: number = 100,\n message: string = 'Operazione in corso...'\n ) {\n this.subscription = timer(due).pipe(tap(() => this.shellService.busy(message))).subscribe();\n }\n\n /**\n * Disarms the timer and takes the overlay away.\n * @returns void\n */\n clear(): void {\n this.subscription.unsubscribe();\n this.shellService.clearBusy();\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { SafeHtmlPipe, ThemeService, ThemeType } from '@arsedizioni/ars-utils/core';\n\n/** Visual style of the busy indicator. */\nexport type ShellBusyType = 'bar' | 'spinner' | 'wait' | 'hourglass';\n\n/** Progress mode of the bar and of the spinner. */\nexport type ShellBusyMode = 'determinate' | 'indeterminate';\n\n/** Circumference of the spinner circle, in user units. Kept here so the template stays arithmetic-free. */\nconst SPINNER_CIRCUMFERENCE = 2 * Math.PI * 31.5;\n\n/**\n * Overlay that blocks interaction while an operation is running, in the four styles the\n * applications use: progress bar, spinner, hourglass and bare wait.\n *\n * Reproduces `mat-progress-bar` and `mat-progress-spinner` in CSS and SVG rather than importing\n * them, because this overlay is shown from the boot path — an HTTP interceptor calls it before\n * any route exists — and `ui.shell` exists precisely so that path costs no Material.\n *\n * The instance is created once by {@link ShellService} and then reused: showing and hiding is a\n * class on the host, never a `createComponent`, so the 40-odd calls a screen costs nothing.\n */\n@Component({\n selector: 'ars-shell-busy',\n templateUrl: './shell-busy.component.html',\n styleUrl: './shell-busy.component.scss',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SafeHtmlPipe],\n host: { '[class.ars-hidden]': '!visible()', '[class.ars-dark]': 'dark()' }\n})\nexport class ShellBusyComponent {\n\n private readonly themeService = inject(ThemeService);\n\n /**\n * True when the panel must paint itself dark.\n *\n * Read from {@link ThemeService} and not from `prefers-color-scheme`, because the two do not\n * always agree: the service is what the user chose, and it may be forcing dark on a machine\n * that is on light. Following the OS instead would leave this panel the only light thing on a\n * dark screen.\n */\n protected readonly dark = signal(false);\n\n /**\n * Keeps {@link dark} in step with the service, now and at every later change.\n *\n * `'auto'` is resolved through `getTheme()`, which is the only thing that knows what the\n * operating system is currently on.\n * @returns void\n */\n private followTheme(): void {\n const resolve = (theme: ThemeType): boolean =>\n (theme === 'auto' ? this.themeService.getTheme() : theme) === 'dark';\n this.dark.set(resolve(this.themeService.getTheme()));\n this.themeService.changed\n .pipe(takeUntilDestroyed())\n .subscribe(theme => this.dark.set(resolve(theme)));\n }\n\n /** Whether the overlay is on screen. Hidden with `display: none`, so it costs no layout. */\n readonly visible = signal(false);\n\n /** Visual style of the indicator. */\n readonly type = signal<ShellBusyType>('bar');\n\n /** Current progress value (0-100), used when {@link progressMode} is `'determinate'`. */\n readonly progress = signal(0);\n\n /** Progress mode of the bar and of the spinner. */\n readonly progressMode = signal<ShellBusyMode>('indeterminate');\n\n /** Message displayed above the indicator. */\n readonly message = signal('');\n\n /** Circumference of the spinner circle, bound to `stroke-dasharray`. */\n protected readonly circumference = SPINNER_CIRCUMFERENCE;\n\n constructor() {\n this.followTheme();\n }\n\n /** Length of the spinner arc still to be drawn, derived from {@link progress}. */\n protected readonly dashOffset = computed(\n () => SPINNER_CIRCUMFERENCE * (1 - Math.min(Math.max(this.progress(), 0), 100) / 100)\n );\n\n /**\n * Updates the overlay state.\n *\n * Same contract as the `BusyDialogComponent` it replaces, down to the two implicit rules that\n * callers rely on: an empty message keeps the previous text (so `wait()` does not wipe it), and\n * a progress above zero forces `'determinate'` whatever the caller passed.\n * @param message - New message to display. An empty string preserves the current one.\n * @param progress - Current progress value (0-100). Above zero it forces determinate mode.\n * @param progressMode - Progress mode to use. Defaults to `'indeterminate'`.\n * @param type - Visual style to use. Defaults to `'bar'`.\n * @returns void\n */\n set(\n message: string,\n progress: number,\n progressMode: ShellBusyMode = 'indeterminate',\n type: ShellBusyType = 'bar'\n ): void {\n if (message) this.message.set(message);\n if (type) this.type.set(type);\n this.progress.set(progress);\n this.progressMode.set(progress > 0 ? 'determinate' : progressMode);\n }\n}\n","<div class=\"scrim\"></div>\n\n@if (type() === 'hourglass' || type() === 'wait') {\n<div class=\"bare\">\n <svg class=\"hourglass\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M6 2h12v6l-4 4 4 4v6H6v-6l4-4-4-4zm2 2v3.2l4 4 4-4V4zm0 16h8v-3.2l-4-4-4 4z\" />\n </svg>\n @if (type() === 'hourglass' && message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n</div>\n} @else {\n<div class=\"panel\" role=\"status\" aria-live=\"polite\">\n @if (message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n\n @if (type() === 'bar') {\n <div class=\"bar\" [class.indeterminate]=\"progressMode() === 'indeterminate'\">\n <div class=\"bar-fill\" [style.width.%]=\"progressMode() === 'determinate' ? progress() : null\"></div>\n </div>\n } @else if (type() === 'spinner') {\n <svg class=\"spinner\" [class.indeterminate]=\"progressMode() === 'indeterminate'\" viewBox=\"0 0 70 70\"\n aria-hidden=\"true\">\n <circle class=\"track\" cx=\"35\" cy=\"35\" r=\"31.5\"></circle>\n <circle class=\"arc\" cx=\"35\" cy=\"35\" r=\"31.5\" [style.stroke-dasharray]=\"circumference\"\n [style.stroke-dashoffset]=\"progressMode() === 'determinate' ? dashOffset() : null\"></circle>\n </svg>\n }\n\n @if (progress() > 0) {\n <div class=\"percent\"><b>{{ progress() }}%</b></div>\n }\n</div>\n}\n","import {\n ChangeDetectionStrategy, Component, DestroyRef, ElementRef,\n HostListener, afterNextRender, inject, output, signal, viewChild\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { SafeHtmlPipe, ThemeService, ThemeType } from '@arsedizioni/ars-utils/core';\nimport { ShellMessageData } from '../definitions';\n\n/**\n * The shell's message panel: a modal that looks like a Material dialog and owes nothing to\n * Material.\n *\n * It exists because shell, interceptors, guards and app initializers must be able to say\n * \"the session is gone\" before a single route has been loaded, and paying for `mat-dialog`,\n * `cdk/overlay` and the rest of that stack on the boot path costs the initial bundle more\n * than every route of the application put together. The look is matched through CSS custom\n * properties (`--ars-*` first, Material's `--mat-sys-*` next, a literal last), so an\n * application that themes Material gets the same surface here for free.\n *\n * Instantiated imperatively by {@link ShellService}, never declared in a template: that is\n * what lets an interceptor open it.\n */\n@Component({\n selector: 'ars-shell-message',\n templateUrl: './shell-message.component.html',\n styleUrl: './shell-message.component.scss',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SafeHtmlPipe],\n host: { '[class.ars-dark]': 'dark()' }\n})\nexport class ShellMessageComponent {\n\n /** Emitted when the user dismisses the message, whichever way they did it. */\n readonly closed = output<void>();\n\n private readonly themeService = inject(ThemeService);\n\n private readonly panel = viewChild.required<ElementRef<HTMLElement>>('panel');\n private readonly okButton = viewChild.required<ElementRef<HTMLButtonElement>>('ok');\n\n /** Unique id tying the panel to its heading for assistive technology. */\n protected readonly titleId = `ars-shell-message-title-${Math.random().toString(36).slice(2, 10)}`;\n\n /** Current content, with the defaults the shell relies on already applied. */\n protected readonly data = signal<ShellMessageData>({ message: '', title: 'Informazioni', okCaption: 'Ok', width: 500 });\n\n /** True for a moment after a successful copy, so the button can acknowledge it. */\n protected readonly copied = signal(false);\n\n private dismissTimer?: ReturnType<typeof setTimeout>;\n private copiedTimer?: ReturnType<typeof setTimeout>;\n private closing = false;\n\n /**\n * True when the panel must paint itself dark.\n *\n * Read from {@link ThemeService} and not from `prefers-color-scheme`, because the two do not\n * always agree: the service is what the user chose, and it may be forcing dark on a machine\n * that is on light. Following the OS instead would leave this panel the only light thing on a\n * dark screen.\n */\n protected readonly dark = signal(false);\n\n /**\n * Keeps {@link dark} in step with the service, now and at every later change.\n *\n * `'auto'` is resolved through `getTheme()`, which is the only thing that knows what the\n * operating system is currently on.\n * @returns void\n */\n private followTheme(): void {\n const resolve = (theme: ThemeType): boolean =>\n (theme === 'auto' ? this.themeService.getTheme() : theme) === 'dark';\n this.dark.set(resolve(this.themeService.getTheme()));\n this.themeService.changed\n .pipe(takeUntilDestroyed())\n .subscribe(theme => this.dark.set(resolve(theme)));\n }\n\n constructor() {\n this.followTheme();\n afterNextRender(() => this.okButton().nativeElement.focus());\n inject(DestroyRef).onDestroy(() => {\n clearTimeout(this.dismissTimer);\n clearTimeout(this.copiedTimer);\n });\n }\n\n /**\n * Replaces the content shown by the panel and restarts the auto-dismiss timer.\n *\n * Called on an already open panel by `ShellService.error()` so that a burst of failures\n * updates one message instead of stacking modals nobody can dismiss.\n * @param data - The new content to display.\n * @returns void\n */\n setData(data: ShellMessageData): void {\n this.data.set({ title: 'Informazioni', okCaption: 'Ok', width: 500, ...data });\n this.scheduleDismiss(this.data().dismissAfter);\n }\n\n /**\n * Dismisses the panel. Safe to call more than once: only the first call is announced.\n * @returns void\n */\n close(): void {\n if (this.closing) return;\n this.closing = true;\n clearTimeout(this.dismissTimer);\n this.closed.emit();\n }\n\n /**\n * Closes the panel on Escape, mirroring a Material dialog opened with the default config.\n * @param e - The keyboard event captured at document level.\n * @returns void\n */\n @HostListener('document:keydown', ['$event'])\n protected onKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n e.preventDefault();\n this.close();\n return;\n }\n if (e.key === 'Tab') this.trapFocus(e);\n }\n\n /**\n * Keeps Tab inside the panel while the message is up.\n *\n * A hand-rolled two-element version of what `cdk/a11y` does, which is all this panel needs:\n * it never holds more than the copy button and the dismiss button.\n * @param e - The Tab keydown event.\n * @returns void\n */\n private trapFocus(e: KeyboardEvent): void {\n const focusable = Array.from(\n this.panel().nativeElement.querySelectorAll<HTMLElement>('button:not([disabled]), [href], [tabindex]:not([tabindex=\"-1\"])')\n );\n if (!focusable.length) return;\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const active = document.activeElement;\n\n if (e.shiftKey && (active === first || !this.panel().nativeElement.contains(active))) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && active === last) {\n e.preventDefault();\n first.focus();\n }\n }\n\n /**\n * (Re)schedules the auto-dismiss timer, cancelling any pending one so a timer armed for an\n * earlier message can never close a newer one.\n * @param dismissAfter - Delay in milliseconds; no-op when falsy.\n * @returns void\n */\n private scheduleDismiss(dismissAfter?: number): void {\n clearTimeout(this.dismissTimer);\n this.dismissTimer = undefined;\n if (dismissAfter) this.dismissTimer = setTimeout(() => this.close(), dismissAfter);\n }\n\n /**\n * Copies the message and its details to the clipboard, as both HTML and plain text.\n *\n * Unlike `InfoDialogComponent` there is no toast to report the outcome — the shell has no\n * toast — so the button itself acknowledges it for a moment.\n * @returns A promise that resolves once the copy has been attempted.\n */\n protected async copy(): Promise<void> {\n const content = this.panel().nativeElement.querySelector<HTMLElement>('.content');\n if (!content) return;\n try {\n await navigator.clipboard.write([\n new ClipboardItem({\n 'text/html': new Blob([content.innerHTML], { type: 'text/html' }),\n 'text/plain': new Blob([content.innerText], { type: 'text/plain' })\n })\n ]);\n this.copied.set(true);\n clearTimeout(this.copiedTimer);\n this.copiedTimer = setTimeout(() => this.copied.set(false), 1500);\n } catch {\n // Clipboard permission denied or the document is not focused: nothing worth interrupting\n // the user for, and the text is on screen anyway.\n }\n }\n}\n","<div class=\"scrim\" (click)=\"close()\"></div>\n\n<div #panel class=\"panel\" role=\"alertdialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"titleId\"\n [style.max-width.px]=\"data().width\">\n\n <h2 class=\"title\" [id]=\"titleId\" [innerHTML]=\"data().title | safeHtml\"></h2>\n\n <div class=\"content\">\n @if (data().message) {\n <div class=\"message\" [innerHTML]=\"data().message | safeHtml\"></div>\n }\n @if (data().details) {\n <div class=\"details-box\">\n <div class=\"details-separator\"></div>\n <p class=\"details-label\">Dettaglio:</p>\n <div class=\"details\">\n <div [innerHTML]=\"data().details | safeHtml\"></div>\n </div>\n </div>\n }\n </div>\n\n <div class=\"actions\">\n <button type=\"button\" class=\"icon-button\" (click)=\"copy()\"\n [title]=\"copied() ? 'Copiato negli appunti' : 'Copia negli appunti'\" aria-label=\"Copia negli appunti\">\n @if (copied()) {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\" /></svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path\n d=\"M16 1H4a2 2 0 0 0-2 2v14h2V3h12zm3 4H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2m0 16H8V7h11z\" /></svg>\n }\n </button>\n <button #ok type=\"button\" class=\"flat-button\" (click)=\"close()\">{{ data().okCaption }}</button>\n </div>\n</div>\n","import { ApplicationRef, ComponentRef, EnvironmentInjector, Service, createComponent, inject } from '@angular/core';\nimport { SystemUtils } from '@arsedizioni/ars-utils/core';\nimport { Observable, Subject, Subscription } from 'rxjs';\nimport { first } from 'rxjs/operators';\nimport { BusyTimer } from './busy-timer';\nimport { ShellMessageData, ShellMessageRef } from './definitions';\nimport { ShellBusyComponent, ShellBusyMode, ShellBusyType } from './shell-busy/shell-busy.component';\nimport { ShellMessageComponent } from './shell-message/shell-message.component';\n\n/** Grace period before the busy overlay is actually taken away, in milliseconds. */\nconst CLEAR_BUSY_GRACE = 500;\n\n/**\n * Everything the application can say to the user without asking anything back: a message, an\n * error, and the wait overlay. No Angular Material behind any of it.\n *\n * `DialogService` extends this class, so a route component injects `DialogService` and has both\n * halves; shell, HTTP interceptors, route guards and app initializers inject `ShellService` and\n * pay for neither `mat-dialog` nor `cdk/overlay` on the boot path — measured at 445 KB of the\n * 905 KB initial bundle on myARS, more than every route of the application put together.\n *\n * The methods keep the parameter order of the `DialogService` ones they came from, so no call\n * site changed when they moved here.\n *\n * ## Stacking\n *\n * Since Angular CDK 22 every overlay is opened as `popover=\"manual\"`, so a Material dialog is not\n * at z-index 1000 any more: it is in the browser top layer, which is painted above the whole\n * document whatever the z-index of the document says. A number, however large, cannot get above\n * it — so these overlays are promoted to the top layer as well, and the order there is the order\n * of promotion: whatever went up last is on top.\n *\n * That gives the right answer by itself in the case that matters, an error raised while a dialog\n * is open. The other three are arranged explicitly: `setBusy()` puts the message back on top\n * after raising the busy overlay, `DialogService.open()` calls {@link raiseMessage} after opening\n * a dialog, and it also takes the busy away immediately rather than with the grace period, so a\n * dialog is never drawn under an overlay that is on its way out.\n *\n * The `--ars-shell-z-index` / `--ars-busy-z-index` pair (1100 / 1090, above the CDK's 1000) is\n * still there and still correct: it is what orders the overlays on a browser without the Popover\n * API, where the CDK does not use it either.\n */\n@Service()\nexport class ShellService {\n\n private readonly appRef = inject(ApplicationRef);\n private readonly environmentInjector = inject(EnvironmentInjector);\n\n private messageRef?: ComponentRef<ShellMessageComponent>;\n private messageKind?: 'info' | 'error';\n private messageClosed?: Subject<void>;\n private previousOverflow?: string;\n private previouslyFocused?: HTMLElement;\n\n private busyRef?: ComponentRef<ShellBusyComponent>;\n private busyVisible = false;\n private busyActionSubscription?: Subscription;\n private clearBusyTimer?: ReturnType<typeof setTimeout>;\n\n /** Cached answer of {@link supportsTopLayer}, resolved the first time an overlay is shown. */\n private topLayerSupport?: boolean;\n\n // ---------------------------------------------------------------------------\n // Messages\n // ---------------------------------------------------------------------------\n\n /**\n * Shows an informational message.\n * @param message - HTML message to display.\n * @param title - Heading. Defaults to `'Informazioni'`.\n * @param okCaption - Dismiss button label. Defaults to `'Ok'`.\n * @param width - Maximum panel width in pixels. Defaults to `500`.\n * @param dismissAfter - Auto-close delay in milliseconds (optional).\n * @param details - Optional secondary details text.\n * @returns A handle over the open message, or `null` outside the browser.\n */\n info(\n message: string,\n title: string = 'Informazioni',\n okCaption: string = 'Ok',\n width: number = 500,\n dismissAfter?: number,\n details?: string\n ): ShellMessageRef | null {\n this.clearBusy();\n return this.showMessage('info', { message, title, okCaption, width, dismissAfter, details });\n }\n\n /**\n * Shows an error message. When one is already on screen its content is replaced in place: a\n * failing API answers many requests at once, and each of them must not add a panel of its own.\n * @param message - HTML error message to display.\n * @param log - Optional technical log or stack trace shown in the details panel.\n * @param title - Heading. Defaults to `'Errore'`.\n * @param okCaption - Dismiss button label. Defaults to `'Ok'`.\n * @param width - Maximum panel width in pixels. Defaults to `500`.\n * @param dismissAfter - Auto-close delay in milliseconds (optional).\n * @returns A handle over the open message, or `null` outside the browser.\n */\n error(\n message: string,\n log?: string,\n title: string = 'Errore',\n okCaption: string = 'Ok',\n width: number = 500,\n dismissAfter?: number\n ): ShellMessageRef | null {\n this.clearBusy();\n return this.showMessage('error', { message, title, okCaption, width, dismissAfter, details: log });\n }\n\n /**\n * Closes the message currently on screen, if any. Does not touch the busy overlay.\n * @returns void\n */\n closeMessage(): void {\n if (!this.messageRef) return;\n\n const ref = this.messageRef;\n this.messageRef = undefined;\n this.messageKind = undefined;\n\n this.leaveTopLayer(ref.location.nativeElement as HTMLElement);\n this.appRef.detachView(ref.hostView);\n ref.destroy();\n\n if (this.previousOverflow !== undefined) {\n document.body.style.overflow = this.previousOverflow;\n this.previousOverflow = undefined;\n }\n this.previouslyFocused?.focus();\n this.previouslyFocused = undefined;\n\n // Last, so that whoever is waiting on it finds the screen already in its final state.\n const closed = this.messageClosed;\n this.messageClosed = undefined;\n closed?.next();\n closed?.complete();\n }\n\n /**\n * Opens the message panel, or updates the one already open when it is showing the same kind of\n * message.\n * @param kind - Whether this is an informational or an error message.\n * @param data - The content to display.\n * @returns A handle over the open message, or `null` outside the browser.\n */\n private showMessage(kind: 'info' | 'error', data: ShellMessageData): ShellMessageRef | null {\n if (!SystemUtils.isBrowser()) return null;\n\n if (this.messageRef && this.messageKind === kind) {\n this.messageRef.instance.setData(data);\n this.messageRef.changeDetectorRef.detectChanges();\n // Back to the front: a dialog may have been opened since this panel went up, and the top\n // layer orders by promotion, not by z-index.\n this.raiseTopLayer(this.messageRef.location.nativeElement as HTMLElement);\n return this.messageHandle();\n }\n\n // A message of a different kind replaces the one on screen rather than stacking on it.\n this.closeMessage();\n\n const ref = createComponent(ShellMessageComponent, { environmentInjector: this.environmentInjector });\n ref.instance.setData(data);\n ref.instance.closed.subscribe(() => this.closeMessage());\n\n // One subject per panel, not per handle: an `error()` that replaces the text of the message\n // already on screen hands out a second handle, and both must fire when that message goes.\n this.messageClosed = new Subject<void>();\n\n this.previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : undefined;\n this.previousOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n\n this.appRef.attachView(ref.hostView);\n document.body.appendChild(ref.location.nativeElement as HTMLElement);\n this.enterTopLayer(ref.location.nativeElement as HTMLElement);\n\n this.messageRef = ref;\n this.messageKind = kind;\n return this.messageHandle();\n }\n\n /**\n * Builds the handle returned to callers.\n *\n * The subject is captured now rather than read at call time, so `afterClosed()` keeps\n * answering about the message this handle was given for, even once another one has taken\n * its place on screen.\n * @returns The handle over the message currently on screen.\n */\n private messageHandle(): ShellMessageRef {\n const closed = this.messageClosed!;\n return {\n close: () => this.closeMessage(),\n afterClosed: () => closed.asObservable()\n };\n }\n\n // ---------------------------------------------------------------------------\n // Busy overlay\n // ---------------------------------------------------------------------------\n\n /**\n * Shows or updates the busy overlay.\n *\n * Called dozens of times per screen, so it creates nothing after the first time: the component\n * is built once and then kept, and showing it again is a class on the host element. The state\n * is written to signals and checked synchronously before returning, so the message on screen is\n * always the last one asked for — a second `busy()` in the same task never leaves the previous\n * text behind.\n * @param message - Text to display. An empty string keeps the current one.\n * @param progress - Progress value (`-1` = indeterminate). Defaults to `-1`.\n * @param progressMode - Progress mode. Defaults to `'indeterminate'`.\n * @param type - Visual style of the overlay. Defaults to `'bar'`.\n * @param action - Optional observable; the overlay is dismissed when it first emits. It\n * replaces the one passed to a previous call, which is unsubscribed.\n * @returns `true` if the overlay was brought up by this call, `false` if it was already up.\n */\n setBusy(\n message: string,\n progress: number = -1,\n progressMode: ShellBusyMode = 'indeterminate',\n type: ShellBusyType = 'bar',\n action?: Observable<unknown>\n ): boolean {\n if (!SystemUtils.isBrowser()) return false;\n\n // Cancel any pending clearBusy(): it must never take away an overlay just asked for.\n clearTimeout(this.clearBusyTimer);\n this.clearBusyTimer = undefined;\n\n const created = !this.busyVisible;\n const ref = this.ensureBusy();\n ref.instance.set(message, progress, progressMode, type);\n ref.instance.visible.set(true);\n this.busyVisible = true;\n ref.changeDetectorRef.detectChanges();\n this.enterTopLayer(ref.location.nativeElement as HTMLElement);\n\n // The overlay has just been promoted, so it is the topmost element of the top layer: put the\n // message back above it, which is what the 1100/1090 pair used to do on its own.\n this.raiseMessage();\n\n // The action always replaces the previous one. Keeping the first, as the previous\n // implementation did, meant the overlay outlived the operation that was actually running.\n this.busyActionSubscription?.unsubscribe();\n this.busyActionSubscription = action?.pipe(first()).subscribe(() => this.clearBusy());\n\n return created;\n }\n\n /**\n * Shows or updates the busy overlay using the progress-bar style.\n * @param message - Text to display inside the overlay.\n * @param progress - Progress value (`-1` = indeterminate). Defaults to `-1`.\n * @param progressMode - Progress mode. Defaults to `'indeterminate'`.\n * @param action - Optional observable; the overlay is dismissed when it emits.\n * @returns `true` if the overlay was brought up by this call.\n */\n busy(\n message: string,\n progress: number = -1,\n progressMode: ShellBusyMode = 'indeterminate',\n action?: Observable<unknown>\n ): boolean {\n return this.setBusy(message, progress, progressMode, 'bar', action);\n }\n\n /**\n * Shows or updates the busy overlay using the spinner style.\n * @param message - Text to display inside the overlay.\n * @param progress - Progress value (`-1` = indeterminate). Defaults to `-1`.\n * @param progressMode - Progress mode. Defaults to `'indeterminate'`.\n * @param action - Optional observable; the overlay is dismissed when it emits.\n * @returns `true` if the overlay was brought up by this call.\n */\n busySpinner(\n message: string,\n progress: number = -1,\n progressMode: ShellBusyMode = 'indeterminate',\n action?: Observable<unknown>\n ): boolean {\n return this.setBusy(message, progress, progressMode, 'spinner', action);\n }\n\n /**\n * Shows or updates the busy overlay using the hourglass style.\n * @param message - Text to display inside the overlay.\n * @param action - Optional observable; the overlay is dismissed when it emits.\n * @returns `true` if the overlay was brought up by this call.\n */\n busyHourglass(message: string, action?: Observable<unknown>): boolean {\n return this.setBusy(message, -1, 'indeterminate', 'hourglass', action);\n }\n\n /**\n * Shows a bare wait indicator, with no panel and no message.\n * @param action - Optional observable; the overlay is dismissed when it emits.\n * @returns `true` if the overlay was brought up by this call.\n */\n wait(action?: Observable<unknown>): boolean {\n return this.setBusy('', -1, 'indeterminate', 'wait', action);\n }\n\n /**\n * Returns a {@link BusyTimer} that brings the overlay up only if the operation is still running\n * after a debounce delay.\n * @param message - Text to display. Defaults to `'Operazione in corso...'`.\n * @param due - Delay in milliseconds before the overlay appears. Defaults to `100`.\n * @returns A timer that must be disposed with `clear()` when the operation ends.\n */\n busyTimer(message: string = 'Operazione in corso...', due: number = 100): BusyTimer {\n return new BusyTimer(this, due, message);\n }\n\n /**\n * Takes the busy overlay away.\n *\n * By default it waits a short grace period, so that a chain of quick operations does not make\n * the overlay blink between one and the next; any `setBusy()` in the meantime cancels the\n * pending removal. Pass `true` when something is about to be drawn underneath it and the wait\n * would be visible — that is what `DialogService.open()` does.\n * @param immediate - When `true`, removes the overlay without waiting for the grace period.\n * @returns void\n */\n clearBusy(immediate: boolean = false): void {\n clearTimeout(this.clearBusyTimer);\n this.clearBusyTimer = undefined;\n\n if (immediate) {\n this.hideBusy();\n return;\n }\n this.clearBusyTimer = setTimeout(() => {\n this.clearBusyTimer = undefined;\n this.hideBusy();\n }, CLEAR_BUSY_GRACE);\n }\n\n /**\n * Hides the busy overlay without destroying it, so the next call can reuse the instance.\n * @returns void\n */\n private hideBusy(): void {\n this.busyActionSubscription?.unsubscribe();\n this.busyActionSubscription = undefined;\n if (!this.busyVisible) return;\n this.busyVisible = false;\n this.busyRef?.instance.visible.set(false);\n this.busyRef?.changeDetectorRef.detectChanges();\n this.leaveTopLayer(this.busyRef?.location.nativeElement as HTMLElement | undefined);\n }\n\n /**\n * Returns the busy component, creating and attaching it the first time it is needed.\n * @returns The reused busy component reference.\n */\n private ensureBusy(): ComponentRef<ShellBusyComponent> {\n if (this.busyRef) return this.busyRef;\n\n const ref = createComponent(ShellBusyComponent, { environmentInjector: this.environmentInjector });\n this.appRef.attachView(ref.hostView);\n document.body.appendChild(ref.location.nativeElement as HTMLElement);\n this.busyRef = ref;\n return ref;\n }\n\n // ---------------------------------------------------------------------------\n // Top layer\n // ---------------------------------------------------------------------------\n\n /**\n * Brings the message currently on screen back to the front of the top layer, if there is one.\n *\n * Called by `DialogService` after opening a dialog: an error the user has not dismissed yet\n * must stay above whatever is opened underneath it.\n * @returns void\n */\n raiseMessage(): void {\n this.raiseTopLayer(this.messageRef?.location.nativeElement as HTMLElement | undefined);\n }\n\n /**\n * Whether the browser can promote an element to the top layer through the Popover API.\n *\n * Angular CDK 22 opens every overlay as `popover=\"manual\"`, so a Material dialog does not sit\n * at z-index 1000 any more: it sits in the top layer, which is painted above the whole page\n * whatever the z-index of the page says. The only way to put something above it is to be in\n * the top layer too. Where the API is missing the overlays fall back to their z-index, which\n * is also the CDK's own fallback and therefore still the right order.\n * @returns `true` when `showPopover()` is available.\n */\n private supportsTopLayer(): boolean {\n if (this.topLayerSupport === undefined) {\n this.topLayerSupport = SystemUtils.isBrowser()\n && typeof HTMLElement !== 'undefined'\n && 'showPopover' in HTMLElement.prototype;\n }\n return this.topLayerSupport;\n }\n\n /**\n * Promotes an overlay to the top layer, marking it as a manual popover the first time.\n *\n * `manual` and not `auto`: an `auto` popover is light-dismissed by a click anywhere and closed\n * by Escape without telling anyone, which would take the panel off the screen behind the back\n * of the component that owns it.\n * @param el - The host element of the overlay. Ignored when undefined.\n * @returns void\n */\n private enterTopLayer(el?: HTMLElement): void {\n if (!el || !this.supportsTopLayer()) return;\n if (el.getAttribute('popover') !== 'manual') el.setAttribute('popover', 'manual');\n // Throws if the element is already showing, or is not connected yet.\n try { if (!el.matches(':popover-open')) el.showPopover(); } catch { /* already up */ }\n }\n\n /**\n * Takes an overlay out of the top layer.\n * @param el - The host element of the overlay. Ignored when undefined.\n * @returns void\n */\n private leaveTopLayer(el?: HTMLElement): void {\n if (!el || !this.supportsTopLayer()) return;\n try { if (el.matches(':popover-open')) el.hidePopover(); } catch { /* already down */ }\n }\n\n /**\n * Moves an overlay back to the front of the top layer.\n *\n * The top layer is a stack ordered by promotion, so the only way to raise an element already\n * in it is to take it out and put it back.\n * @param el - The host element of the overlay. Ignored when undefined.\n * @returns void\n */\n private raiseTopLayer(el?: HTMLElement): void {\n if (!el || !this.supportsTopLayer()) return;\n if (!el.matches(':popover-open')) {\n this.enterTopLayer(el);\n return;\n }\n try {\n el.hidePopover();\n el.showPopover();\n } catch { /* the element is on its way out */ }\n }\n}\n","/*\n * Public API Surface of @arsedizioni/ars-utils/ui.shell\n */\nexport * from './definitions';\nexport * from './busy-timer';\nexport * from './shell.service';\nexport * from './shell-message/shell-message.component';\nexport * from './shell-busy/shell-busy.component';\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-ui.shell.mjs","sources":["../../../projects/ars-utils/ui.shell/busy-timer.ts","../../../projects/ars-utils/ui.shell/shell-busy/shell-busy.component.ts","../../../projects/ars-utils/ui.shell/shell-busy/shell-busy.component.html","../../../projects/ars-utils/ui.shell/shell-message/shell-message.component.ts","../../../projects/ars-utils/ui.shell/shell-message/shell-message.component.html","../../../projects/ars-utils/ui.shell/shell.service.ts","../../../projects/ars-utils/ui.shell/public_api.ts","../../../projects/ars-utils/ui.shell/arsedizioni-ars-utils-ui.shell.ts"],"sourcesContent":["import { Subscription, timer } from 'rxjs';\nimport { tap } from 'rxjs/operators';\nimport type { ShellService } from './shell.service';\n\n/**\n * Shows the busy overlay only if the operation is still running after a debounce delay, so that\n * an operation that answers in 30 ms never makes the screen flash.\n *\n * Whoever creates one owns it: {@link clear} must be called when the operation ends, otherwise\n * the overlay appears after the fact and stays.\n */\nexport class BusyTimer {\n private readonly subscription: Subscription;\n\n /**\n * Arms the timer.\n * @param shellService - The service that owns the overlay. A `DialogService` is accepted too,\n * since it extends `ShellService`.\n * @param due - Delay in milliseconds before the overlay appears. Defaults to `100`.\n * @param message - Text to display. Defaults to `'Operazione in corso...'`.\n */\n constructor(\n private readonly shellService: ShellService,\n due: number = 100,\n message: string = 'Operazione in corso...'\n ) {\n this.subscription = timer(due).pipe(tap(() => this.shellService.busy(message))).subscribe();\n }\n\n /**\n * Disarms the timer and takes the overlay away.\n * @returns void\n */\n clear(): void {\n this.subscription.unsubscribe();\n this.shellService.clearBusy();\n }\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { SafeHtmlPipe, ThemeService, ThemeType } from '@arsedizioni/ars-utils/core';\n\n/** Visual style of the busy indicator. */\nexport type ShellBusyType = 'bar' | 'spinner' | 'wait' | 'hourglass';\n\n/** Progress mode of the bar and of the spinner. */\nexport type ShellBusyMode = 'determinate' | 'indeterminate';\n\n/** Circumference of the spinner circle, in user units. Kept here so the template stays arithmetic-free. */\nconst SPINNER_CIRCUMFERENCE = 2 * Math.PI * 31.5;\n\n/**\n * Overlay that blocks interaction while an operation is running, in the four styles the\n * applications use: progress bar, spinner, hourglass and bare wait.\n *\n * Reproduces `mat-progress-bar` and `mat-progress-spinner` in CSS and SVG rather than importing\n * them, because this overlay is shown from the boot path — an HTTP interceptor calls it before\n * any route exists — and `ui.shell` exists precisely so that path costs no Material.\n *\n * The instance is created once by {@link ShellService} and then reused: showing and hiding is a\n * class on the host, never a `createComponent`, so the 40-odd calls a screen costs nothing.\n */\n@Component({\n selector: 'ars-shell-busy',\n templateUrl: './shell-busy.component.html',\n styleUrl: './shell-busy.component.scss',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SafeHtmlPipe],\n host: { '[class.ars-hidden]': '!visible()', '[class.ars-dark]': 'dark()' }\n})\nexport class ShellBusyComponent {\n\n private readonly themeService = inject(ThemeService);\n\n /**\n * True when the panel must paint itself dark.\n *\n * Read from {@link ThemeService} and not from `prefers-color-scheme`, because the two do not\n * always agree: the service is what the user chose, and it may be forcing dark on a machine\n * that is on light. Following the OS instead would leave this panel the only light thing on a\n * dark screen.\n */\n protected readonly dark = signal(false);\n\n /**\n * Keeps {@link dark} in step with the service, now and at every later change.\n *\n * `'auto'` is resolved through `getTheme()`, which is the only thing that knows what the\n * operating system is currently on.\n * @returns void\n */\n private followTheme(): void {\n const resolve = (theme: ThemeType): boolean =>\n (theme === 'auto' ? this.themeService.getTheme() : theme) === 'dark';\n this.dark.set(resolve(this.themeService.getTheme()));\n this.themeService.changed\n .pipe(takeUntilDestroyed())\n .subscribe(theme => this.dark.set(resolve(theme)));\n }\n\n /** Whether the overlay is on screen. Hidden with `display: none`, so it costs no layout. */\n readonly visible = signal(false);\n\n /** Visual style of the indicator. */\n readonly type = signal<ShellBusyType>('bar');\n\n /** Current progress value (0-100), used when {@link progressMode} is `'determinate'`. */\n readonly progress = signal(0);\n\n /** Progress mode of the bar and of the spinner. */\n readonly progressMode = signal<ShellBusyMode>('indeterminate');\n\n /** Message displayed above the indicator. */\n readonly message = signal('');\n\n /** Circumference of the spinner circle, bound to `stroke-dasharray`. */\n protected readonly circumference = SPINNER_CIRCUMFERENCE;\n\n constructor() {\n this.followTheme();\n }\n\n /** Length of the spinner arc still to be drawn, derived from {@link progress}. */\n protected readonly dashOffset = computed(\n () => SPINNER_CIRCUMFERENCE * (1 - Math.min(Math.max(this.progress(), 0), 100) / 100)\n );\n\n /**\n * Updates the overlay state.\n *\n * Same contract as the `BusyDialogComponent` it replaces, down to the two implicit rules that\n * callers rely on: an empty message keeps the previous text (so `wait()` does not wipe it), and\n * a progress above zero forces `'determinate'` whatever the caller passed.\n * @param message - New message to display. An empty string preserves the current one.\n * @param progress - Current progress value (0-100). Above zero it forces determinate mode.\n * @param progressMode - Progress mode to use. Defaults to `'indeterminate'`.\n * @param type - Visual style to use. Defaults to `'bar'`.\n * @returns void\n */\n set(\n message: string,\n progress: number,\n progressMode: ShellBusyMode = 'indeterminate',\n type: ShellBusyType = 'bar'\n ): void {\n if (message) this.message.set(message);\n if (type) this.type.set(type);\n this.progress.set(progress);\n this.progressMode.set(progress > 0 ? 'determinate' : progressMode);\n }\n}\n","<div class=\"scrim\"></div>\n\n@if (type() === 'hourglass' || type() === 'wait') {\n<div class=\"bare\">\n <svg class=\"hourglass\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M6 2h12v6l-4 4 4 4v6H6v-6l4-4-4-4zm2 2v3.2l4 4 4-4V4zm0 16h8v-3.2l-4-4-4 4z\" />\n </svg>\n @if (type() === 'hourglass' && message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n</div>\n} @else {\n<div class=\"panel\" role=\"status\" aria-live=\"polite\">\n @if (message()) {\n <div class=\"message\" [innerHTML]=\"message() | safeHtml\"></div>\n }\n\n @if (type() === 'bar') {\n <div class=\"bar\" [class.indeterminate]=\"progressMode() === 'indeterminate'\">\n <div class=\"bar-fill\" [style.width.%]=\"progressMode() === 'determinate' ? progress() : null\"></div>\n </div>\n } @else if (type() === 'spinner') {\n <svg class=\"spinner\" [class.indeterminate]=\"progressMode() === 'indeterminate'\" viewBox=\"0 0 70 70\"\n aria-hidden=\"true\">\n <circle class=\"track\" cx=\"35\" cy=\"35\" r=\"31.5\"></circle>\n <circle class=\"arc\" cx=\"35\" cy=\"35\" r=\"31.5\" [style.stroke-dasharray]=\"circumference\"\n [style.stroke-dashoffset]=\"progressMode() === 'determinate' ? dashOffset() : null\"></circle>\n </svg>\n }\n\n @if (progress() > 0) {\n <div class=\"percent\"><b>{{ progress() }}%</b></div>\n }\n</div>\n}\n","import {\n ChangeDetectionStrategy, Component, DestroyRef, ElementRef,\n HostListener, afterNextRender, inject, output, signal, viewChild\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { SafeHtmlPipe, ThemeService, ThemeType } from '@arsedizioni/ars-utils/core';\nimport { ShellMessageData } from '../definitions';\n\n/**\n * The shell's message panel: a modal that looks like a Material dialog and owes nothing to\n * Material.\n *\n * It exists because shell, interceptors, guards and app initializers must be able to say\n * \"the session is gone\" before a single route has been loaded, and paying for `mat-dialog`,\n * `cdk/overlay` and the rest of that stack on the boot path costs the initial bundle more\n * than every route of the application put together. The look is matched through CSS custom\n * properties (`--ars-*` first, Material's `--mat-sys-*` next, a literal last), so an\n * application that themes Material gets the same surface here for free.\n *\n * Instantiated imperatively by {@link ShellService}, never declared in a template: that is\n * what lets an interceptor open it.\n */\n@Component({\n selector: 'ars-shell-message',\n templateUrl: './shell-message.component.html',\n styleUrl: './shell-message.component.scss',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SafeHtmlPipe],\n host: { '[class.ars-dark]': 'dark()' }\n})\nexport class ShellMessageComponent {\n\n /** Emitted when the user dismisses the message, whichever way they did it. */\n readonly closed = output<void>();\n\n private readonly themeService = inject(ThemeService);\n\n private readonly panel = viewChild.required<ElementRef<HTMLElement>>('panel');\n private readonly okButton = viewChild.required<ElementRef<HTMLButtonElement>>('ok');\n\n /** Unique id tying the panel to its heading for assistive technology. */\n protected readonly titleId = `ars-shell-message-title-${Math.random().toString(36).slice(2, 10)}`;\n\n /** Unique id tying the details panel to the header that opens it. */\n protected readonly detailsId = `ars-shell-message-details-${Math.random().toString(36).slice(2, 10)}`;\n\n /**\n * Whether the technical details are open.\n *\n * Closed on arrival, and closed again by every {@link setData}: the message is what the user is\n * meant to read, and a stack trace unfolded under it is noise until they ask for it.\n */\n protected readonly detailsOpen = signal(false);\n\n /** Current content, with the defaults the shell relies on already applied. */\n protected readonly data = signal<ShellMessageData>({ message: '', title: 'Informazioni', okCaption: 'Ok', width: 500 });\n\n /** True for a moment after a successful copy, so the button can acknowledge it. */\n protected readonly copied = signal(false);\n\n private dismissTimer?: ReturnType<typeof setTimeout>;\n private copiedTimer?: ReturnType<typeof setTimeout>;\n private closing = false;\n\n /**\n * True when the panel must paint itself dark.\n *\n * Read from {@link ThemeService} and not from `prefers-color-scheme`, because the two do not\n * always agree: the service is what the user chose, and it may be forcing dark on a machine\n * that is on light. Following the OS instead would leave this panel the only light thing on a\n * dark screen.\n */\n protected readonly dark = signal(false);\n\n /**\n * Keeps {@link dark} in step with the service, now and at every later change.\n *\n * `'auto'` is resolved through `getTheme()`, which is the only thing that knows what the\n * operating system is currently on.\n * @returns void\n */\n private followTheme(): void {\n const resolve = (theme: ThemeType): boolean =>\n (theme === 'auto' ? this.themeService.getTheme() : theme) === 'dark';\n this.dark.set(resolve(this.themeService.getTheme()));\n this.themeService.changed\n .pipe(takeUntilDestroyed())\n .subscribe(theme => this.dark.set(resolve(theme)));\n }\n\n constructor() {\n this.followTheme();\n afterNextRender(() => this.okButton().nativeElement.focus());\n inject(DestroyRef).onDestroy(() => {\n clearTimeout(this.dismissTimer);\n clearTimeout(this.copiedTimer);\n });\n }\n\n /**\n * Replaces the content shown by the panel and restarts the auto-dismiss timer.\n *\n * Called on an already open panel by `ShellService.error()` so that a burst of failures\n * updates one message instead of stacking modals nobody can dismiss.\n * @param data - The new content to display.\n * @returns void\n */\n setData(data: ShellMessageData): void {\n this.data.set({ title: 'Informazioni', okCaption: 'Ok', width: 500, ...data });\n this.detailsOpen.set(false);\n this.scheduleDismiss(this.data().dismissAfter);\n }\n\n /**\n * Opens or closes the technical details panel.\n * @returns void\n */\n protected toggleDetails(): void {\n this.detailsOpen.update(open => !open);\n }\n\n /**\n * Dismisses the panel. Safe to call more than once: only the first call is announced.\n * @returns void\n */\n close(): void {\n if (this.closing) return;\n this.closing = true;\n clearTimeout(this.dismissTimer);\n this.closed.emit();\n }\n\n /**\n * Closes the panel on Escape, mirroring a Material dialog opened with the default config.\n * @param e - The keyboard event captured at document level.\n * @returns void\n */\n @HostListener('document:keydown', ['$event'])\n protected onKeydown(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n e.preventDefault();\n this.close();\n return;\n }\n if (e.key === 'Tab') this.trapFocus(e);\n }\n\n /**\n * Keeps Tab inside the panel while the message is up.\n *\n * A hand-rolled two-element version of what `cdk/a11y` does, which is all this panel needs:\n * it never holds more than the copy button and the dismiss button.\n * @param e - The Tab keydown event.\n * @returns void\n */\n private trapFocus(e: KeyboardEvent): void {\n const focusable = Array.from(\n this.panel().nativeElement.querySelectorAll<HTMLElement>('button:not([disabled]), [href], [tabindex]:not([tabindex=\"-1\"])')\n );\n if (!focusable.length) return;\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const active = document.activeElement;\n\n if (e.shiftKey && (active === first || !this.panel().nativeElement.contains(active))) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && active === last) {\n e.preventDefault();\n first.focus();\n }\n }\n\n /**\n * (Re)schedules the auto-dismiss timer, cancelling any pending one so a timer armed for an\n * earlier message can never close a newer one.\n * @param dismissAfter - Delay in milliseconds; no-op when falsy.\n * @returns void\n */\n private scheduleDismiss(dismissAfter?: number): void {\n clearTimeout(this.dismissTimer);\n this.dismissTimer = undefined;\n if (dismissAfter) this.dismissTimer = setTimeout(() => this.close(), dismissAfter);\n }\n\n /**\n * Copies the message and its details to the clipboard, as both HTML and plain text.\n *\n * Unlike `InfoDialogComponent` there is no toast to report the outcome — the shell has no\n * toast — so the button itself acknowledges it for a moment.\n * @returns A promise that resolves once the copy has been attempted.\n */\n protected async copy(): Promise<void> {\n const content = this.panel().nativeElement.querySelector<HTMLElement>('.content');\n if (!content) return;\n try {\n await navigator.clipboard.write([\n new ClipboardItem({\n 'text/html': new Blob([content.innerHTML], { type: 'text/html' }),\n 'text/plain': new Blob([content.innerText], { type: 'text/plain' })\n })\n ]);\n this.copied.set(true);\n clearTimeout(this.copiedTimer);\n this.copiedTimer = setTimeout(() => this.copied.set(false), 1500);\n } catch {\n // Clipboard permission denied or the document is not focused: nothing worth interrupting\n // the user for, and the text is on screen anyway.\n }\n }\n}\n","<div class=\"scrim\" (click)=\"close()\"></div>\n\n<div #panel class=\"panel\" role=\"alertdialog\" aria-modal=\"true\" [attr.aria-labelledby]=\"titleId\"\n [style.max-width.px]=\"data().width\">\n\n <h2 class=\"title\" [id]=\"titleId\" [innerHTML]=\"data().title | safeHtml\"></h2>\n\n <div class=\"content\">\n @if (data().message) {\n <div class=\"message\" [innerHTML]=\"data().message | safeHtml\"></div>\n }\n @if (data().details) {\n <div class=\"details-box\" [class.open]=\"detailsOpen()\">\n <button type=\"button\" class=\"details-header\" (click)=\"toggleDetails()\"\n [attr.aria-expanded]=\"detailsOpen()\" [attr.aria-controls]=\"detailsId\">\n <span class=\"details-label\">Dettaglio</span>\n <svg class=\"chevron\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M7.41 8.59 12 13.17l4.59-4.58L18 10l-6 6-6-6z\" />\n </svg>\n </button>\n <div class=\"details-body\">\n <div class=\"details\" [id]=\"detailsId\" [attr.aria-hidden]=\"!detailsOpen()\">\n <div class=\"details-text\" [innerHTML]=\"data().details | safeHtml\"></div>\n </div>\n </div>\n </div>\n }\n </div>\n\n <div class=\"actions\">\n <button type=\"button\" class=\"icon-button\" (click)=\"copy()\"\n [title]=\"copied() ? 'Copiato negli appunti' : 'Copia negli appunti'\" aria-label=\"Copia negli appunti\">\n @if (copied()) {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\" /></svg>\n } @else {\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path\n d=\"M16 1H4a2 2 0 0 0-2 2v14h2V3h12zm3 4H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2m0 16H8V7h11z\" /></svg>\n }\n </button>\n <button #ok type=\"button\" class=\"flat-button\" (click)=\"close()\">{{ data().okCaption }}</button>\n </div>\n</div>\n","import { ApplicationRef, ComponentRef, EnvironmentInjector, Service, createComponent, inject } from '@angular/core';\nimport { SystemUtils } from '@arsedizioni/ars-utils/core';\nimport { Observable, Subject, Subscription } from 'rxjs';\nimport { first } from 'rxjs/operators';\nimport { BusyTimer } from './busy-timer';\nimport { ShellMessageData, ShellMessageRef } from './definitions';\nimport { ShellBusyComponent, ShellBusyMode, ShellBusyType } from './shell-busy/shell-busy.component';\nimport { ShellMessageComponent } from './shell-message/shell-message.component';\n\n/** Grace period before the busy overlay is actually taken away, in milliseconds. */\nconst CLEAR_BUSY_GRACE = 500;\n\n/**\n * Everything the application can say to the user without asking anything back: a message, an\n * error, and the wait overlay. No Angular Material behind any of it.\n *\n * `DialogService` extends this class, so a route component injects `DialogService` and has both\n * halves; shell, HTTP interceptors, route guards and app initializers inject `ShellService` and\n * pay for neither `mat-dialog` nor `cdk/overlay` on the boot path — measured at 445 KB of the\n * 905 KB initial bundle on myARS, more than every route of the application put together.\n *\n * The methods keep the parameter order of the `DialogService` ones they came from, so no call\n * site changed when they moved here.\n *\n * ## Stacking\n *\n * Since Angular CDK 22 every overlay is opened as `popover=\"manual\"`, so a Material dialog is not\n * at z-index 1000 any more: it is in the browser top layer, which is painted above the whole\n * document whatever the z-index of the document says. A number, however large, cannot get above\n * it — so these overlays are promoted to the top layer as well, and the order there is the order\n * of promotion: whatever went up last is on top.\n *\n * That gives the right answer by itself in the case that matters, an error raised while a dialog\n * is open. The other three are arranged explicitly: `setBusy()` puts the message back on top\n * after raising the busy overlay, `DialogService.open()` calls {@link raiseMessage} after opening\n * a dialog, and it also takes the busy away immediately rather than with the grace period, so a\n * dialog is never drawn under an overlay that is on its way out.\n *\n * The `--ars-shell-dialog-z-index` / `--ars-shell-busy-z-index` pair (1100 / 1090, above the CDK's 1000) is\n * still there and still correct: it is what orders the overlays on a browser without the Popover\n * API, where the CDK does not use it either.\n */\n@Service()\nexport class ShellService {\n\n private readonly appRef = inject(ApplicationRef);\n private readonly environmentInjector = inject(EnvironmentInjector);\n\n private messageRef?: ComponentRef<ShellMessageComponent>;\n private messageKind?: 'info' | 'error';\n private messageClosed?: Subject<void>;\n private previousOverflow?: string;\n private previouslyFocused?: HTMLElement;\n\n private busyRef?: ComponentRef<ShellBusyComponent>;\n private busyVisible = false;\n private busyActionSubscription?: Subscription;\n private clearBusyTimer?: ReturnType<typeof setTimeout>;\n\n /** Cached answer of {@link supportsTopLayer}, resolved the first time an overlay is shown. */\n private topLayerSupport?: boolean;\n\n // ---------------------------------------------------------------------------\n // Messages\n // ---------------------------------------------------------------------------\n\n /**\n * Shows an informational message.\n * @param message - HTML message to display.\n * @param title - Heading. Defaults to `'Informazioni'`.\n * @param okCaption - Dismiss button label. Defaults to `'Ok'`.\n * @param width - Maximum panel width in pixels. Defaults to `500`.\n * @param dismissAfter - Auto-close delay in milliseconds (optional).\n * @param details - Optional secondary details text.\n * @returns A handle over the open message, or `null` outside the browser.\n */\n info(\n message: string,\n title: string = 'Informazioni',\n okCaption: string = 'Ok',\n width: number = 500,\n dismissAfter?: number,\n details?: string\n ): ShellMessageRef | null {\n this.clearBusy();\n return this.showMessage('info', { message, title, okCaption, width, dismissAfter, details });\n }\n\n /**\n * Shows an error message. When one is already on screen its content is replaced in place: a\n * failing API answers many requests at once, and each of them must not add a panel of its own.\n * @param message - HTML error message to display.\n * @param log - Optional technical log or stack trace shown in the details panel.\n * @param title - Heading. Defaults to `'Errore'`.\n * @param okCaption - Dismiss button label. Defaults to `'Ok'`.\n * @param width - Maximum panel width in pixels. Defaults to `500`.\n * @param dismissAfter - Auto-close delay in milliseconds (optional).\n * @returns A handle over the open message, or `null` outside the browser.\n */\n error(\n message: string,\n log?: string,\n title: string = 'Errore',\n okCaption: string = 'Ok',\n width: number = 500,\n dismissAfter?: number\n ): ShellMessageRef | null {\n this.clearBusy();\n return this.showMessage('error', { message, title, okCaption, width, dismissAfter, details: log });\n }\n\n /**\n * Closes the message currently on screen, if any. Does not touch the busy overlay.\n * @returns void\n */\n closeMessage(): void {\n if (!this.messageRef) return;\n\n const ref = this.messageRef;\n this.messageRef = undefined;\n this.messageKind = undefined;\n\n this.leaveTopLayer(ref.location.nativeElement as HTMLElement);\n this.appRef.detachView(ref.hostView);\n ref.destroy();\n\n if (this.previousOverflow !== undefined) {\n document.body.style.overflow = this.previousOverflow;\n this.previousOverflow = undefined;\n }\n this.previouslyFocused?.focus();\n this.previouslyFocused = undefined;\n\n // Last, so that whoever is waiting on it finds the screen already in its final state.\n const closed = this.messageClosed;\n this.messageClosed = undefined;\n closed?.next();\n closed?.complete();\n }\n\n /**\n * Opens the message panel, or updates the one already open when it is showing the same kind of\n * message.\n * @param kind - Whether this is an informational or an error message.\n * @param data - The content to display.\n * @returns A handle over the open message, or `null` outside the browser.\n */\n private showMessage(kind: 'info' | 'error', data: ShellMessageData): ShellMessageRef | null {\n if (!SystemUtils.isBrowser()) return null;\n\n if (this.messageRef && this.messageKind === kind) {\n this.messageRef.instance.setData(data);\n this.messageRef.changeDetectorRef.detectChanges();\n // Back to the front: a dialog may have been opened since this panel went up, and the top\n // layer orders by promotion, not by z-index.\n this.raiseTopLayer(this.messageRef.location.nativeElement as HTMLElement);\n return this.messageHandle();\n }\n\n // A message of a different kind replaces the one on screen rather than stacking on it.\n this.closeMessage();\n\n const ref = createComponent(ShellMessageComponent, { environmentInjector: this.environmentInjector });\n ref.instance.setData(data);\n ref.instance.closed.subscribe(() => this.closeMessage());\n\n // One subject per panel, not per handle: an `error()` that replaces the text of the message\n // already on screen hands out a second handle, and both must fire when that message goes.\n this.messageClosed = new Subject<void>();\n\n this.previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : undefined;\n this.previousOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n\n this.appRef.attachView(ref.hostView);\n document.body.appendChild(ref.location.nativeElement as HTMLElement);\n this.enterTopLayer(ref.location.nativeElement as HTMLElement);\n\n this.messageRef = ref;\n this.messageKind = kind;\n return this.messageHandle();\n }\n\n /**\n * Builds the handle returned to callers.\n *\n * The subject is captured now rather than read at call time, so `afterClosed()` keeps\n * answering about the message this handle was given for, even once another one has taken\n * its place on screen.\n * @returns The handle over the message currently on screen.\n */\n private messageHandle(): ShellMessageRef {\n const closed = this.messageClosed!;\n return {\n close: () => this.closeMessage(),\n afterClosed: () => closed.asObservable()\n };\n }\n\n // ---------------------------------------------------------------------------\n // Busy overlay\n // ---------------------------------------------------------------------------\n\n /**\n * Shows or updates the busy overlay.\n *\n * Called dozens of times per screen, so it creates nothing after the first time: the component\n * is built once and then kept, and showing it again is a class on the host element. The state\n * is written to signals and checked synchronously before returning, so the message on screen is\n * always the last one asked for — a second `busy()` in the same task never leaves the previous\n * text behind.\n * @param message - Text to display. An empty string keeps the current one.\n * @param progress - Progress value (`-1` = indeterminate). Defaults to `-1`.\n * @param progressMode - Progress mode. Defaults to `'indeterminate'`.\n * @param type - Visual style of the overlay. Defaults to `'bar'`.\n * @param action - Optional observable; the overlay is dismissed when it first emits. It\n * replaces the one passed to a previous call, which is unsubscribed.\n * @returns `true` if the overlay was brought up by this call, `false` if it was already up.\n */\n setBusy(\n message: string,\n progress: number = -1,\n progressMode: ShellBusyMode = 'indeterminate',\n type: ShellBusyType = 'bar',\n action?: Observable<unknown>\n ): boolean {\n if (!SystemUtils.isBrowser()) return false;\n\n // Cancel any pending clearBusy(): it must never take away an overlay just asked for.\n clearTimeout(this.clearBusyTimer);\n this.clearBusyTimer = undefined;\n\n const created = !this.busyVisible;\n const ref = this.ensureBusy();\n ref.instance.set(message, progress, progressMode, type);\n ref.instance.visible.set(true);\n this.busyVisible = true;\n ref.changeDetectorRef.detectChanges();\n this.enterTopLayer(ref.location.nativeElement as HTMLElement);\n\n // The overlay has just been promoted, so it is the topmost element of the top layer: put the\n // message back above it, which is what the 1100/1090 pair used to do on its own.\n this.raiseMessage();\n\n // The action always replaces the previous one. Keeping the first, as the previous\n // implementation did, meant the overlay outlived the operation that was actually running.\n this.busyActionSubscription?.unsubscribe();\n this.busyActionSubscription = action?.pipe(first()).subscribe(() => this.clearBusy());\n\n return created;\n }\n\n /**\n * Shows or updates the busy overlay using the progress-bar style.\n * @param message - Text to display inside the overlay.\n * @param progress - Progress value (`-1` = indeterminate). Defaults to `-1`.\n * @param progressMode - Progress mode. Defaults to `'indeterminate'`.\n * @param action - Optional observable; the overlay is dismissed when it emits.\n * @returns `true` if the overlay was brought up by this call.\n */\n busy(\n message: string,\n progress: number = -1,\n progressMode: ShellBusyMode = 'indeterminate',\n action?: Observable<unknown>\n ): boolean {\n return this.setBusy(message, progress, progressMode, 'bar', action);\n }\n\n /**\n * Shows or updates the busy overlay using the spinner style.\n * @param message - Text to display inside the overlay.\n * @param progress - Progress value (`-1` = indeterminate). Defaults to `-1`.\n * @param progressMode - Progress mode. Defaults to `'indeterminate'`.\n * @param action - Optional observable; the overlay is dismissed when it emits.\n * @returns `true` if the overlay was brought up by this call.\n */\n busySpinner(\n message: string,\n progress: number = -1,\n progressMode: ShellBusyMode = 'indeterminate',\n action?: Observable<unknown>\n ): boolean {\n return this.setBusy(message, progress, progressMode, 'spinner', action);\n }\n\n /**\n * Shows or updates the busy overlay using the hourglass style.\n * @param message - Text to display inside the overlay.\n * @param action - Optional observable; the overlay is dismissed when it emits.\n * @returns `true` if the overlay was brought up by this call.\n */\n busyHourglass(message: string, action?: Observable<unknown>): boolean {\n return this.setBusy(message, -1, 'indeterminate', 'hourglass', action);\n }\n\n /**\n * Shows a bare wait indicator, with no panel and no message.\n * @param action - Optional observable; the overlay is dismissed when it emits.\n * @returns `true` if the overlay was brought up by this call.\n */\n wait(action?: Observable<unknown>): boolean {\n return this.setBusy('', -1, 'indeterminate', 'wait', action);\n }\n\n /**\n * Returns a {@link BusyTimer} that brings the overlay up only if the operation is still running\n * after a debounce delay.\n * @param message - Text to display. Defaults to `'Operazione in corso...'`.\n * @param due - Delay in milliseconds before the overlay appears. Defaults to `100`.\n * @returns A timer that must be disposed with `clear()` when the operation ends.\n */\n busyTimer(message: string = 'Operazione in corso...', due: number = 100): BusyTimer {\n return new BusyTimer(this, due, message);\n }\n\n /**\n * Takes the busy overlay away.\n *\n * By default it waits a short grace period, so that a chain of quick operations does not make\n * the overlay blink between one and the next; any `setBusy()` in the meantime cancels the\n * pending removal. Pass `true` when something is about to be drawn underneath it and the wait\n * would be visible — that is what `DialogService.open()` does.\n * @param immediate - When `true`, removes the overlay without waiting for the grace period.\n * @returns void\n */\n clearBusy(immediate: boolean = false): void {\n clearTimeout(this.clearBusyTimer);\n this.clearBusyTimer = undefined;\n\n if (immediate) {\n this.hideBusy();\n return;\n }\n this.clearBusyTimer = setTimeout(() => {\n this.clearBusyTimer = undefined;\n this.hideBusy();\n }, CLEAR_BUSY_GRACE);\n }\n\n /**\n * Hides the busy overlay without destroying it, so the next call can reuse the instance.\n * @returns void\n */\n private hideBusy(): void {\n this.busyActionSubscription?.unsubscribe();\n this.busyActionSubscription = undefined;\n if (!this.busyVisible) return;\n this.busyVisible = false;\n this.busyRef?.instance.visible.set(false);\n this.busyRef?.changeDetectorRef.detectChanges();\n this.leaveTopLayer(this.busyRef?.location.nativeElement as HTMLElement | undefined);\n }\n\n /**\n * Returns the busy component, creating and attaching it the first time it is needed.\n * @returns The reused busy component reference.\n */\n private ensureBusy(): ComponentRef<ShellBusyComponent> {\n if (this.busyRef) return this.busyRef;\n\n const ref = createComponent(ShellBusyComponent, { environmentInjector: this.environmentInjector });\n this.appRef.attachView(ref.hostView);\n document.body.appendChild(ref.location.nativeElement as HTMLElement);\n this.busyRef = ref;\n return ref;\n }\n\n // ---------------------------------------------------------------------------\n // Top layer\n // ---------------------------------------------------------------------------\n\n /**\n * Brings the message currently on screen back to the front of the top layer, if there is one.\n *\n * Called by `DialogService` after opening a dialog: an error the user has not dismissed yet\n * must stay above whatever is opened underneath it.\n * @returns void\n */\n raiseMessage(): void {\n this.raiseTopLayer(this.messageRef?.location.nativeElement as HTMLElement | undefined);\n }\n\n /**\n * Whether the browser can promote an element to the top layer through the Popover API.\n *\n * Angular CDK 22 opens every overlay as `popover=\"manual\"`, so a Material dialog does not sit\n * at z-index 1000 any more: it sits in the top layer, which is painted above the whole page\n * whatever the z-index of the page says. The only way to put something above it is to be in\n * the top layer too. Where the API is missing the overlays fall back to their z-index, which\n * is also the CDK's own fallback and therefore still the right order.\n * @returns `true` when `showPopover()` is available.\n */\n private supportsTopLayer(): boolean {\n if (this.topLayerSupport === undefined) {\n this.topLayerSupport = SystemUtils.isBrowser()\n && typeof HTMLElement !== 'undefined'\n && 'showPopover' in HTMLElement.prototype;\n }\n return this.topLayerSupport;\n }\n\n /**\n * Promotes an overlay to the top layer, marking it as a manual popover the first time.\n *\n * `manual` and not `auto`: an `auto` popover is light-dismissed by a click anywhere and closed\n * by Escape without telling anyone, which would take the panel off the screen behind the back\n * of the component that owns it.\n * @param el - The host element of the overlay. Ignored when undefined.\n * @returns void\n */\n private enterTopLayer(el?: HTMLElement): void {\n if (!el || !this.supportsTopLayer()) return;\n if (el.getAttribute('popover') !== 'manual') el.setAttribute('popover', 'manual');\n // Throws if the element is already showing, or is not connected yet.\n try { if (!el.matches(':popover-open')) el.showPopover(); } catch { /* already up */ }\n }\n\n /**\n * Takes an overlay out of the top layer.\n * @param el - The host element of the overlay. Ignored when undefined.\n * @returns void\n */\n private leaveTopLayer(el?: HTMLElement): void {\n if (!el || !this.supportsTopLayer()) return;\n try { if (el.matches(':popover-open')) el.hidePopover(); } catch { /* already down */ }\n }\n\n /**\n * Moves an overlay back to the front of the top layer.\n *\n * The top layer is a stack ordered by promotion, so the only way to raise an element already\n * in it is to take it out and put it back.\n * @param el - The host element of the overlay. Ignored when undefined.\n * @returns void\n */\n private raiseTopLayer(el?: HTMLElement): void {\n if (!el || !this.supportsTopLayer()) return;\n if (!el.matches(':popover-open')) {\n this.enterTopLayer(el);\n return;\n }\n try {\n el.hidePopover();\n el.showPopover();\n } catch { /* the element is on its way out */ }\n }\n}\n","/*\n * Public API Surface of @arsedizioni/ars-utils/ui.shell\n */\nexport * from './definitions';\nexport * from './busy-timer';\nexport * from './shell.service';\nexport * from './shell-message/shell-message.component';\nexport * from './shell-busy/shell-busy.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/styles/ui.colors.scss
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
--ars-color-primary: #00a293;
|
|
22
22
|
--ars-color-primary-low: #006a60;
|
|
23
23
|
--ars-color-primary-hi: #12c0ae;
|
|
24
|
+
--ars-color-on-primary: var(--mat-sys-on-primary, #ffffff);
|
|
24
25
|
--ars-color-secondary: #4a635f;
|
|
25
26
|
--ars-color-secondary-low: #27403c;
|
|
26
27
|
--ars-color-error: #ff5449;
|
|
@@ -34,22 +35,22 @@
|
|
|
34
35
|
--ars-color-divider: #757d87;
|
|
35
36
|
--ars-color-overlay: rgba(255, 255, 255, 0.75);
|
|
36
37
|
--ars-color-background: #f7faf8;
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
--ars-dialog-background-color: var(--mat-sys-surface-container-high, #e6eae8);
|
|
41
|
-
--ars-
|
|
42
|
-
--ars-scrim-color: rgba(0, 0, 0, 0.24);
|
|
43
|
-
--ars-dialog-radius: 28px;
|
|
44
|
-
--ars-dialog-elevation: 0 4px 8px 3px rgba(0, 0, 0, 0.15), 0 1px 3px 0 rgba(0, 0, 0, 0.3);
|
|
45
|
-
//
|
|
46
|
-
--ars-busy-scrim-color: rgba(0, 0, 0, 0.28);
|
|
47
|
-
--ars-
|
|
48
|
-
--ars-busy-bare-color: #ffffff;
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
--ars-shell-z-index: 1100;
|
|
52
|
-
--ars-busy-z-index: 1090;
|
|
38
|
+
// ui.shell / pannello messaggio: riproduce la superficie di un dialog Material senza Material.
|
|
39
|
+
// Ogni token risolve sul tema dell'applicazione quando c'e', su un letterale quando non c'e'.
|
|
40
|
+
// Non confondere con --ars-dialog-item-*, che sono i dialog Material veri.
|
|
41
|
+
--ars-shell-dialog-background-color: var(--mat-sys-surface-container-high, #e6eae8);
|
|
42
|
+
--ars-shell-dialog-sunken-background-color: rgba(0, 0, 0, 0.05);
|
|
43
|
+
--ars-shell-dialog-scrim-color: rgba(0, 0, 0, 0.24);
|
|
44
|
+
--ars-shell-dialog-radius: 28px;
|
|
45
|
+
--ars-shell-dialog-elevation: 0 4px 8px 3px rgba(0, 0, 0, 0.15), 0 1px 3px 0 rgba(0, 0, 0, 0.3);
|
|
46
|
+
// ui.shell / overlay busy: barra, spinner e clessidra ridisegnati in CSS e SVG.
|
|
47
|
+
--ars-shell-busy-scrim-color: rgba(0, 0, 0, 0.28);
|
|
48
|
+
--ars-shell-busy-track-color: var(--mat-sys-surface-container-highest, #d5dbd8);
|
|
49
|
+
--ars-shell-busy-bare-color: #ffffff;
|
|
50
|
+
// Impilamento: nel top layer conta l'ordine di promozione, non lo z-index. Questi due numeri
|
|
51
|
+
// servono dove la Popover API manca, e li' cdk-overlay-container sta a 1000.
|
|
52
|
+
--ars-shell-dialog-z-index: 1100;
|
|
53
|
+
--ars-shell-busy-z-index: 1090;
|
|
53
54
|
// Drawer
|
|
54
55
|
--ars-drawer-background-color: #eff1ef;
|
|
55
56
|
--ars-drawer-divider-color: #6f7977;
|
|
@@ -74,6 +75,7 @@
|
|
|
74
75
|
--ars-color-primary: #53dbc9;
|
|
75
76
|
--ars-color-primary-low: #008679;
|
|
76
77
|
--ars-color-primary-hi: #74f8e5;
|
|
78
|
+
--ars-color-on-primary: var(--mat-sys-on-primary, #00382f);
|
|
77
79
|
--ars-color-secondary: #b1ccc6;
|
|
78
80
|
--ars-color-secondary-low: #627c77;
|
|
79
81
|
--ars-color-error: #ff5449;
|
|
@@ -90,13 +92,13 @@
|
|
|
90
92
|
--ars-color-overlay: rgba(0, 0, 0, 0.65);
|
|
91
93
|
--ars-color-background: #101413;
|
|
92
94
|
|
|
93
|
-
//
|
|
94
|
-
--ars-dialog-background-color: var(--mat-sys-surface-container-high, #282a29);
|
|
95
|
-
--ars-
|
|
96
|
-
--ars-scrim-color: rgba(0, 0, 0, 0.45);
|
|
97
|
-
//
|
|
98
|
-
--ars-busy-scrim-color: rgba(0, 0, 0, 0.45);
|
|
99
|
-
--ars-
|
|
95
|
+
// ui.shell / pannello messaggio
|
|
96
|
+
--ars-shell-dialog-background-color: var(--mat-sys-surface-container-high, #282a29);
|
|
97
|
+
--ars-shell-dialog-sunken-background-color: rgba(0, 0, 0, 0.22);
|
|
98
|
+
--ars-shell-dialog-scrim-color: rgba(0, 0, 0, 0.45);
|
|
99
|
+
// ui.shell / overlay busy
|
|
100
|
+
--ars-shell-busy-scrim-color: rgba(0, 0, 0, 0.45);
|
|
101
|
+
--ars-shell-busy-track-color: var(--mat-sys-surface-container-highest, #3a3d3c);
|
|
100
102
|
// Drawer
|
|
101
103
|
--ars-drawer-background-color: #212223;
|
|
102
104
|
--ars-drawer-divider-color: #899390;
|
|
@@ -1052,7 +1052,7 @@ declare class ClipperDocumentMenuComponent {
|
|
|
1052
1052
|
private readonly renderer2;
|
|
1053
1053
|
private readonly clipperService;
|
|
1054
1054
|
readonly useSelections: _angular_core.InputSignal<boolean>;
|
|
1055
|
-
readonly selectionSource: _angular_core.InputSignal<"
|
|
1055
|
+
readonly selectionSource: _angular_core.InputSignal<"bag" | "selection" | "none">;
|
|
1056
1056
|
/**
|
|
1057
1057
|
* Computed signal that returns the current effective document selection.
|
|
1058
1058
|
* Re-evaluates when any input signal or the underlying selection model changes.
|
|
@@ -66,6 +66,21 @@ declare class EqualsValidatorDirective implements Validator {
|
|
|
66
66
|
static ɵdir: i0.ɵɵDirectiveDeclaration<EqualsValidatorDirective, "[equals]", never, { "equals": { "alias": "equals"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Directive that validates a semicolon-separated list of email addresses.
|
|
71
|
+
* Apply `emails` to a text input containing one or more addresses separated by `;`.
|
|
72
|
+
*/
|
|
73
|
+
declare class EmailsValidatorDirective implements Validator {
|
|
74
|
+
/**
|
|
75
|
+
* Validates each address in a semicolon-separated email list.
|
|
76
|
+
* Returns `null` when the control is empty.
|
|
77
|
+
* @param control - The form control to validate.
|
|
78
|
+
*/
|
|
79
|
+
validate(control: AbstractControl): ValidationErrors | null;
|
|
80
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<EmailsValidatorDirective, never>;
|
|
81
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<EmailsValidatorDirective, "[emails]", never, {}, {}, never, never, true, never>;
|
|
82
|
+
}
|
|
83
|
+
|
|
69
84
|
/**
|
|
70
85
|
* Directive that validates that the host control's value is different from another control's value.
|
|
71
86
|
* Bind `[notEqual]="otherControl"`.
|
|
@@ -99,21 +114,6 @@ declare class NotEqualValidatorDirective implements Validator {
|
|
|
99
114
|
static ɵdir: i0.ɵɵDirectiveDeclaration<NotEqualValidatorDirective, "[notEqual]", never, { "notEqual": { "alias": "notEqual"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
100
115
|
}
|
|
101
116
|
|
|
102
|
-
/**
|
|
103
|
-
* Directive that validates a semicolon-separated list of email addresses.
|
|
104
|
-
* Apply `emails` to a text input containing one or more addresses separated by `;`.
|
|
105
|
-
*/
|
|
106
|
-
declare class EmailsValidatorDirective implements Validator {
|
|
107
|
-
/**
|
|
108
|
-
* Validates each address in a semicolon-separated email list.
|
|
109
|
-
* Returns `null` when the control is empty.
|
|
110
|
-
* @param control - The form control to validate.
|
|
111
|
-
*/
|
|
112
|
-
validate(control: AbstractControl): ValidationErrors | null;
|
|
113
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<EmailsValidatorDirective, never>;
|
|
114
|
-
static ɵdir: i0.ɵɵDirectiveDeclaration<EmailsValidatorDirective, "[emails]", never, {}, {}, never, never, true, never>;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
117
|
/**
|
|
118
118
|
* Directive that validates a control value as a GUID / UUID string.
|
|
119
119
|
* Apply `guid` to a text input that expects a valid UUID.
|
|
@@ -138,7 +138,7 @@ declare class ShellBusyComponent {
|
|
|
138
138
|
* a dialog, and it also takes the busy away immediately rather than with the grace period, so a
|
|
139
139
|
* dialog is never drawn under an overlay that is on its way out.
|
|
140
140
|
*
|
|
141
|
-
* The `--ars-shell-z-index` / `--ars-busy-z-index` pair (1100 / 1090, above the CDK's 1000) is
|
|
141
|
+
* The `--ars-shell-dialog-z-index` / `--ars-shell-busy-z-index` pair (1100 / 1090, above the CDK's 1000) is
|
|
142
142
|
* still there and still correct: it is what orders the overlays on a browser without the Popover
|
|
143
143
|
* API, where the CDK does not use it either.
|
|
144
144
|
*/
|
|
@@ -373,6 +373,15 @@ declare class ShellMessageComponent {
|
|
|
373
373
|
private readonly okButton;
|
|
374
374
|
/** Unique id tying the panel to its heading for assistive technology. */
|
|
375
375
|
protected readonly titleId: string;
|
|
376
|
+
/** Unique id tying the details panel to the header that opens it. */
|
|
377
|
+
protected readonly detailsId: string;
|
|
378
|
+
/**
|
|
379
|
+
* Whether the technical details are open.
|
|
380
|
+
*
|
|
381
|
+
* Closed on arrival, and closed again by every {@link setData}: the message is what the user is
|
|
382
|
+
* meant to read, and a stack trace unfolded under it is noise until they ask for it.
|
|
383
|
+
*/
|
|
384
|
+
protected readonly detailsOpen: _angular_core.WritableSignal<boolean>;
|
|
376
385
|
/** Current content, with the defaults the shell relies on already applied. */
|
|
377
386
|
protected readonly data: _angular_core.WritableSignal<ShellMessageData>;
|
|
378
387
|
/** True for a moment after a successful copy, so the button can acknowledge it. */
|
|
@@ -407,6 +416,11 @@ declare class ShellMessageComponent {
|
|
|
407
416
|
* @returns void
|
|
408
417
|
*/
|
|
409
418
|
setData(data: ShellMessageData): void;
|
|
419
|
+
/**
|
|
420
|
+
* Opens or closes the technical details panel.
|
|
421
|
+
* @returns void
|
|
422
|
+
*/
|
|
423
|
+
protected toggleDetails(): void;
|
|
410
424
|
/**
|
|
411
425
|
* Dismisses the panel. Safe to call more than once: only the first call is announced.
|
|
412
426
|
* @returns void
|