tmw-numeric 0.1.1

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.
@@ -0,0 +1,127 @@
1
+ # AI_BUILD_PLAN — tmw-numeric
2
+
3
+ Sostituto di `@eqproject/eqp-numeric`, nato non da un'iniziativa dedicata come tmw-select/tmw-table/
4
+ tmw-attachments, ma come tassello di un'indagine più ampia: rimozione sicura dei pacchetti
5
+ `@eqproject/*` da TMED (v. `Tmed.Web/TmedClient/package.json`), tenendo solo `eqp-filters` e
6
+ `eqp-dynamic-module` (quest'ultimo non rimovibile — è il motore dei form dinamici, non un widget).
7
+
8
+ ## Cosa sostituisce
9
+
10
+ `EqpNumericDirective` (selettore `[eqpNumericMask]`) — **non** un componente, una direttiva
11
+ `ControlValueAccessor` su `<input>` per la mascheratura di valori numerici/valuta (separatori
12
+ migliaia/decimali, prefisso/suffisso, precisione, min/max, modalità di digitazione FINANCIAL/
13
+ NATURAL). Documentata in `node_modules/@eqproject/eqp-numeric/README.md` (stessa forma/API di
14
+ `ngx-currency`/`ng2-currency-mask`).
15
+
16
+ ## Audit uso reale in TMED (prima di scrivere una riga di codice)
17
+
18
+ 5 punti d'uso reali, tutti campi prezzo (fatturazione/ambulatori, **fuori** da `projects/tmed-therapy`
19
+ — nessun impatto clinico/MDR):
20
+ - `invoice-generate.component.html:64`
21
+ - `add-outpatientclinics.component.html:562,1768,1776`
22
+ - `create-invoice-fattureincloud.component.html:136`
23
+
24
+ Tutti e 5 passano **lo stesso** `[options]="{ prefix: '€ ', thousands: '.', decimal: ',' }"` (formato
25
+ euro) — nessuno usa i default nudi del pacchetto (`$`/`,`/`.`) né chiama `EqpNumericModule.forRoot()`.
26
+ Wiring in `src/modules/shared.module.ts` (import + `imports`/`exports` di `SharedModule`).
27
+
28
+ ## Decisioni
29
+
30
+ 1. **Direttiva standalone**, stesso principio delle altre `tmw-*` (niente `TmwNumericModule`,
31
+ si importa `TmwNumericMaskDirective` direttamente).
32
+ 2. **Selettore** `[tmwNumericMask]` (rename `eqpNumericMask`→`tmwNumericMask`, stesso principio
33
+ `eqp-xxx`→`tmw-xxx` delle altre). **`[options]` e i nomi delle sue proprietà (`align`,
34
+ `allowNegative`, `decimal`, `precision`, `prefix`, `suffix`, `thousands`, `nullable`, `min`,
35
+ `max`, `inputMode`) restano INVARIATI** — compatibilità byte-per-byte con i binding esistenti,
36
+ il rename tocca solo l'attributo/selettore.
37
+ 3. **Nessun `forRoot()`**: nessun consumer reale lo usava, i default (`TMW_NUMERIC_DEFAULT_OPTIONS`)
38
+ bastano com'erano nell'originale.
39
+ 4. **`TmwNumericInputMode`** (rename `EqpNumericInputMode`) con gli stessi due valori
40
+ `FINANCIAL`/`NATURAL` e comportamento identico.
41
+
42
+ ## Bug scoperti e corretti durante la verifica funzionale (Playwright, non solo tsc)
43
+
44
+ La prima bozza (formattazione a piena precisione ad ogni tasto anche in modalità NATURAL) si è
45
+ rivelata **rotta digitando davvero** (verificato con `page.type()`, non solo lettura del codice):
46
+
47
+ 1. **Cifre perse durante la digitazione (NATURAL)**: arrotondare/paddare a `precision` ad OGNI
48
+ `input` event faceva sì che digitare `"1"` su un campo vuoto producesse subito `"$ 0.00"` —
49
+ la cifra veniva arrotondata via prima ancora di poter comporre un numero. Fix: formattazione
50
+ **live** durante la digitazione (nessun padding/arrotondamento, si preservano le cifre esatte
51
+ digitate, capped a `precision` cifre decimali) e formattazione **piena** (padding/arrotondamento
52
+ `toFixed`) solo a `blur`/`writeValue`/cambio opzioni. La modalità FINANCIAL non soffriva di
53
+ questo bug (si ricalcola sempre da zero dalle sole cifre, insensibile alla formattazione
54
+ precedente) — lì il formato pieno ad ogni tasto è corretto fin da subito.
55
+ 2. **Segno negativo mai riconosciuto**: `rawValue.startsWith('-')` non funziona MAI, perché il
56
+ segno digitato dall'utente finisce sempre DOPO un eventuale prefisso (es. `"$ -5"`, non
57
+ `"-$ 5"` nella stringa grezza del campo) — il controllo iniziale falliva sempre silenziosamente.
58
+ Fix: `rawValue.includes('-')`.
59
+
60
+ Entrambi scoperti SOLO grazie a un test funzionale che digita davvero nel campo (Playwright
61
+ `page.locator(...).type(...)`) — una verifica solo statica/tsc non li avrebbe mai presi.
62
+
63
+ ## Verifica
64
+
65
+ Playground `test-tmw-numeric` in `tmw-suite` (route `/tmw-numeric`, 3 casi: default TMED — euro,
66
+ virgola decimale, punto migliaia, no `[options]` custom oltre a quello reale —, custom con
67
+ `nullable`+`allowNegative:false`, FINANCIAL). Verificato via Playwright headless (Chromium 1228 già
68
+ installato in TMED, non serve emulazione mobile qui): digitazione carattere per carattere,
69
+ `fill('')`+`type(...)`+`blur()`, controllo sia del valore visualizzato sia del model (`ngModel`)
70
+ sottostante. Tutti i casi passano dopo il fix, incluso il caso reale esatto usato in TMED (prefisso
71
+ `€ `, migliaia `.`, decimale `,`). Zero errori console.
72
+
73
+ ## Sync in TMED
74
+
75
+ `tmw-numeric` 0.1.0, build produzione, `npm pack` → tarball locale (non pubblicato su npm reale,
76
+ a differenza di tmw-attachments — l'utente non l'ha richiesto per questo pacchetto, resta per
77
+ quando lo chiederà a parte, stesso principio di tmw-table/tmw-select prima della pubblicazione).
78
+ `TmedClient/package.json`: rimosso `@eqproject/eqp-numeric`, aggiunto `tmw-numeric` (tarball).
79
+ `shared.module.ts`: `EqpNumericModule`→`TmwNumericMaskDirective`. 5 template: `eqpNumericMask`→
80
+ `tmwNumericMask` (`[options]` invariato). `tsc --noEmit --skipLibCheck`: 27 errori pre-esistenti
81
+ invariati, zero nuovi. `ng serve` (heap 16GB, v. `project_ng_serve_perf` in memoria — necessario,
82
+ altrimenti OOM) pulito, `Compiled successfully`.
83
+
84
+ **Non verificato dal vivo in TMED** (stesso limite onesto di altre sincronizzazioni): nessuna
85
+ credenziale e2e reale disponibile in questa sessione (`e2e/.auth/credentials.json` assente) — la
86
+ verifica del comportamento REALE nei 5 campi prezzo si basa su tsc pulito + AOT compile pulito +
87
+ verifica funzionale esaustiva nel playground con la STESSA identica configurazione `[options]`
88
+ usata in produzione (prefisso `€ `, migliaia `.`, decimale `,`), non su un click reale in TMED.
89
+
90
+ ## Round mobile/tablet (2026-07-15, stessa giornata) — v0.1.0 → v0.1.1
91
+
92
+ L'utente ha chiesto esplicitamente se il componente fosse pensato per mobile/tablet — risposta
93
+ onesta: non ancora. Analisi e fix:
94
+
95
+ 1. **Nessun hint di tastiera numerica**: un `<input>` senza `type`/`inputmode` mostra la tastiera
96
+ alfanumerica completa su mobile/tablet — sbagliato per un campo numerico, e nessuno dei 5 usi
97
+ reali in TMED imposta `type`/`inputmode` proprio. Fix: la direttiva imposta
98
+ `inputmode="decimal"` nel costruttore, MA SOLO se il consumer non ha già messo un proprio
99
+ `type`/`inputmode` nel template (nessun conflitto, nessun binding Angular duplicato sullo
100
+ stesso attributo).
101
+
102
+ 2. **Bug reale scoperto testando su viewport mobile con tastiera touch**: le tastiere numeriche
103
+ mobile mostrano quasi sempre "." come tasto decimale, a prescindere dalla configurazione locale
104
+ — un primo fix ("accetta sia il separatore configurato sia `.` come decimale") si è rivelato
105
+ **rotto per la configurazione ESATTA usata in produzione** (`thousands: '.'`, `decimal: ','` —
106
+ formato euro): il punto delle migliaia già inserito dal render "live" veniva confuso con il
107
+ punto decimale appena digitato (entrambi lo stesso carattere), producendo un parsing
108
+ completamente sbagliato (digitare `"1234.5"` risultava in `"€ 1,23"` invece di
109
+ `"€ 1.234,50"`). **Fix corretto**: stato persistente `_hasDecimalState`, impostato SOLO quando
110
+ `event.data` (il carattere/testo appena digitato/incollato, non l'intera stringa già
111
+ formattata) corrisponde al separatore decimale configurato o a `'.'` — una volta noto che un
112
+ separatore decimale esiste, si cerca la sua ULTIMA occorrenza nella stringa (le migliaia, anche
113
+ quando coincidono con `'.'`, possono comparire SOLO prima del separatore decimale reale, mai
114
+ dopo — la formattazione non raggruppa mai le cifre decimali). Gestito anche il caso di
115
+ backspace sul separatore (torna correttamente a "nessun decimale", verificato: cancellare la
116
+ virgola e digitare una cifra la rimette nella parte intera, non in quella decimale).
117
+
118
+ **Cosa NON serviva**: nessun CSS responsive/breakpoint — la direttiva non possiede overlay/modali/
119
+ dropdown propri (a differenza di tmw-attachments/tmw-select/tmw-table), è un attributo su un
120
+ `<input>` che il consumer stila autonomamente; non c'è "chrome" della libreria che possa rompersi
121
+ su schermi piccoli.
122
+
123
+ **Verifica**: Playwright con device emulation (`iPhone 13`, `hasTouch:true`) — confermato
124
+ `inputmode="decimal"` presente, digitazione carattere per carattere del formato euro reale
125
+ (`"1234.5"` e `"1234,5"`) entrambe producono `"€ 1.234,50"` / modello `1234.5`, backspace sul
126
+ separatore verificato, zero errori console. Bump a v0.1.1, tarball rigenerata, risincronizzata in
127
+ TMED (`tsc` pulito, 27 errori pre-esistenti invariati).
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Modalità di digitazione — nomi/valori/comportamento invariati rispetto a
3
+ * `@eqproject/eqp-numeric` (`EqpNumericInputMode`), per parità di comportamento.
4
+ */
5
+ export var TmwNumericInputMode;
6
+ (function (TmwNumericInputMode) {
7
+ /**
8
+ * I numeri partono dalla precisione più alta (i decimali): digitare uno shifta tutto a
9
+ * sinistra, il carattere decimale digitato viene ignorato. Es. `'12'` → `'0.12'`,
10
+ * `'1234'` → `'12.34'`.
11
+ */
12
+ TmwNumericInputMode["FINANCIAL"] = "FINANCIAL";
13
+ /**
14
+ * I numeri partono a sinistra del separatore decimale, come un campo di testo qualunque.
15
+ * Es. `'1234'` → `'1234'`, `'12.34'` → `'12.34'`.
16
+ */
17
+ TmwNumericInputMode["NATURAL"] = "NATURAL";
18
+ })(TmwNumericInputMode || (TmwNumericInputMode = {}));
19
+ /**
20
+ * Default identici a `@eqproject/eqp-numeric` — nessun consumer TMED chiamava
21
+ * `EqpNumericModule.forRoot(...)` né passava `[options]`, quindi questi default SONO il
22
+ * comportamento reale in produzione (v. AI_BUILD_PLAN.md per i 5 punti d'uso reali).
23
+ */
24
+ export const TMW_NUMERIC_DEFAULT_OPTIONS = {
25
+ align: 'right',
26
+ allowNegative: true,
27
+ decimal: '.',
28
+ precision: 2,
29
+ prefix: '$ ',
30
+ suffix: '',
31
+ thousands: ',',
32
+ nullable: false,
33
+ min: undefined,
34
+ max: undefined,
35
+ inputMode: TmwNumericInputMode.NATURAL,
36
+ };
37
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG13LW51bWVyaWMtb3B0aW9ucy5tb2RlbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3Rtdy1udW1lcmljL3NyYy9saWIvbW9kZWxzL3Rtdy1udW1lcmljLW9wdGlvbnMubW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBQ0gsTUFBTSxDQUFOLElBQVksbUJBWVg7QUFaRCxXQUFZLG1CQUFtQjtJQUM3Qjs7OztPQUlHO0lBQ0gsOENBQXVCLENBQUE7SUFDdkI7OztPQUdHO0lBQ0gsMENBQW1CLENBQUE7QUFDckIsQ0FBQyxFQVpXLG1CQUFtQixLQUFuQixtQkFBbUIsUUFZOUI7QUEyQkQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLDJCQUEyQixHQUFnQztJQUN0RSxLQUFLLEVBQUUsT0FBTztJQUNkLGFBQWEsRUFBRSxJQUFJO0lBQ25CLE9BQU8sRUFBRSxHQUFHO0lBQ1osU0FBUyxFQUFFLENBQUM7SUFDWixNQUFNLEVBQUUsSUFBSTtJQUNaLE1BQU0sRUFBRSxFQUFFO0lBQ1YsU0FBUyxFQUFFLEdBQUc7SUFDZCxRQUFRLEVBQUUsS0FBSztJQUNmLEdBQUcsRUFBRSxTQUE4QjtJQUNuQyxHQUFHLEVBQUUsU0FBOEI7SUFDbkMsU0FBUyxFQUFFLG1CQUFtQixDQUFDLE9BQU87Q0FDdkMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTW9kYWxpdMOgIGRpIGRpZ2l0YXppb25lIOKAlCBub21pL3ZhbG9yaS9jb21wb3J0YW1lbnRvIGludmFyaWF0aSByaXNwZXR0byBhXG4gKiBgQGVxcHJvamVjdC9lcXAtbnVtZXJpY2AgKGBFcXBOdW1lcmljSW5wdXRNb2RlYCksIHBlciBwYXJpdMOgIGRpIGNvbXBvcnRhbWVudG8uXG4gKi9cbmV4cG9ydCBlbnVtIFRtd051bWVyaWNJbnB1dE1vZGUge1xuICAvKipcbiAgICogSSBudW1lcmkgcGFydG9ubyBkYWxsYSBwcmVjaXNpb25lIHBpw7kgYWx0YSAoaSBkZWNpbWFsaSk6IGRpZ2l0YXJlIHVubyBzaGlmdGEgdHV0dG8gYVxuICAgKiBzaW5pc3RyYSwgaWwgY2FyYXR0ZXJlIGRlY2ltYWxlIGRpZ2l0YXRvIHZpZW5lIGlnbm9yYXRvLiBFcy4gYCcxMidgIOKGkiBgJzAuMTInYCxcbiAgICogYCcxMjM0J2Ag4oaSIGAnMTIuMzQnYC5cbiAgICovXG4gIEZJTkFOQ0lBTCA9ICdGSU5BTkNJQUwnLFxuICAvKipcbiAgICogSSBudW1lcmkgcGFydG9ubyBhIHNpbmlzdHJhIGRlbCBzZXBhcmF0b3JlIGRlY2ltYWxlLCBjb21lIHVuIGNhbXBvIGRpIHRlc3RvIHF1YWx1bnF1ZS5cbiAgICogRXMuIGAnMTIzNCdgIOKGkiBgJzEyMzQnYCwgYCcxMi4zNCdgIOKGkiBgJzEyLjM0J2AuXG4gICAqL1xuICBOQVRVUkFMID0gJ05BVFVSQUwnLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRtd051bWVyaWNPcHRpb25zIHtcbiAgLyoqIEFsbGluZWFtZW50byB0ZXN0byBuZWxsJ2lucHV0LiBEZWZhdWx0IGAncmlnaHQnYC4gKi9cbiAgYWxpZ24/OiAnbGVmdCcgfCAncmlnaHQnO1xuICAvKiogU2UgYHRydWVgIGNvbnNlbnRlIHZhbG9yaSBuZWdhdGl2aS4gRGVmYXVsdCBgdHJ1ZWAuICovXG4gIGFsbG93TmVnYXRpdmU/OiBib29sZWFuO1xuICAvKiogU2VwYXJhdG9yZSBkZWkgZGVjaW1hbGkuIERlZmF1bHQgYCcuJ2AuICovXG4gIGRlY2ltYWw/OiBzdHJpbmc7XG4gIC8qKiBOdW1lcm8gZGkgY2lmcmUgZGVjaW1hbGkuIERlZmF1bHQgYDJgLiAqL1xuICBwcmVjaXNpb24/OiBudW1iZXI7XG4gIC8qKiBQcmVmaXNzbyAoZXMuIHNpbWJvbG8gdmFsdXRhKS4gRGVmYXVsdCBgJyQgJ2AuICovXG4gIHByZWZpeD86IHN0cmluZztcbiAgLyoqIFN1ZmZpc3NvLiBEZWZhdWx0IGAnJ2AuICovXG4gIHN1ZmZpeD86IHN0cmluZztcbiAgLyoqIFNlcGFyYXRvcmUgZGVsbGUgbWlnbGlhaWEuIERlZmF1bHQgYCcsJ2AuICovXG4gIHRob3VzYW5kcz86IHN0cmluZztcbiAgLyoqIFNlIGB0cnVlYCwgdW4gY2FtcG8gdnVvdG8gcHJvZHVjZSBgbnVsbGAgaW52ZWNlIGRpIGAwYC4gRGVmYXVsdCBgZmFsc2VgLiAqL1xuICBudWxsYWJsZT86IGJvb2xlYW47XG4gIC8qKiBWYWxvcmUgbWluaW1vIGNvbnNlbnRpdG8uIERlZmF1bHQgYHVuZGVmaW5lZGAgKG5lc3N1biBsaW1pdGUpLiAqL1xuICBtaW4/OiBudW1iZXI7XG4gIC8qKiBWYWxvcmUgbWFzc2ltbyBjb25zZW50aXRvLiBEZWZhdWx0IGB1bmRlZmluZWRgIChuZXNzdW4gbGltaXRlKS4gKi9cbiAgbWF4PzogbnVtYmVyO1xuICAvKiogTW9kYWxpdMOgIGRpIGRpZ2l0YXppb25lLiBEZWZhdWx0IGBOQVRVUkFMYC4gKi9cbiAgaW5wdXRNb2RlPzogVG13TnVtZXJpY0lucHV0TW9kZTtcbn1cblxuLyoqXG4gKiBEZWZhdWx0IGlkZW50aWNpIGEgYEBlcXByb2plY3QvZXFwLW51bWVyaWNgIOKAlCBuZXNzdW4gY29uc3VtZXIgVE1FRCBjaGlhbWF2YVxuICogYEVxcE51bWVyaWNNb2R1bGUuZm9yUm9vdCguLi4pYCBuw6kgcGFzc2F2YSBgW29wdGlvbnNdYCwgcXVpbmRpIHF1ZXN0aSBkZWZhdWx0IFNPTk8gaWxcbiAqIGNvbXBvcnRhbWVudG8gcmVhbGUgaW4gcHJvZHV6aW9uZSAodi4gQUlfQlVJTERfUExBTi5tZCBwZXIgaSA1IHB1bnRpIGQndXNvIHJlYWxpKS5cbiAqL1xuZXhwb3J0IGNvbnN0IFRNV19OVU1FUklDX0RFRkFVTFRfT1BUSU9OUzogUmVxdWlyZWQ8VG13TnVtZXJpY09wdGlvbnM+ID0ge1xuICBhbGlnbjogJ3JpZ2h0JyxcbiAgYWxsb3dOZWdhdGl2ZTogdHJ1ZSxcbiAgZGVjaW1hbDogJy4nLFxuICBwcmVjaXNpb246IDIsXG4gIHByZWZpeDogJyQgJyxcbiAgc3VmZml4OiAnJyxcbiAgdGhvdXNhbmRzOiAnLCcsXG4gIG51bGxhYmxlOiBmYWxzZSxcbiAgbWluOiB1bmRlZmluZWQgYXMgdW5rbm93biBhcyBudW1iZXIsXG4gIG1heDogdW5kZWZpbmVkIGFzIHVua25vd24gYXMgbnVtYmVyLFxuICBpbnB1dE1vZGU6IFRtd051bWVyaWNJbnB1dE1vZGUuTkFUVVJBTCxcbn07XG4iXX0=
@@ -0,0 +1,272 @@
1
+ import { Directive, HostListener, Input, forwardRef } from '@angular/core';
2
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
3
+ import { TMW_NUMERIC_DEFAULT_OPTIONS, TmwNumericInputMode } from './models/tmw-numeric-options.model';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * Sostituto di `[eqpNumericMask]` (`@eqproject/eqp-numeric`) — stesso `[options]`, stessi nomi
7
+ * di opzione, stessi default (v. `TMW_NUMERIC_DEFAULT_OPTIONS`). Nessun `forRoot()`: nessun
8
+ * consumer reale in TMED lo usava, i default del pacchetto originale erano già il comportamento
9
+ * effettivo in produzione.
10
+ *
11
+ * Formatta un `<input>` come numero mascherato (valuta/decimale) mantenendo il model
12
+ * (`ngModel`/`formControlName`) come `number | null` — l'utente vede `'$ 1,234.56'`, il form
13
+ * riceve `1234.56`.
14
+ *
15
+ * In modalità NATURAL la formattazione "live" (durante la digitazione) NON forza il padding a
16
+ * piena precisione: farlo ad ogni tasto arrotonderebbe via le cifre appena digitate (es. digitare
17
+ * "1" su un campo vuoto renderizzerebbe subito "0.00", perdendo la cifra) — il padding/
18
+ * arrotondamento pieno avviene solo al `blur`/`writeValue`. In modalità FINANCIAL questo problema
19
+ * non esiste (il valore si ricalcola sempre da zero dalle sole cifre digitate, insensibile alla
20
+ * formattazione precedente), quindi lì si usa direttamente il formato pieno ad ogni tasto.
21
+ */
22
+ export class TmwNumericMaskDirective {
23
+ set options(value) {
24
+ this._options = { ...TMW_NUMERIC_DEFAULT_OPTIONS, ...(value ?? {}) };
25
+ this._applyAlignment();
26
+ this._renderFinal(this._value);
27
+ }
28
+ constructor(_elementRef, _renderer) {
29
+ this._elementRef = _elementRef;
30
+ this._renderer = _renderer;
31
+ this._options = { ...TMW_NUMERIC_DEFAULT_OPTIONS };
32
+ this._value = null;
33
+ this._onChange = () => { };
34
+ this._onTouched = () => { };
35
+ this._disabled = false;
36
+ /**
37
+ * Stato PERSISTENTE (non ri-derivato ogni volta dalla stringa già formattata): true dal
38
+ * momento in cui l'utente ha digitato/incollato un carattere decimale, false quando il campo
39
+ * è vuoto o quel carattere viene cancellato. Necessario perché in formato euro `thousands` e
40
+ * l'alternativa mobile-friendly per `decimal` possono coincidere entrambi su `'.'` — v.
41
+ * `_tokenize` per come risolve l'ambiguità usando questo stato invece di ri-cercare "il primo
42
+ * punto" nella stringa (che potrebbe essere un separatore delle migliaia già inserito da noi).
43
+ */
44
+ this._hasDecimalState = false;
45
+ this._applyAlignment();
46
+ // Senza un hint esplicito, mobile/tablet mostrano la tastiera alfanumerica completa per un
47
+ // <input> senza type/inputmode — sbagliato per un campo numerico. Impostato solo se il
48
+ // consumer non ha già messo il proprio `type`/`inputmode` nel template (es. `type="tel"`,
49
+ // suggerito anche dal README dell'originale `eqp-numeric` per Ionic).
50
+ const el = this._elementRef.nativeElement;
51
+ if (!el.hasAttribute('inputmode') && !el.hasAttribute('type')) {
52
+ this._renderer.setAttribute(el, 'inputmode', 'decimal');
53
+ }
54
+ }
55
+ //#region ControlValueAccessor
56
+ writeValue(value) {
57
+ this._value = this._roundToPrecision(this._clampRange(value == null ? null : Number(value)));
58
+ this._hasDecimalState = false;
59
+ this._renderFinal(this._value);
60
+ }
61
+ registerOnChange(fn) {
62
+ this._onChange = fn;
63
+ }
64
+ registerOnTouched(fn) {
65
+ this._onTouched = fn;
66
+ }
67
+ setDisabledState(isDisabled) {
68
+ this._disabled = isDisabled;
69
+ this._renderer.setProperty(this._elementRef.nativeElement, 'disabled', isDisabled);
70
+ }
71
+ //#endregion
72
+ onInput(event) {
73
+ if (this._disabled) {
74
+ return;
75
+ }
76
+ const rawValue = event.target.value;
77
+ const caretFromEnd = this._captureCaretFromEnd();
78
+ if (this._options.inputMode === TmwNumericInputMode.FINANCIAL) {
79
+ this._value = this._clampRange(this._parseFinancial(rawValue));
80
+ this._onChange(this._value);
81
+ this._renderFinal(this._value);
82
+ }
83
+ else {
84
+ const { decimal } = this._options;
85
+ const insertedText = event.data;
86
+ // Il carattere/testo appena digitato o incollato (`event.data`) dice INEQUIVOCABILMENTE se
87
+ // l'utente sta esprimendo l'intento "questo è il separatore decimale" — a differenza di
88
+ // ri-cercare "il primo punto" nell'intera stringa già formattata, che in formato euro
89
+ // (`thousands: '.'`) confonderebbe un punto delle migliaia già inserito da noi con il
90
+ // punto decimale appena digitato (v. commento su `_hasDecimalState`).
91
+ if (insertedText && (insertedText.includes(decimal) || insertedText.includes('.'))) {
92
+ this._hasDecimalState = true;
93
+ }
94
+ if (rawValue.length === 0) {
95
+ this._hasDecimalState = false;
96
+ }
97
+ const { integerDigits, decimalDigits, hasDecimalSeparator, isNegative } = this._tokenize(rawValue, this._hasDecimalState);
98
+ this._hasDecimalState = hasDecimalSeparator;
99
+ this._value = this._clampRange(this._toNumber(integerDigits, decimalDigits, isNegative));
100
+ this._onChange(this._value);
101
+ this._renderLive(integerDigits, decimalDigits, hasDecimalSeparator, isNegative);
102
+ }
103
+ this._restoreCaretFromEnd(caretFromEnd);
104
+ }
105
+ onBlur() {
106
+ this._onTouched();
107
+ this._value = this._roundToPrecision(this._value);
108
+ this._onChange(this._value);
109
+ this._renderFinal(this._value);
110
+ }
111
+ _applyAlignment() {
112
+ this._renderer.setStyle(this._elementRef.nativeElement, 'text-align', this._options.align);
113
+ }
114
+ /**
115
+ * Modalità FINANCIAL: TUTTE le cifre della stringa (incluse quelle già formattate dal render
116
+ * precedente — prefisso/migliaia/decimali) vengono lette come un unico intero in centesimi
117
+ * (o nella più piccola unità di `precision`) e ridivise per `10^precision` — è quello che dà
118
+ * l'effetto "shift da destra" tipico delle casse, insensibile a qualunque formattazione
119
+ * precedente (a differenza di NATURAL non serve un formato "live" separato).
120
+ */
121
+ _parseFinancial(rawValue) {
122
+ const { precision, allowNegative, nullable } = this._options;
123
+ const isNegative = allowNegative && this._hasTypedMinus(rawValue);
124
+ const digitsOnly = rawValue.replace(/[^0-9]/g, '');
125
+ if (digitsOnly.length === 0) {
126
+ return nullable ? null : 0;
127
+ }
128
+ const units = parseInt(digitsOnly, 10);
129
+ const value = units / Math.pow(10, precision);
130
+ return isNegative ? -value : value;
131
+ }
132
+ /**
133
+ * `rawValue.startsWith('-')` non basta: il segno digitato dall'utente finisce SEMPRE dopo un
134
+ * eventuale prefisso (es. `"$ -5"`), mai a inizio stringa assoluto — si cerca quindi il
135
+ * carattere ovunque nella stringa.
136
+ */
137
+ _hasTypedMinus(rawValue) {
138
+ return rawValue.includes('-');
139
+ }
140
+ /**
141
+ * Estrae dalla stringa grezza le sole cifre intere/decimali digitate. Usato SOLO in modalità
142
+ * NATURAL. `hasDecimalHint` (stato persistente, v. `_hasDecimalState`) dice se un separatore
143
+ * decimale è già stato digitato in un keystroke precedente:
144
+ *
145
+ * - `false`: nessun separatore ancora — si scartano TUTTI i caratteri non-cifra (incluso un
146
+ * eventuale punto delle migliaia già presente dal render precedente), tutto ciò che resta è
147
+ * parte intera.
148
+ * - `true`: si cerca l'ULTIMA occorrenza di `decimal` o `'.'` nella stringa — mai la prima. Le
149
+ * migliaia (anche quando coincidono con `'.'`, formato euro) possono comparire SOLO PRIMA del
150
+ * separatore decimale reale (la formattazione non raggruppa mai le cifre decimali), quindi
151
+ * l'ultima occorrenza è sempre quella vera, senza ambiguità. Se non se ne trova più nessuna
152
+ * (l'utente ha cancellato il separatore), si ritorna a "nessun decimale".
153
+ */
154
+ _tokenize(rawValue, hasDecimalHint) {
155
+ const { decimal, allowNegative, precision } = this._options;
156
+ const isNegative = allowNegative && this._hasTypedMinus(rawValue);
157
+ if (!hasDecimalHint) {
158
+ return { integerDigits: rawValue.replace(/[^0-9]/g, ''), decimalDigits: '', hasDecimalSeparator: false, isNegative };
159
+ }
160
+ let splitIndex = -1;
161
+ for (let i = rawValue.length - 1; i >= 0; i--) {
162
+ if (rawValue[i] === decimal || rawValue[i] === '.') {
163
+ splitIndex = i;
164
+ break;
165
+ }
166
+ }
167
+ if (splitIndex === -1) {
168
+ return { integerDigits: rawValue.replace(/[^0-9]/g, ''), decimalDigits: '', hasDecimalSeparator: false, isNegative };
169
+ }
170
+ const integerDigits = rawValue.slice(0, splitIndex).replace(/[^0-9]/g, '');
171
+ const decimalDigits = rawValue.slice(splitIndex + 1).replace(/[^0-9]/g, '').slice(0, precision);
172
+ return { integerDigits, decimalDigits, hasDecimalSeparator: true, isNegative };
173
+ }
174
+ _toNumber(integerDigits, decimalDigits, isNegative) {
175
+ if (integerDigits.length === 0 && decimalDigits.length === 0) {
176
+ return this._options.nullable ? null : 0;
177
+ }
178
+ const value = parseFloat(`${integerDigits || '0'}.${decimalDigits || '0'}`);
179
+ return isNegative ? -value : value;
180
+ }
181
+ /** Applica solo `allowNegative`/`min`/`max` — NON arrotonda a `precision` (v. commento di classe). */
182
+ _clampRange(value) {
183
+ if (value == null) {
184
+ return value;
185
+ }
186
+ const { min, max, allowNegative } = this._options;
187
+ let result = value;
188
+ if (!allowNegative && result < 0) {
189
+ result = -result;
190
+ }
191
+ if (min != null && result < min) {
192
+ result = min;
193
+ }
194
+ if (max != null && result > max) {
195
+ result = max;
196
+ }
197
+ return result;
198
+ }
199
+ _roundToPrecision(value) {
200
+ if (value == null) {
201
+ return value;
202
+ }
203
+ const factor = Math.pow(10, this._options.precision);
204
+ return Math.round(value * factor) / factor;
205
+ }
206
+ /** Formato "live", usato in NATURAL durante la digitazione: nessun padding/arrotondamento. */
207
+ _renderLive(integerDigits, decimalDigits, hasDecimalSeparator, isNegative) {
208
+ const { prefix, suffix, thousands, decimal, precision } = this._options;
209
+ const groupedInteger = integerDigits.replace(/\B(?=(\d{3})+(?!\d))/g, thousands);
210
+ const decimalSegment = precision > 0 && hasDecimalSeparator ? decimal + decimalDigits : '';
211
+ const formatted = `${isNegative ? '-' : ''}${prefix}${groupedInteger}${decimalSegment}${suffix}`;
212
+ this._renderer.setProperty(this._elementRef.nativeElement, 'value', formatted);
213
+ }
214
+ /** Formato pieno (padding a `precision`, arrotondato) — usato a `blur`/`writeValue`/opzioni cambiate. */
215
+ _renderFinal(value) {
216
+ const formatted = value == null ? '' : this._formatFull(value);
217
+ this._renderer.setProperty(this._elementRef.nativeElement, 'value', formatted);
218
+ }
219
+ _formatFull(value) {
220
+ const { prefix, suffix, thousands, decimal, precision } = this._options;
221
+ const isNegative = value < 0;
222
+ const fixed = Math.abs(value).toFixed(precision);
223
+ const [integerPart, decimalPart] = fixed.split('.');
224
+ const groupedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousands);
225
+ const decimalSegment = precision > 0 ? decimal + decimalPart : '';
226
+ return `${isNegative ? '-' : ''}${prefix}${groupedInteger}${decimalSegment}${suffix}`;
227
+ }
228
+ _captureCaretFromEnd() {
229
+ const el = this._elementRef.nativeElement;
230
+ const caret = el.selectionStart ?? el.value.length;
231
+ return el.value.length - caret;
232
+ }
233
+ _restoreCaretFromEnd(distanceFromEnd) {
234
+ const el = this._elementRef.nativeElement;
235
+ const position = Math.max(0, el.value.length - distanceFromEnd);
236
+ // Il reformat avviene sincronamente nello stesso ciclo dell'evento `input`: il browser
237
+ // applica la posizione del cursore SUBITO dopo, senza bisogno di un setTimeout/microtask.
238
+ el.setSelectionRange(position, position);
239
+ }
240
+ }
241
+ TmwNumericMaskDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TmwNumericMaskDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
242
+ TmwNumericMaskDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: TmwNumericMaskDirective, isStandalone: true, selector: "[tmwNumericMask]", inputs: { options: "options" }, host: { listeners: { "input": "onInput($event)", "blur": "onBlur()" } }, providers: [
243
+ {
244
+ provide: NG_VALUE_ACCESSOR,
245
+ useExisting: forwardRef(() => TmwNumericMaskDirective),
246
+ multi: true,
247
+ },
248
+ ], ngImport: i0 });
249
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: TmwNumericMaskDirective, decorators: [{
250
+ type: Directive,
251
+ args: [{
252
+ selector: '[tmwNumericMask]',
253
+ standalone: true,
254
+ providers: [
255
+ {
256
+ provide: NG_VALUE_ACCESSOR,
257
+ useExisting: forwardRef(() => TmwNumericMaskDirective),
258
+ multi: true,
259
+ },
260
+ ],
261
+ }]
262
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }]; }, propDecorators: { options: [{
263
+ type: Input,
264
+ args: ['options']
265
+ }], onInput: [{
266
+ type: HostListener,
267
+ args: ['input', ['$event']]
268
+ }], onBlur: [{
269
+ type: HostListener,
270
+ args: ['blur']
271
+ }] } });
272
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG13LW51bWVyaWMtbWFzay5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy90bXctbnVtZXJpYy9zcmMvbGliL3Rtdy1udW1lcmljLW1hc2suZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQWMsWUFBWSxFQUFFLEtBQUssRUFBYSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbEcsT0FBTyxFQUFFLGlCQUFpQixFQUF3QixNQUFNLGdCQUFnQixDQUFDO0FBQ3pFLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxtQkFBbUIsRUFBcUIsTUFBTSxvQ0FBb0MsQ0FBQzs7QUFFekg7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFZSCxNQUFNLE9BQU8sdUJBQXVCO0lBR2xDLElBQ0ksT0FBTyxDQUFDLEtBQW9DO1FBQzlDLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxHQUFHLDJCQUEyQixFQUFFLEdBQUcsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUNyRSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakMsQ0FBQztJQWdCRCxZQUFvQixXQUF5QyxFQUFVLFNBQW9CO1FBQXZFLGdCQUFXLEdBQVgsV0FBVyxDQUE4QjtRQUFVLGNBQVMsR0FBVCxTQUFTLENBQVc7UUF2Qm5GLGFBQVEsR0FBZ0MsRUFBRSxHQUFHLDJCQUEyQixFQUFFLENBQUM7UUFTM0UsV0FBTSxHQUFrQixJQUFJLENBQUM7UUFDN0IsY0FBUyxHQUFtQyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUM7UUFDckQsZUFBVSxHQUFlLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQztRQUNsQyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBQzFCOzs7Ozs7O1dBT0c7UUFDSyxxQkFBZ0Is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OztvSEF4UFUsdUJBQXVCO3dHQUF2Qix1QkFBdUIsd0tBUnZCO1FBQ1Q7WUFDRSxPQUFPLEVBQUUsaUJBQWlCO1lBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsdUJBQXVCLENBQUM7WUFDdEQsS0FBSyxFQUFFLElBQUk7U0FDWjtLQUNGOzJGQUVVLHVCQUF1QjtrQkFYbkMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsa0JBQWtCO29CQUM1QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsU0FBUyxFQUFFO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLHdCQUF3QixDQUFDOzRCQUN0RCxLQUFLLEVBQUUsSUFBSTt5QkFDWjtxQkFDRjtpQkFDRjt5SEFLSyxPQUFPO3NCQURWLEtBQUs7dUJBQUMsU0FBUztnQkF5RGhCLE9BQU87c0JBRE4sWUFBWTt1QkFBQyxPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBb0NqQyxNQUFNO3NCQURMLFlBQVk7dUJBQUMsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgSG9zdExpc3RlbmVyLCBJbnB1dCwgUmVuZGVyZXIyLCBmb3J3YXJkUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOR19WQUxVRV9BQ0NFU1NPUiwgQ29udHJvbFZhbHVlQWNjZXNzb3IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBUTVdfTlVNRVJJQ19ERUZBVUxUX09QVElPTlMsIFRtd051bWVyaWNJbnB1dE1vZGUsIFRtd051bWVyaWNPcHRpb25zIH0gZnJvbSAnLi9tb2RlbHMvdG13LW51bWVyaWMtb3B0aW9ucy5tb2RlbCc7XG5cbi8qKlxuICogU29zdGl0dXRvIGRpIGBbZXFwTnVtZXJpY01hc2tdYCAoYEBlcXByb2plY3QvZXFwLW51bWVyaWNgKSDigJQgc3Rlc3NvIGBbb3B0aW9uc11gLCBzdGVzc2kgbm9taVxuICogZGkgb3B6aW9uZSwgc3Rlc3NpIGRlZmF1bHQgKHYuIGBUTVdfTlVNRVJJQ19ERUZBVUxUX09QVElPTlNgKS4gTmVzc3VuIGBmb3JSb290KClgOiBuZXNzdW5cbiAqIGNvbnN1bWVyIHJlYWxlIGluIFRNRUQgbG8gdXNhdmEsIGkgZGVmYXVsdCBkZWwgcGFjY2hldHRvIG9yaWdpbmFsZSBlcmFubyBnacOgIGlsIGNvbXBvcnRhbWVudG9cbiAqIGVmZmV0dGl2byBpbiBwcm9kdXppb25lLlxuICpcbiAqIEZvcm1hdHRhIHVuIGA8aW5wdXQ+YCBjb21lIG51bWVybyBtYXNjaGVyYXRvICh2YWx1dGEvZGVjaW1hbGUpIG1hbnRlbmVuZG8gaWwgbW9kZWxcbiAqIChgbmdNb2RlbGAvYGZvcm1Db250cm9sTmFtZWApIGNvbWUgYG51bWJlciB8IG51bGxgIOKAlCBsJ3V0ZW50ZSB2ZWRlIGAnJCAxLDIzNC41NidgLCBpbCBmb3JtXG4gKiByaWNldmUgYDEyMzQuNTZgLlxuICpcbiAqIEluIG1vZGFsaXTDoCBOQVRVUkFMIGxhIGZvcm1hdHRhemlvbmUgXCJsaXZlXCIgKGR1cmFudGUgbGEgZGlnaXRhemlvbmUpIE5PTiBmb3J6YSBpbCBwYWRkaW5nIGFcbiAqIHBpZW5hIHByZWNpc2lvbmU6IGZhcmxvIGFkIG9nbmkgdGFzdG8gYXJyb3RvbmRlcmViYmUgdmlhIGxlIGNpZnJlIGFwcGVuYSBkaWdpdGF0ZSAoZXMuIGRpZ2l0YXJlXG4gKiBcIjFcIiBzdSB1biBjYW1wbyB2dW90byByZW5kZXJpenplcmViYmUgc3ViaXRvIFwiMC4wMFwiLCBwZXJkZW5kbyBsYSBjaWZyYSkg4oCUIGlsIHBhZGRpbmcvXG4gKiBhcnJvdG9uZGFtZW50byBwaWVubyBhdnZpZW5lIHNvbG8gYWwgYGJsdXJgL2B3cml0ZVZhbHVlYC4gSW4gbW9kYWxpdMOgIEZJTkFOQ0lBTCBxdWVzdG8gcHJvYmxlbWFcbiAqIG5vbiBlc2lzdGUgKGlsIHZhbG9yZSBzaSByaWNhbGNvbGEgc2VtcHJlIGRhIHplcm8gZGFsbGUgc29sZSBjaWZyZSBkaWdpdGF0ZSwgaW5zZW5zaWJpbGUgYWxsYVxuICogZm9ybWF0dGF6aW9uZSBwcmVjZWRlbnRlKSwgcXVpbmRpIGzDrCBzaSB1c2EgZGlyZXR0YW1lbnRlIGlsIGZvcm1hdG8gcGllbm8gYWQgb2duaSB0YXN0by5cbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW3Rtd051bWVyaWNNYXNrXScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHByb3ZpZGVyczogW1xuICAgIHtcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gVG13TnVtZXJpY01hc2tEaXJlY3RpdmUpLFxuICAgICAgbXVsdGk6IHRydWUsXG4gICAgfSxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgVG13TnVtZXJpY01hc2tEaXJlY3RpdmUgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG4gIHByaXZhdGUgX29wdGlvbnM6IFJlcXVpcmVkPFRtd051bWVyaWNPcHRpb25zPiA9IHsgLi4uVE1XX05VTUVSSUNfREVGQVVMVF9PUFRJT05TIH07XG5cbiAgQElucHV0KCdvcHRpb25zJylcbiAgc2V0IG9wdGlvbnModmFsdWU6IFRtd051bWVyaWNPcHRpb25zIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5fb3B0aW9ucyA9IHsgLi4uVE1XX05VTUVSSUNfREVGQVVMVF9PUFRJT05TLCAuLi4odmFsdWUgPz8ge30pIH07XG4gICAgdGhpcy5fYXBwbHlBbGlnbm1lbnQoKTtcbiAgICB0aGlzLl9yZW5kZXJGaW5hbCh0aGlzLl92YWx1ZSk7XG4gIH1cblxuICBwcml2YXRlIF92YWx1ZTogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgX29uQ2hhbmdlOiAodmFsdWU6IG51bWJlciB8IG51bGwpID0+IHZvaWQgPSAoKSA9PiB7fTtcbiAgcHJpdmF0ZSBfb25Ub3VjaGVkOiAoKSA9PiB2b2lkID0gKCkgPT4ge307XG4gIHByaXZhdGUgX2Rpc2FibGVkID0gZmFsc2U7XG4gIC8qKlxuICAgKiBTdGF0byBQRVJTSVNURU5URSAobm9uIHJpLWRlcml2YXRvIG9nbmkgdm9sdGEgZGFsbGEgc3RyaW5nYSBnacOgIGZvcm1hdHRhdGEpOiB0cnVlIGRhbFxuICAgKiBtb21lbnRvIGluIGN1aSBsJ3V0ZW50ZSBoYSBkaWdpdGF0by9pbmNvbGxhdG8gdW4gY2FyYXR0ZXJlIGRlY2ltYWxlLCBmYWxzZSBxdWFuZG8gaWwgY2FtcG9cbiAgICogw6ggdnVvdG8gbyBxdWVsIGNhcmF0dGVyZSB2aWVuZSBjYW5jZWxsYXRvLiBOZWNlc3NhcmlvIHBlcmNow6kgaW4gZm9ybWF0byBldXJvIGB0aG91c2FuZHNgIGVcbiAgICogbCdhbHRlcm5hdGl2YSBtb2JpbGUtZnJpZW5kbHkgcGVyIGBkZWNpbWFsYCBwb3Nzb25vIGNvaW5jaWRlcmUgZW50cmFtYmkgc3UgYCcuJ2Ag4oCUIHYuXG4gICAqIGBfdG9rZW5pemVgIHBlciBjb21lIHJpc29sdmUgbCdhbWJpZ3VpdMOgIHVzYW5kbyBxdWVzdG8gc3RhdG8gaW52ZWNlIGRpIHJpLWNlcmNhcmUgXCJpbCBwcmltb1xuICAgKiBwdW50b1wiIG5lbGxhIHN0cmluZ2EgKGNoZSBwb3RyZWJiZSBlc3NlcmUgdW4gc2VwYXJhdG9yZSBkZWxsZSBtaWdsaWFpYSBnacOgIGluc2VyaXRvIGRhIG5vaSkuXG4gICAqL1xuICBwcml2YXRlIF9oYXNEZWNpbWFsU3RhdGUgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9lbGVtZW50UmVmOiBFbGVtZW50UmVmPEhUTUxJbnB1dEVsZW1lbnQ+LCBwcml2YXRlIF9yZW5kZXJlcjogUmVuZGVyZXIyKSB7XG4gICAgdGhpcy5fYXBwbHlBbGlnbm1lbnQoKTtcbiAgICAvLyBTZW56YSB1biBoaW50IGVzcGxpY2l0bywgbW9iaWxlL3RhYmxldCBtb3N0cmFubyBsYSB0YXN0aWVyYSBhbGZhbnVtZXJpY2EgY29tcGxldGEgcGVyIHVuXG4gICAgLy8gPGlucHV0PiBzZW56YSB0eXBlL2lucHV0bW9kZSDigJQgc2JhZ2xpYXRvIHBlciB1biBjYW1wbyBudW1lcmljby4gSW1wb3N0YXRvIHNvbG8gc2UgaWxcbiAgICAvLyBjb25zdW1lciBub24gaGEgZ2nDoCBtZXNzbyBpbCBwcm9wcmlvIGB0eXBlYC9gaW5wdXRtb2RlYCBuZWwgdGVtcGxhdGUgKGVzLiBgdHlwZT1cInRlbFwiYCxcbiAgICAvLyBzdWdnZXJpdG8gYW5jaGUgZGFsIFJFQURNRSBkZWxsJ29yaWdpbmFsZSBgZXFwLW51bWVyaWNgIHBlciBJb25pYykuXG4gICAgY29uc3QgZWwgPSB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgaWYgKCFlbC5oYXNBdHRyaWJ1dGUoJ2lucHV0bW9kZScpICYmICFlbC5oYXNBdHRyaWJ1dGUoJ3R5cGUnKSkge1xuICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0QXR0cmlidXRlKGVsLCAnaW5wdXRtb2RlJywgJ2RlY2ltYWwnKTtcbiAgICB9XG4gIH1cblxuICAvLyNyZWdpb24gQ29udHJvbFZhbHVlQWNjZXNzb3JcblxuICB3cml0ZVZhbHVlKHZhbHVlOiBudW1iZXIgfCBudWxsKTogdm9pZCB7XG4gICAgdGhpcy5fdmFsdWUgPSB0aGlzLl9yb3VuZFRvUHJlY2lzaW9uKHRoaXMuX2NsYW1wUmFuZ2UodmFsdWUgPT0gbnVsbCA/IG51bGwgOiBOdW1iZXIodmFsdWUpKSk7XG4gICAgdGhpcy5faGFzRGVjaW1hbFN0YXRlID0gZmFsc2U7XG4gICAgdGhpcy5fcmVuZGVyRmluYWwodGhpcy5fdmFsdWUpO1xuICB9XG5cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogKHZhbHVlOiBudW1iZXIgfCBudWxsKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5fb25DaGFuZ2UgPSBmbjtcbiAgfVxuXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5fb25Ub3VjaGVkID0gZm47XG4gIH1cblxuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLl9kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gICAgdGhpcy5fcmVuZGVyZXIuc2V0UHJvcGVydHkodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAnZGlzYWJsZWQnLCBpc0Rpc2FibGVkKTtcbiAgfVxuXG4gIC8vI2VuZHJlZ2lvblxuXG4gIEBIb3N0TGlzdGVuZXIoJ2lucHV0JywgWyckZXZlbnQnXSlcbiAgb25JbnB1dChldmVudDogSW5wdXRFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9kaXNhYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCByYXdWYWx1ZSA9IChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWU7XG4gICAgY29uc3QgY2FyZXRGcm9tRW5kID0gdGhpcy5fY2FwdHVyZUNhcmV0RnJvbUVuZCgpO1xuXG4gICAgaWYgKHRoaXMuX29wdGlvbnMuaW5wdXRNb2RlID09PSBUbXdOdW1lcmljSW5wdXRNb2RlLkZJTkFOQ0lBTCkge1xuICAgICAgdGhpcy5fdmFsdWUgPSB0aGlzLl9jbGFtcFJhbmdlKHRoaXMuX3BhcnNlRmluYW5jaWFsKHJhd1ZhbHVlKSk7XG4gICAgICB0aGlzLl9vbkNoYW5nZSh0aGlzLl92YWx1ZSk7XG4gICAgICB0aGlzLl9yZW5kZXJGaW5hbCh0aGlzLl92YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHsgZGVjaW1hbCB9ID0gdGhpcy5fb3B0aW9ucztcbiAgICAgIGNvbnN0IGluc2VydGVkVGV4dCA9IGV2ZW50LmRhdGE7XG4gICAgICAvLyBJbCBjYXJhdHRlcmUvdGVzdG8gYXBwZW5hIGRpZ2l0YXRvIG8gaW5jb2xsYXRvIChgZXZlbnQuZGF0YWApIGRpY2UgSU5FUVVJVk9DQUJJTE1FTlRFIHNlXG4gICAgICAvLyBsJ3V0ZW50ZSBzdGEgZXNwcmltZW5kbyBsJ2ludGVudG8gXCJxdWVzdG8gw6ggaWwgc2VwYXJhdG9yZSBkZWNpbWFsZVwiIOKAlCBhIGRpZmZlcmVuemEgZGlcbiAgICAgIC8vIHJpLWNlcmNhcmUgXCJpbCBwcmltbyBwdW50b1wiIG5lbGwnaW50ZXJhIHN0cmluZ2EgZ2nDoCBmb3JtYXR0YXRhLCBjaGUgaW4gZm9ybWF0byBldXJvXG4gICAgICAvLyAoYHRob3VzYW5kczogJy4nYCkgY29uZm9uZGVyZWJiZSB1biBwdW50byBkZWxsZSBtaWdsaWFpYSBnacOgIGluc2VyaXRvIGRhIG5vaSBjb24gaWxcbiAgICAgIC8vIHB1bnRvIGRlY2ltYWxlIGFwcGVuYSBkaWdpdGF0byAodi4gY29tbWVudG8gc3UgYF9oYXNEZWNpbWFsU3RhdGVgKS5cbiAgICAgIGlmIChpbnNlcnRlZFRleHQgJiYgKGluc2VydGVkVGV4dC5pbmNsdWRlcyhkZWNpbWFsKSB8fCBpbnNlcnRlZFRleHQuaW5jbHVkZXMoJy4nKSkpIHtcbiAgICAgICAgdGhpcy5faGFzRGVjaW1hbFN0YXRlID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChyYXdWYWx1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdGhpcy5faGFzRGVjaW1hbFN0YXRlID0gZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCB7IGludGVnZXJEaWdpdHMsIGRlY2ltYWxEaWdpdHMsIGhhc0RlY2ltYWxTZXBhcmF0b3IsIGlzTmVnYXRpdmUgfSA9IHRoaXMuX3Rva2VuaXplKHJhd1ZhbHVlLCB0aGlzLl9oYXNEZWNpbWFsU3RhdGUpO1xuICAgICAgdGhpcy5faGFzRGVjaW1hbFN0YXRlID0gaGFzRGVjaW1hbFNlcGFyYXRvcjtcbiAgICAgIHRoaXMuX3ZhbHVlID0gdGhpcy5fY2xhbXBSYW5nZSh0aGlzLl90b051bWJlcihpbnRlZ2VyRGlnaXRzLCBkZWNpbWFsRGlnaXRzLCBpc05lZ2F0aXZlKSk7XG4gICAgICB0aGlzLl9vbkNoYW5nZSh0aGlzLl92YWx1ZSk7XG4gICAgICB0aGlzLl9yZW5kZXJMaXZlKGludGVnZXJEaWdpdHMsIGRlY2ltYWxEaWdpdHMsIGhhc0RlY2ltYWxTZXBhcmF0b3IsIGlzTmVnYXRpdmUpO1xuICAgIH1cbiAgICB0aGlzLl9yZXN0b3JlQ2FyZXRGcm9tRW5kKGNhcmV0RnJvbUVuZCk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdibHVyJylcbiAgb25CbHVyKCk6IHZvaWQge1xuICAgIHRoaXMuX29uVG91Y2hlZCgpO1xuICAgIHRoaXMuX3ZhbHVlID0gdGhpcy5fcm91bmRUb1ByZWNpc2lvbih0aGlzLl92YWx1ZSk7XG4gICAgdGhpcy5fb25DaGFuZ2UodGhpcy5fdmFsdWUpO1xuICAgIHRoaXMuX3JlbmRlckZpbmFsKHRoaXMuX3ZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgX2FwcGx5QWxpZ25tZW50KCk6IHZvaWQge1xuICAgIHRoaXMuX3JlbmRlcmVyLnNldFN0eWxlKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ3RleHQtYWxpZ24nLCB0aGlzLl9vcHRpb25zLmFsaWduKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb2RhbGl0w6AgRklOQU5DSUFMOiBUVVRURSBsZSBjaWZyZSBkZWxsYSBzdHJpbmdhIChpbmNsdXNlIHF1ZWxsZSBnacOgIGZvcm1hdHRhdGUgZGFsIHJlbmRlclxuICAgKiBwcmVjZWRlbnRlIOKAlCBwcmVmaXNzby9taWdsaWFpYS9kZWNpbWFsaSkgdmVuZ29ubyBsZXR0ZSBjb21lIHVuIHVuaWNvIGludGVybyBpbiBjZW50ZXNpbWlcbiAgICogKG8gbmVsbGEgcGnDuSBwaWNjb2xhIHVuaXTDoCBkaSBgcHJlY2lzaW9uYCkgZSByaWRpdmlzZSBwZXIgYDEwXnByZWNpc2lvbmAg4oCUIMOoIHF1ZWxsbyBjaGUgZMOgXG4gICAqIGwnZWZmZXR0byBcInNoaWZ0IGRhIGRlc3RyYVwiIHRpcGljbyBkZWxsZSBjYXNzZSwgaW5zZW5zaWJpbGUgYSBxdWFsdW5xdWUgZm9ybWF0dGF6aW9uZVxuICAgKiBwcmVjZWRlbnRlIChhIGRpZmZlcmVuemEgZGkgTkFUVVJBTCBub24gc2VydmUgdW4gZm9ybWF0byBcImxpdmVcIiBzZXBhcmF0bykuXG4gICAqL1xuICBwcml2YXRlIF9wYXJzZUZpbmFuY2lhbChyYXdWYWx1ZTogc3RyaW5nKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgY29uc3QgeyBwcmVjaXNpb24sIGFsbG93TmVnYXRpdmUsIG51bGxhYmxlIH0gPSB0aGlzLl9vcHRpb25zO1xuICAgIGNvbnN0IGlzTmVnYXRpdmUgPSBhbGxvd05lZ2F0aXZlICYmIHRoaXMuX2hhc1R5cGVkTWludXMocmF3VmFsdWUpO1xuICAgIGNvbnN0IGRpZ2l0c09ubHkgPSByYXdWYWx1ZS5yZXBsYWNlKC9bXjAtOV0vZywgJycpO1xuICAgIGlmIChkaWdpdHNPbmx5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG51bGxhYmxlID8gbnVsbCA6IDA7XG4gICAgfVxuICAgIGNvbnN0IHVuaXRzID0gcGFyc2VJbnQoZGlnaXRzT25seSwgMTApO1xuICAgIGNvbnN0IHZhbHVlID0gdW5pdHMgLyBNYXRoLnBvdygxMCwgcHJlY2lzaW9uKTtcbiAgICByZXR1cm4gaXNOZWdhdGl2ZSA/IC12YWx1ZSA6IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIGByYXdWYWx1ZS5zdGFydHNXaXRoKCctJylgIG5vbiBiYXN0YTogaWwgc2Vnbm8gZGlnaXRhdG8gZGFsbCd1dGVudGUgZmluaXNjZSBTRU1QUkUgZG9wbyB1blxuICAgKiBldmVudHVhbGUgcHJlZmlzc28gKGVzLiBgXCIkIC01XCJgKSwgbWFpIGEgaW5pemlvIHN0cmluZ2EgYXNzb2x1dG8g4oCUIHNpIGNlcmNhIHF1aW5kaSBpbFxuICAgKiBjYXJhdHRlcmUgb3Z1bnF1ZSBuZWxsYSBzdHJpbmdhLlxuICAgKi9cbiAgcHJpdmF0ZSBfaGFzVHlwZWRNaW51cyhyYXdWYWx1ZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHJhd1ZhbHVlLmluY2x1ZGVzKCctJyk7XG4gIH1cblxuICAvKipcbiAgICogRXN0cmFlIGRhbGxhIHN0cmluZ2EgZ3JlenphIGxlIHNvbGUgY2lmcmUgaW50ZXJlL2RlY2ltYWxpIGRpZ2l0YXRlLiBVc2F0byBTT0xPIGluIG1vZGFsaXTDoFxuICAgKiBOQVRVUkFMLiBgaGFzRGVjaW1hbEhpbnRgIChzdGF0byBwZXJzaXN0ZW50ZSwgdi4gYF9oYXNEZWNpbWFsU3RhdGVgKSBkaWNlIHNlIHVuIHNlcGFyYXRvcmVcbiAgICogZGVjaW1hbGUgw6ggZ2nDoCBzdGF0byBkaWdpdGF0byBpbiB1biBrZXlzdHJva2UgcHJlY2VkZW50ZTpcbiAgICpcbiAgICogLSBgZmFsc2VgOiBuZXNzdW4gc2VwYXJhdG9yZSBhbmNvcmEg4oCUIHNpIHNjYXJ0YW5vIFRVVFRJIGkgY2FyYXR0ZXJpIG5vbi1jaWZyYSAoaW5jbHVzbyB1blxuICAgKiAgIGV2ZW50dWFsZSBwdW50byBkZWxsZSBtaWdsaWFpYSBnacOgIHByZXNlbnRlIGRhbCByZW5kZXIgcHJlY2VkZW50ZSksIHR1dHRvIGNpw7IgY2hlIHJlc3RhIMOoXG4gICAqICAgcGFydGUgaW50ZXJhLlxuICAgKiAtIGB0cnVlYDogc2kgY2VyY2EgbCdVTFRJTUEgb2Njb3JyZW56YSBkaSBgZGVjaW1hbGAgbyBgJy4nYCBuZWxsYSBzdHJpbmdhIOKAlCBtYWkgbGEgcHJpbWEuIExlXG4gICAqICAgbWlnbGlhaWEgKGFuY2hlIHF1YW5kbyBjb2luY2lkb25vIGNvbiBgJy4nYCwgZm9ybWF0byBldXJvKSBwb3Nzb25vIGNvbXBhcmlyZSBTT0xPIFBSSU1BIGRlbFxuICAgKiAgIHNlcGFyYXRvcmUgZGVjaW1hbGUgcmVhbGUgKGxhIGZvcm1hdHRhemlvbmUgbm9uIHJhZ2dydXBwYSBtYWkgbGUgY2lmcmUgZGVjaW1hbGkpLCBxdWluZGlcbiAgICogICBsJ3VsdGltYSBvY2NvcnJlbnphIMOoIHNlbXByZSBxdWVsbGEgdmVyYSwgc2VuemEgYW1iaWd1aXTDoC4gU2Ugbm9uIHNlIG5lIHRyb3ZhIHBpw7kgbmVzc3VuYVxuICAgKiAgIChsJ3V0ZW50ZSBoYSBjYW5jZWxsYXRvIGlsIHNlcGFyYXRvcmUpLCBzaSByaXRvcm5hIGEgXCJuZXNzdW4gZGVjaW1hbGVcIi5cbiAgICovXG4gIHByaXZhdGUgX3Rva2VuaXplKHJhd1ZhbHVlOiBzdHJpbmcsIGhhc0RlY2ltYWxIaW50OiBib29sZWFuKToge1xuICAgIGludGVnZXJEaWdpdHM6IHN0cmluZztcbiAgICBkZWNpbWFsRGlnaXRzOiBzdHJpbmc7XG4gICAgaGFzRGVjaW1hbFNlcGFyYXRvcjogYm9vbGVhbjtcbiAgICBpc05lZ2F0aXZlOiBib29sZWFuO1xuICB9IHtcbiAgICBjb25zdCB7IGRlY2ltYWwsIGFsbG93TmVnYXRpdmUsIHByZWNpc2lvbiB9ID0gdGhpcy5fb3B0aW9ucztcbiAgICBjb25zdCBpc05lZ2F0aXZlID0gYWxsb3dOZWdhdGl2ZSAmJiB0aGlzLl9oYXNUeXBlZE1pbnVzKHJhd1ZhbHVlKTtcblxuICAgIGlmICghaGFzRGVjaW1hbEhpbnQpIHtcbiAgICAgIHJldHVybiB7IGludGVnZXJEaWdpdHM6IHJhd1ZhbHVlLnJlcGxhY2UoL1teMC05XS9nLCAnJyksIGRlY2ltYWxEaWdpdHM6ICcnLCBoYXNEZWNpbWFsU2VwYXJhdG9yOiBmYWxzZSwgaXNOZWdhdGl2ZSB9O1xuICAgIH1cblxuICAgIGxldCBzcGxpdEluZGV4ID0gLTE7XG4gICAgZm9yIChsZXQgaSA9IHJhd1ZhbHVlLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBpZiAocmF3VmFsdWVbaV0gPT09IGRlY2ltYWwgfHwgcmF3VmFsdWVbaV0gPT09ICcuJykge1xuICAgICAgICBzcGxpdEluZGV4ID0gaTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChzcGxpdEluZGV4ID09PSAtMSkge1xuICAgICAgcmV0dXJuIHsgaW50ZWdlckRpZ2l0czogcmF3VmFsdWUucmVwbGFjZSgvW14wLTldL2csICcnKSwgZGVjaW1hbERpZ2l0czogJycsIGhhc0RlY2ltYWxTZXBhcmF0b3I6IGZhbHNlLCBpc05lZ2F0aXZlIH07XG4gICAgfVxuICAgIGNvbnN0IGludGVnZXJEaWdpdHMgPSByYXdWYWx1ZS5zbGljZSgwLCBzcGxpdEluZGV4KS5yZXBsYWNlKC9bXjAtOV0vZywgJycpO1xuICAgIGNvbnN0IGRlY2ltYWxEaWdpdHMgPSByYXdWYWx1ZS5zbGljZShzcGxpdEluZGV4ICsgMSkucmVwbGFjZSgvW14wLTldL2csICcnKS5zbGljZSgwLCBwcmVjaXNpb24pO1xuICAgIHJldHVybiB7IGludGVnZXJEaWdpdHMsIGRlY2ltYWxEaWdpdHMsIGhhc0RlY2ltYWxTZXBhcmF0b3I6IHRydWUsIGlzTmVnYXRpdmUgfTtcbiAgfVxuXG4gIHByaXZhdGUgX3RvTnVtYmVyKGludGVnZXJEaWdpdHM6IHN0cmluZywgZGVjaW1hbERpZ2l0czogc3RyaW5nLCBpc05lZ2F0aXZlOiBib29sZWFuKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgaWYgKGludGVnZXJEaWdpdHMubGVuZ3RoID09PSAwICYmIGRlY2ltYWxEaWdpdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucy5udWxsYWJsZSA/IG51bGwgOiAwO1xuICAgIH1cbiAgICBjb25zdCB2YWx1ZSA9IHBhcnNlRmxvYXQoYCR7aW50ZWdlckRpZ2l0cyB8fCAnMCd9LiR7ZGVjaW1hbERpZ2l0cyB8fCAnMCd9YCk7XG4gICAgcmV0dXJuIGlzTmVnYXRpdmUgPyAtdmFsdWUgOiB2YWx1ZTtcbiAgfVxuXG4gIC8qKiBBcHBsaWNhIHNvbG8gYGFsbG93TmVnYXRpdmVgL2BtaW5gL2BtYXhgIOKAlCBOT04gYXJyb3RvbmRhIGEgYHByZWNpc2lvbmAgKHYuIGNvbW1lbnRvIGRpIGNsYXNzZSkuICovXG4gIHByaXZhdGUgX2NsYW1wUmFuZ2UodmFsdWU6IG51bWJlciB8IG51bGwpOiBudW1iZXIgfCBudWxsIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICBjb25zdCB7IG1pbiwgbWF4LCBhbGxvd05lZ2F0aXZlIH0gPSB0aGlzLl9vcHRpb25zO1xuICAgIGxldCByZXN1bHQgPSB2YWx1ZTtcbiAgICBpZiAoIWFsbG93TmVnYXRpdmUgJiYgcmVzdWx0IDwgMCkge1xuICAgICAgcmVzdWx0ID0gLXJlc3VsdDtcbiAgICB9XG4gICAgaWYgKG1pbiAhPSBudWxsICYmIHJlc3VsdCA8IG1pbikge1xuICAgICAgcmVzdWx0ID0gbWluO1xuICAgIH1cbiAgICBpZiAobWF4ICE9IG51bGwgJiYgcmVzdWx0ID4gbWF4KSB7XG4gICAgICByZXN1bHQgPSBtYXg7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwcml2YXRlIF9yb3VuZFRvUHJlY2lzaW9uKHZhbHVlOiBudW1iZXIgfCBudWxsKTogbnVtYmVyIHwgbnVsbCB7XG4gICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgY29uc3QgZmFjdG9yID0gTWF0aC5wb3coMTAsIHRoaXMuX29wdGlvbnMucHJlY2lzaW9uKTtcbiAgICByZXR1cm4gTWF0aC5yb3VuZCh2YWx1ZSAqIGZhY3RvcikgLyBmYWN0b3I7XG4gIH1cblxuICAvKiogRm9ybWF0byBcImxpdmVcIiwgdXNhdG8gaW4gTkFUVVJBTCBkdXJhbnRlIGxhIGRpZ2l0YXppb25lOiBuZXNzdW4gcGFkZGluZy9hcnJvdG9uZGFtZW50by4gKi9cbiAgcHJpdmF0ZSBfcmVuZGVyTGl2ZShpbnRlZ2VyRGlnaXRzOiBzdHJpbmcsIGRlY2ltYWxEaWdpdHM6IHN0cmluZywgaGFzRGVjaW1hbFNlcGFyYXRvcjogYm9vbGVhbiwgaXNOZWdhdGl2ZTogYm9vbGVhbik6IHZvaWQge1xuICAgIGNvbnN0IHsgcHJlZml4LCBzdWZmaXgsIHRob3VzYW5kcywgZGVjaW1hbCwgcHJlY2lzaW9uIH0gPSB0aGlzLl9vcHRpb25zO1xuICAgIGNvbnN0IGdyb3VwZWRJbnRlZ2VyID0gaW50ZWdlckRpZ2l0cy5yZXBsYWNlKC9cXEIoPz0oXFxkezN9KSsoPyFcXGQpKS9nLCB0aG91c2FuZHMpO1xuICAgIGNvbnN0IGRlY2ltYWxTZWdtZW50ID0gcHJlY2lzaW9uID4gMCAmJiBoYXNEZWNpbWFsU2VwYXJhdG9yID8gZGVjaW1hbCArIGRlY2ltYWxEaWdpdHMgOiAnJztcbiAgICBjb25zdCBmb3JtYXR0ZWQgPSBgJHtpc05lZ2F0aXZlID8gJy0nIDogJyd9JHtwcmVmaXh9JHtncm91cGVkSW50ZWdlcn0ke2RlY2ltYWxTZWdtZW50fSR7c3VmZml4fWA7XG4gICAgdGhpcy5fcmVuZGVyZXIuc2V0UHJvcGVydHkodGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAndmFsdWUnLCBmb3JtYXR0ZWQpO1xuICB9XG5cbiAgLyoqIEZvcm1hdG8gcGllbm8gKHBhZGRpbmcgYSBgcHJlY2lzaW9uYCwgYXJyb3RvbmRhdG8pIOKAlCB1c2F0byBhIGBibHVyYC9gd3JpdGVWYWx1ZWAvb3B6aW9uaSBjYW1iaWF0ZS4gKi9cbiAgcHJpdmF0ZSBfcmVuZGVyRmluYWwodmFsdWU6IG51bWJlciB8IG51bGwpOiB2b2lkIHtcbiAgICBjb25zdCBmb3JtYXR0ZWQgPSB2YWx1ZSA9PSBudWxsID8gJycgOiB0aGlzLl9mb3JtYXRGdWxsKHZhbHVlKTtcbiAgICB0aGlzLl9yZW5kZXJlci5zZXRQcm9wZXJ0eSh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICd2YWx1ZScsIGZvcm1hdHRlZCk7XG4gIH1cblxuICBwcml2YXRlIF9mb3JtYXRGdWxsKHZhbHVlOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGNvbnN0IHsgcHJlZml4LCBzdWZmaXgsIHRob3VzYW5kcywgZGVjaW1hbCwgcHJlY2lzaW9uIH0gPSB0aGlzLl9vcHRpb25zO1xuICAgIGNvbnN0IGlzTmVnYXRpdmUgPSB2YWx1ZSA8IDA7XG4gICAgY29uc3QgZml4ZWQgPSBNYXRoLmFicyh2YWx1ZSkudG9GaXhlZChwcmVjaXNpb24pO1xuICAgIGNvbnN0IFtpbnRlZ2VyUGFydCwgZGVjaW1hbFBhcnRdID0gZml4ZWQuc3BsaXQoJy4nKTtcbiAgICBjb25zdCBncm91cGVkSW50ZWdlciA9IGludGVnZXJQYXJ0LnJlcGxhY2UoL1xcQig/PShcXGR7M30pKyg/IVxcZCkpL2csIHRob3VzYW5kcyk7XG4gICAgY29uc3QgZGVjaW1hbFNlZ21lbnQgPSBwcmVjaXNpb24gPiAwID8gZGVjaW1hbCArIGRlY2ltYWxQYXJ0IDogJyc7XG4gICAgcmV0dXJuIGAke2lzTmVnYXRpdmUgPyAnLScgOiAnJ30ke3ByZWZpeH0ke2dyb3VwZWRJbnRlZ2VyfSR7ZGVjaW1hbFNlZ21lbnR9JHtzdWZmaXh9YDtcbiAgfVxuXG4gIHByaXZhdGUgX2NhcHR1cmVDYXJldEZyb21FbmQoKTogbnVtYmVyIHtcbiAgICBjb25zdCBlbCA9IHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgICBjb25zdCBjYXJldCA9IGVsLnNlbGVjdGlvblN0YXJ0ID8/IGVsLnZhbHVlLmxlbmd0aDtcbiAgICByZXR1cm4gZWwudmFsdWUubGVuZ3RoIC0gY2FyZXQ7XG4gIH1cblxuICBwcml2YXRlIF9yZXN0b3JlQ2FyZXRGcm9tRW5kKGRpc3RhbmNlRnJvbUVuZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgZWwgPSB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgY29uc3QgcG9zaXRpb24gPSBNYXRoLm1heCgwLCBlbC52YWx1ZS5sZW5ndGggLSBkaXN0YW5jZUZyb21FbmQpO1xuICAgIC8vIElsIHJlZm9ybWF0IGF2dmllbmUgc2luY3JvbmFtZW50ZSBuZWxsbyBzdGVzc28gY2ljbG8gZGVsbCdldmVudG8gYGlucHV0YDogaWwgYnJvd3NlclxuICAgIC8vIGFwcGxpY2EgbGEgcG9zaXppb25lIGRlbCBjdXJzb3JlIFNVQklUTyBkb3BvLCBzZW56YSBiaXNvZ25vIGRpIHVuIHNldFRpbWVvdXQvbWljcm90YXNrLlxuICAgIGVsLnNldFNlbGVjdGlvblJhbmdlKHBvc2l0aW9uLCBwb3NpdGlvbik7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Public API Surface of tmw-numeric
3
+ */
4
+ export * from './lib/tmw-numeric-mask.directive';
5
+ export * from './lib/models/tmw-numeric-options.model';
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3Rtdy1udW1lcmljL3NyYy9wdWJsaWMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxrQ0FBa0MsQ0FBQztBQUNqRCxjQUFjLHdDQUF3QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIFB1YmxpYyBBUEkgU3VyZmFjZSBvZiB0bXctbnVtZXJpY1xuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vbGliL3Rtdy1udW1lcmljLW1hc2suZGlyZWN0aXZlJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy90bXctbnVtZXJpYy1vcHRpb25zLm1vZGVsJztcbiJdfQ==
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './public-api';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG13LW51bWVyaWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9wcm9qZWN0cy90bXctbnVtZXJpYy9zcmMvdG13LW51bWVyaWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWMtYXBpJztcbiJdfQ==