@seniorsistemas/angular-components 18.0.0 → 18.0.2

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.
Files changed (63) hide show
  1. package/badge/lib/badge/badge.component.d.ts +2 -1
  2. package/badge/lib/badge/badge.module.d.ts +3 -1
  3. package/esm2022/badge/lib/badge/badge.component.mjs +6 -4
  4. package/esm2022/badge/lib/badge/badge.module.mjs +6 -4
  5. package/esm2022/button/lib/button/button.component.mjs +2 -2
  6. package/esm2022/custom-fields/lib/custom-fields/custom-fields.component.mjs +10 -15
  7. package/esm2022/dynamic-form/lib/dynamic-form/components/lookup/lookup.component.mjs +2 -2
  8. package/esm2022/file-upload/lib/file-upload/file-upload.component.mjs +23 -6
  9. package/esm2022/file-upload/lib/file-upload/file-upload.module.mjs +7 -3
  10. package/esm2022/ia-insight/lib/ia-insight/components/ia-insight-card/ia-insight-card.component.mjs +1 -1
  11. package/esm2022/kanban/lib/kanban/components/kanban-item-dragging/kanban-item-dragging.component.mjs +1 -1
  12. package/esm2022/label-value/lib/label-value/label-value.component.mjs +1 -1
  13. package/esm2022/locale/lib/locale/locale.service.mjs +43 -20
  14. package/esm2022/locale/lib/locale/options/index.mjs +7 -6
  15. package/esm2022/locale/lib/locale/pipes/localized-date.pipe.mjs +1 -1
  16. package/esm2022/locale/lib/locale/pipes/localized-time.pipe.mjs +7 -7
  17. package/esm2022/numeric-mask/lib/numeric-mask/numeric-mask.directive.mjs +579 -0
  18. package/esm2022/numeric-mask/lib/numeric-mask/numeric-mask.module.mjs +16 -0
  19. package/esm2022/numeric-mask/public-api.mjs +3 -0
  20. package/esm2022/numeric-mask/seniorsistemas-angular-components-numeric-mask.mjs +5 -0
  21. package/esm2022/object-card/lib/object-card/elements/field/object-card-field.component.mjs +7 -4
  22. package/esm2022/object-card/lib/object-card/object-card.module.mjs +5 -4
  23. package/esm2022/table/lib/table/table-column/table-columns.component.mjs +1 -1
  24. package/esm2022/tooltip/lib/tooltip/tooltip.directive.mjs +26 -20
  25. package/fesm2022/seniorsistemas-angular-components-badge.mjs +10 -6
  26. package/fesm2022/seniorsistemas-angular-components-badge.mjs.map +1 -1
  27. package/fesm2022/seniorsistemas-angular-components-button.mjs +1 -1
  28. package/fesm2022/seniorsistemas-angular-components-button.mjs.map +1 -1
  29. package/fesm2022/seniorsistemas-angular-components-custom-fields.mjs +9 -14
  30. package/fesm2022/seniorsistemas-angular-components-custom-fields.mjs.map +1 -1
  31. package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs +1 -1
  32. package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs.map +1 -1
  33. package/fesm2022/seniorsistemas-angular-components-file-upload.mjs +27 -6
  34. package/fesm2022/seniorsistemas-angular-components-file-upload.mjs.map +1 -1
  35. package/fesm2022/seniorsistemas-angular-components-ia-insight.mjs +1 -1
  36. package/fesm2022/seniorsistemas-angular-components-ia-insight.mjs.map +1 -1
  37. package/fesm2022/seniorsistemas-angular-components-kanban.mjs +1 -1
  38. package/fesm2022/seniorsistemas-angular-components-kanban.mjs.map +1 -1
  39. package/fesm2022/seniorsistemas-angular-components-label-value.mjs +1 -1
  40. package/fesm2022/seniorsistemas-angular-components-label-value.mjs.map +1 -1
  41. package/fesm2022/seniorsistemas-angular-components-locale.mjs +41 -17
  42. package/fesm2022/seniorsistemas-angular-components-locale.mjs.map +1 -1
  43. package/fesm2022/seniorsistemas-angular-components-numeric-mask.mjs +599 -0
  44. package/fesm2022/seniorsistemas-angular-components-numeric-mask.mjs.map +1 -0
  45. package/fesm2022/seniorsistemas-angular-components-object-card.mjs +10 -6
  46. package/fesm2022/seniorsistemas-angular-components-object-card.mjs.map +1 -1
  47. package/fesm2022/seniorsistemas-angular-components-table.mjs +1 -1
  48. package/fesm2022/seniorsistemas-angular-components-table.mjs.map +1 -1
  49. package/fesm2022/seniorsistemas-angular-components-tooltip.mjs +23 -17
  50. package/fesm2022/seniorsistemas-angular-components-tooltip.mjs.map +1 -1
  51. package/file-upload/lib/file-upload/file-upload.component.d.ts +1 -0
  52. package/file-upload/lib/file-upload/file-upload.module.d.ts +2 -1
  53. package/locale/lib/locale/locale.service.d.ts +14 -4
  54. package/locale/lib/locale/options/index.d.ts +6 -5
  55. package/locale/lib/locale/pipes/localized-time.pipe.d.ts +2 -2
  56. package/numeric-mask/README.md +367 -0
  57. package/numeric-mask/index.d.ts +5 -0
  58. package/numeric-mask/lib/numeric-mask/numeric-mask.directive.d.ts +195 -0
  59. package/numeric-mask/lib/numeric-mask/numeric-mask.module.d.ts +7 -0
  60. package/numeric-mask/public-api.d.ts +2 -0
  61. package/object-card/lib/object-card/elements/field/object-card-field.component.d.ts +4 -1
  62. package/object-card/lib/object-card/object-card.module.d.ts +2 -1
  63. package/package.json +7 -1
@@ -0,0 +1,599 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, inject, ElementRef, Renderer2, effect, forwardRef, Directive, NgModule } from '@angular/core';
3
+ import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
4
+ import { LocaleService } from '@seniorsistemas/angular-components/locale';
5
+ import BigNumber from 'bignumber.js';
6
+
7
+ /**
8
+ * Numeric mask directive with internationalization support.
9
+ *
10
+ * Formats numeric values according to the specified locale, applying
11
+ * appropriate thousand and decimal separators, with support for negative values,
12
+ * min/max decimal places control, and scientific notation.
13
+ *
14
+ * @example
15
+ * ```html
16
+ * <input
17
+ * type="text"
18
+ * sNumericMask
19
+ * [locale]="'pt-BR'"
20
+ * [minDecimalPlaces]="2"
21
+ * [maxDecimalPlaces]="2"
22
+ * [allowNegative]="true"
23
+ * [(ngModel)]="value"
24
+ * />
25
+ * ```
26
+ */
27
+ class NumericMaskDirective {
28
+ /**
29
+ * Locale for formatting (e.g. 'pt-BR', 'en-US', 'de-DE')
30
+ * If not provided, uses the locale from LocaleService
31
+ */
32
+ locale = input(undefined);
33
+ /**
34
+ * Minimum number of decimal places to display
35
+ * @default 0
36
+ */
37
+ minDecimalPlaces = input(0);
38
+ /**
39
+ * Maximum number of decimal places allowed
40
+ * @default 10
41
+ */
42
+ maxDecimalPlaces = input(10);
43
+ /**
44
+ * Allows negative values
45
+ * @default false
46
+ */
47
+ allowNegative = input(false);
48
+ /**
49
+ * Enables scientific notation support
50
+ * @default true
51
+ */
52
+ allowScientificNotation = input(true);
53
+ /**
54
+ * Text alignment in input
55
+ * @default 'right'
56
+ */
57
+ textAlign = input('right');
58
+ /**
59
+ * Minimum value allowed
60
+ */
61
+ min = input(undefined);
62
+ /**
63
+ * Maximum value allowed
64
+ */
65
+ max = input(undefined);
66
+ elementRef = inject((ElementRef));
67
+ renderer = inject(Renderer2);
68
+ localeService = inject(LocaleService, { optional: true });
69
+ onChange = () => { };
70
+ onTouched = () => { };
71
+ decimalSeparator = ',';
72
+ thousandSeparator = '.';
73
+ currentLocale = 'pt-BR';
74
+ lastModelValue = null;
75
+ constructor() {
76
+ effect(() => {
77
+ const inputLocale = this.locale();
78
+ if (inputLocale) {
79
+ this.currentLocale = inputLocale;
80
+ this.updateSeparators();
81
+ }
82
+ });
83
+ }
84
+ ngOnInit() {
85
+ if (this.minDecimalPlaces() > this.maxDecimalPlaces()) {
86
+ throw new Error(`NumericMaskDirective: minDecimalPlaces (${this.minDecimalPlaces()}) cannot be greater than maxDecimalPlaces (${this.maxDecimalPlaces()})`);
87
+ }
88
+ if (this.locale()) {
89
+ this.currentLocale = this.locale();
90
+ this.updateSeparators();
91
+ this.setInputMode();
92
+ }
93
+ else if (this.localeService) {
94
+ this.localeService.get().subscribe(() => {
95
+ this.currentLocale = this.localeService.getLocaleOptions()?.locale || 'pt-BR';
96
+ this.updateSeparators();
97
+ this.setInputMode();
98
+ });
99
+ }
100
+ else {
101
+ this.updateSeparators();
102
+ this.setInputMode();
103
+ }
104
+ }
105
+ /**
106
+ * Listener for input events (typing)
107
+ */
108
+ onInput(event) {
109
+ const input = event.target;
110
+ let value = input.value;
111
+ value = this.normalizeSeparators(value);
112
+ this.processInputValue(value);
113
+ }
114
+ /**
115
+ * Listener for focus events (gaining focus)
116
+ */
117
+ onFocus() {
118
+ const input = this.elementRef.nativeElement;
119
+ const currentValue = input.value;
120
+ if (!currentValue || currentValue.trim() === '') {
121
+ return;
122
+ }
123
+ if (this.lastModelValue) {
124
+ const displayValue = this.lastModelValue.replace('.', this.decimalSeparator);
125
+ this.renderer.setProperty(input, 'value', displayValue);
126
+ input.select();
127
+ return;
128
+ }
129
+ const modelValue = this.toModelValue(currentValue);
130
+ if (!modelValue) {
131
+ return;
132
+ }
133
+ const displayValue = modelValue.replace('.', this.decimalSeparator);
134
+ this.renderer.setProperty(input, 'value', displayValue);
135
+ input.select();
136
+ }
137
+ /**
138
+ * Listener for blur events (focus loss)
139
+ */
140
+ onBlur() {
141
+ this.onTouched();
142
+ const currentValue = this.elementRef.nativeElement.value;
143
+ if (!currentValue || currentValue.trim() === '') {
144
+ this.onChange(null);
145
+ this.lastModelValue = null;
146
+ return;
147
+ }
148
+ const modelValue = this.toModelValue(currentValue);
149
+ if (!modelValue) {
150
+ this.onChange(null);
151
+ this.lastModelValue = null;
152
+ return;
153
+ }
154
+ this.lastModelValue = modelValue;
155
+ const displayValue = this.fromModelValue(modelValue);
156
+ this.renderer.setProperty(this.elementRef.nativeElement, 'value', displayValue);
157
+ this.onChange(modelValue);
158
+ }
159
+ /**
160
+ * Listener for paste events (clipboard)
161
+ */
162
+ onPaste(event) {
163
+ event.preventDefault();
164
+ const pastedText = event.clipboardData?.getData('text') || '';
165
+ let value = this.parseClipboardValue(pastedText);
166
+ this.processInputValue(value);
167
+ }
168
+ /**
169
+ * Listener for special keys (+ and -)
170
+ */
171
+ onKeyDown(event) {
172
+ const key = event.key;
173
+ if (key === '-' || key === '+') {
174
+ const input = this.elementRef.nativeElement;
175
+ const value = input.value;
176
+ const cursorPosition = input.selectionStart || 0;
177
+ if (key === '-' && this.allowScientificNotation()) {
178
+ const charBeforeCursor = value[cursorPosition - 1];
179
+ if (charBeforeCursor === 'e' || charBeforeCursor === 'E') {
180
+ return;
181
+ }
182
+ }
183
+ event.preventDefault();
184
+ if (!this.allowNegative()) {
185
+ return;
186
+ }
187
+ this.toggleSign(value, key === '-');
188
+ }
189
+ }
190
+ /**
191
+ * Listener for keypress to block invalid characters
192
+ */
193
+ onKeyPress(event) {
194
+ const key = event.key;
195
+ const input = this.elementRef.nativeElement;
196
+ const cursorPosition = input.selectionStart || 0;
197
+ const value = input.value;
198
+ if ((key === '-' || key === '+') && this.allowScientificNotation()) {
199
+ const charBeforeCursor = value[cursorPosition - 1];
200
+ if (charBeforeCursor === 'e' || charBeforeCursor === 'E') {
201
+ return;
202
+ }
203
+ }
204
+ if (key === '+' || key === '-') {
205
+ event.preventDefault();
206
+ return;
207
+ }
208
+ const isDigit = /^[0-9]$/.test(key);
209
+ const isLocaleDecimalSeparator = key === this.decimalSeparator;
210
+ const isOtherSeparator = (key === ',' || key === '.') && key !== this.decimalSeparator;
211
+ const isScientificNotation = (key === 'e' || key === 'E') && this.allowScientificNotation();
212
+ const isControlKey = event.ctrlKey || event.metaKey || event.altKey;
213
+ const isSpecialKey = [
214
+ 'Backspace',
215
+ 'Tab',
216
+ 'Enter',
217
+ 'Escape',
218
+ 'ArrowLeft',
219
+ 'ArrowRight',
220
+ 'Delete',
221
+ 'Home',
222
+ 'End',
223
+ ].includes(key);
224
+ if (isOtherSeparator) {
225
+ event.preventDefault();
226
+ return;
227
+ }
228
+ if (isScientificNotation) {
229
+ if (value.includes('e') || value.includes('E')) {
230
+ event.preventDefault();
231
+ return;
232
+ }
233
+ const charBeforeCursor = value[cursorPosition - 1];
234
+ if (!charBeforeCursor || !/^[0-9]$/.test(charBeforeCursor)) {
235
+ event.preventDefault();
236
+ return;
237
+ }
238
+ }
239
+ if (!isDigit && !isLocaleDecimalSeparator && !isScientificNotation && !isControlKey && !isSpecialKey) {
240
+ event.preventDefault();
241
+ }
242
+ }
243
+ /**
244
+ * Updates separators according to the locale
245
+ * @private
246
+ */
247
+ updateSeparators() {
248
+ const formatted = new Intl.NumberFormat(this.currentLocale).format(1234.5);
249
+ this.thousandSeparator = formatted[1];
250
+ this.decimalSeparator = formatted[5];
251
+ }
252
+ /**
253
+ * Processes input value and updates the input and model
254
+ * @private
255
+ */
256
+ processInputValue(value) {
257
+ if (!this.decimalSeparator || !this.thousandSeparator) {
258
+ this.updateSeparators();
259
+ }
260
+ this.renderer.setProperty(this.elementRef.nativeElement, 'value', value);
261
+ const modelValue = this.toModelValue(value);
262
+ // During typing, clear the stored model value so onFocus will recalculate
263
+ this.lastModelValue = null;
264
+ this.onChange(modelValue);
265
+ }
266
+ /**
267
+ * Sets inputmode for numeric keyboard on mobile devices
268
+ * @private
269
+ */
270
+ setInputMode() {
271
+ this.renderer.setAttribute(this.elementRef.nativeElement, 'inputmode', 'decimal');
272
+ this.renderer.setAttribute(this.elementRef.nativeElement, 'autocomplete', 'off');
273
+ }
274
+ /**
275
+ * Removes separators from a formatted value
276
+ * @private
277
+ */
278
+ removeSeparators(value) {
279
+ const thousandRegex = new RegExp(`\\${this.escapeRegex(this.thousandSeparator)}`, 'g');
280
+ return value.replace(thousandRegex, '');
281
+ }
282
+ /**
283
+ * Strips unnecessary trailing zeros from decimal part
284
+ * @private
285
+ */
286
+ stripTrailingZeros(value) {
287
+ const parts = value.split(this.decimalSeparator);
288
+ if (parts.length === 2) {
289
+ const decimalPart = parts[1].replace(/0+$/, '');
290
+ return decimalPart.length > 0 ? parts[0] + this.decimalSeparator + decimalPart : parts[0];
291
+ }
292
+ return value;
293
+ }
294
+ /**
295
+ * Normalizes separators during typing
296
+ * @private
297
+ */
298
+ normalizeSeparators(value) {
299
+ value = this.removeSeparators(value);
300
+ if (this.decimalSeparator === ',') {
301
+ value = value.replace(/\./g, ',');
302
+ }
303
+ else if (this.decimalSeparator === '.') {
304
+ value = value.replace(/,/g, '.');
305
+ }
306
+ const parts = value.split(this.decimalSeparator);
307
+ if (parts.length > 2) {
308
+ value = parts[0] + this.decimalSeparator + parts.slice(1).join('');
309
+ }
310
+ return value;
311
+ }
312
+ /**
313
+ * Escapes special characters for use in regex
314
+ * @private
315
+ */
316
+ escapeRegex(str) {
317
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
318
+ }
319
+ /**
320
+ * Truncates a number to the specified decimal places (never rounds)
321
+ * @private
322
+ */
323
+ truncateToDecimalPlaces(bigNumber, decimalPlaces) {
324
+ if (decimalPlaces < 0) {
325
+ return bigNumber;
326
+ }
327
+ const multiplier = new BigNumber(10).pow(decimalPlaces);
328
+ return bigNumber.multipliedBy(multiplier).integerValue(BigNumber.ROUND_DOWN).dividedBy(multiplier);
329
+ }
330
+ /**
331
+ * Checks if the value has excessive decimal places
332
+ * @private
333
+ */
334
+ hasExcessiveDecimalPlaces(value) {
335
+ const parts = value.split(this.decimalSeparator);
336
+ if (parts.length > 1) {
337
+ const decimalPart = parts[1].replace(/[^0-9]/g, '');
338
+ return decimalPart.length > this.maxDecimalPlaces();
339
+ }
340
+ return false;
341
+ }
342
+ /**
343
+ * Clears the input and notifies the model
344
+ * @private
345
+ */
346
+ clearInput() {
347
+ this.renderer.setProperty(this.elementRef.nativeElement, 'value', '');
348
+ this.lastModelValue = null;
349
+ this.onChange(null);
350
+ }
351
+ /**
352
+ * Parses a string value to its numeric representation, handling separators and sign
353
+ * Returns BigNumber to preserve full precision and optional number conversion
354
+ * @private
355
+ */
356
+ parseStringToValue(value) {
357
+ const isNegative = value.startsWith('-');
358
+ let numericStr = value
359
+ .replace(/^-/, '')
360
+ .replace(new RegExp(`\\${this.thousandSeparator}`, 'g'), '')
361
+ .replace(new RegExp(`\\${this.decimalSeparator}`, 'g'), '.');
362
+ if (numericStr === '.' || numericStr === '') {
363
+ numericStr = '0';
364
+ }
365
+ else if (numericStr.startsWith('.')) {
366
+ numericStr = '0' + numericStr;
367
+ }
368
+ let bigNumber = new BigNumber(numericStr);
369
+ if (bigNumber.isNaN()) {
370
+ bigNumber = new BigNumber(0);
371
+ }
372
+ if (isNegative && this.allowNegative()) {
373
+ bigNumber = bigNumber.negated();
374
+ }
375
+ return { bigNumber, numeric: bigNumber.toNumber(), isNegative };
376
+ }
377
+ /**
378
+ * Formats a numeric value according to the locale
379
+ * Truncates (never rounds) to maxDecimalPlaces for display purposes only
380
+ * @private
381
+ */
382
+ formatNumeric(numeric) {
383
+ let bigNumeric = numeric instanceof BigNumber ? numeric : new BigNumber(numeric);
384
+ const truncatedValue = this.truncateToDecimalPlaces(bigNumeric, this.maxDecimalPlaces());
385
+ const valueStr = truncatedValue.toFixed(this.maxDecimalPlaces());
386
+ let formattedValue = valueStr.replace('.', this.decimalSeparator);
387
+ const parts = formattedValue.split(this.decimalSeparator);
388
+ const integerPart = parts[0];
389
+ const decimalPart = parts[1] || '';
390
+ const formattedInteger = new Intl.NumberFormat(this.currentLocale).format(parseInt(integerPart, 10) || 0).split(this.decimalSeparator)[0];
391
+ const minDecimal = Math.max(this.minDecimalPlaces(), decimalPart.replace(/0+$/, '').length || 0);
392
+ const finalDecimal = decimalPart.padEnd(minDecimal, '0');
393
+ return formattedInteger + this.decimalSeparator + finalDecimal;
394
+ }
395
+ /**
396
+ * Formats the value according to the locale
397
+ * @private
398
+ */
399
+ formatValue(value) {
400
+ if (!value || value.trim() === '') {
401
+ return '';
402
+ }
403
+ const { numeric } = this.parseStringToValue(value);
404
+ return this.formatNumeric(numeric);
405
+ }
406
+ /**
407
+ * Converts the formatted value to the model format (international standard string)
408
+ * Always returns decimal notation, never scientific notation
409
+ * Stores the full precision value without truncation
410
+ * @private
411
+ */
412
+ toModelValue(formattedValue) {
413
+ if (!formattedValue || formattedValue.trim() === '') {
414
+ return null;
415
+ }
416
+ const { bigNumber } = this.parseStringToValue(formattedValue);
417
+ return bigNumber.toFixed();
418
+ }
419
+ /**
420
+ * Converts the model value to display format
421
+ * @private
422
+ */
423
+ fromModelValue(modelValue) {
424
+ if (modelValue === null || modelValue === undefined || modelValue === '') {
425
+ return '';
426
+ }
427
+ const bigNumber = new BigNumber(modelValue);
428
+ if (bigNumber.isNaN()) {
429
+ return '';
430
+ }
431
+ return this.formatNumeric(bigNumber);
432
+ }
433
+ /**
434
+ * Processes pasted value from clipboard
435
+ * Converts scientific notation to decimal using BigNumber
436
+ * @private
437
+ */
438
+ parseClipboardValue(text) {
439
+ if (this.allowScientificNotation() && /[eE]/.test(text)) {
440
+ try {
441
+ const bigNumeric = new BigNumber(text);
442
+ if (!bigNumeric.isNaN()) {
443
+ text = bigNumeric.toFixed();
444
+ }
445
+ }
446
+ catch {
447
+ void 0;
448
+ }
449
+ }
450
+ return this.normalizeSeparators(text);
451
+ }
452
+ /**
453
+ * Toggles the sign (- or +) of a value
454
+ * @private
455
+ */
456
+ toggleSign(value, makeNegative) {
457
+ const input = this.elementRef.nativeElement;
458
+ let newValue = value;
459
+ if (makeNegative && !newValue.startsWith('-')) {
460
+ newValue = '-' + newValue;
461
+ }
462
+ else if (!makeNegative && newValue.startsWith('-')) {
463
+ newValue = newValue.substring(1);
464
+ }
465
+ else {
466
+ return;
467
+ }
468
+ this.renderer.setProperty(input, 'value', newValue);
469
+ const modelValue = this.toModelValue(newValue);
470
+ this.lastModelValue = null;
471
+ this.onChange(modelValue);
472
+ }
473
+ writeValue(value) {
474
+ if (!this.decimalSeparator || !this.thousandSeparator) {
475
+ this.updateSeparators();
476
+ }
477
+ const hasFocus = document.activeElement === this.elementRef.nativeElement;
478
+ if (hasFocus) {
479
+ const formattedValue = this.fromModelValue(value);
480
+ const rawValue = this.stripTrailingZeros(this.removeSeparators(formattedValue));
481
+ this.renderer.setProperty(this.elementRef.nativeElement, 'value', rawValue);
482
+ }
483
+ else {
484
+ const formattedValue = this.fromModelValue(value);
485
+ this.renderer.setProperty(this.elementRef.nativeElement, 'value', formattedValue);
486
+ }
487
+ }
488
+ registerOnChange(fn) {
489
+ this.onChange = fn;
490
+ }
491
+ registerOnTouched(fn) {
492
+ this.onTouched = fn;
493
+ }
494
+ setDisabledState(isDisabled) {
495
+ this.renderer.setProperty(this.elementRef.nativeElement, 'disabled', isDisabled);
496
+ }
497
+ validate(control) {
498
+ const value = control.value;
499
+ if (!value) {
500
+ return null;
501
+ }
502
+ const numericValue = parseFloat(value);
503
+ if (isNaN(numericValue)) {
504
+ return null;
505
+ }
506
+ if (!this.allowNegative() && numericValue < 0) {
507
+ return { negativeNotAllowed: true };
508
+ }
509
+ const minValue = this.min();
510
+ if (minValue !== undefined && numericValue < minValue) {
511
+ return {
512
+ min: {
513
+ min: minValue,
514
+ actual: numericValue,
515
+ },
516
+ };
517
+ }
518
+ const maxValue = this.max();
519
+ if (maxValue !== undefined && numericValue > maxValue) {
520
+ return {
521
+ max: {
522
+ max: maxValue,
523
+ actual: numericValue,
524
+ },
525
+ };
526
+ }
527
+ const decimalPart = value.split('.')[1];
528
+ if (decimalPart && decimalPart.length > this.maxDecimalPlaces()) {
529
+ return {
530
+ excessiveDecimalPlaces: {
531
+ max: this.maxDecimalPlaces(),
532
+ actual: decimalPart.length,
533
+ },
534
+ };
535
+ }
536
+ return null;
537
+ }
538
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NumericMaskDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
539
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.14", type: NumericMaskDirective, isStandalone: true, selector: "[sNumericMask]", inputs: { locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, minDecimalPlaces: { classPropertyName: "minDecimalPlaces", publicName: "minDecimalPlaces", isSignal: true, isRequired: false, transformFunction: null }, maxDecimalPlaces: { classPropertyName: "maxDecimalPlaces", publicName: "maxDecimalPlaces", isSignal: true, isRequired: false, transformFunction: null }, allowNegative: { classPropertyName: "allowNegative", publicName: "allowNegative", isSignal: true, isRequired: false, transformFunction: null }, allowScientificNotation: { classPropertyName: "allowScientificNotation", publicName: "allowScientificNotation", isSignal: true, isRequired: false, transformFunction: null }, textAlign: { classPropertyName: "textAlign", publicName: "textAlign", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "input": "onInput($event)", "focus": "onFocus()", "blur": "onBlur()", "paste": "onPaste($event)", "keydown": "onKeyDown($event)", "keypress": "onKeyPress($event)" }, properties: { "style.text-align": "textAlign()" } }, providers: [
540
+ {
541
+ provide: NG_VALUE_ACCESSOR,
542
+ useExisting: forwardRef(() => NumericMaskDirective),
543
+ multi: true,
544
+ },
545
+ {
546
+ provide: NG_VALIDATORS,
547
+ useExisting: forwardRef(() => NumericMaskDirective),
548
+ multi: true,
549
+ },
550
+ ], ngImport: i0 });
551
+ }
552
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NumericMaskDirective, decorators: [{
553
+ type: Directive,
554
+ args: [{
555
+ selector: '[sNumericMask]',
556
+ standalone: true,
557
+ host: {
558
+ '(input)': 'onInput($event)',
559
+ '(focus)': 'onFocus()',
560
+ '(blur)': 'onBlur()',
561
+ '(paste)': 'onPaste($event)',
562
+ '(keydown)': 'onKeyDown($event)',
563
+ '(keypress)': 'onKeyPress($event)',
564
+ '[style.text-align]': 'textAlign()',
565
+ },
566
+ providers: [
567
+ {
568
+ provide: NG_VALUE_ACCESSOR,
569
+ useExisting: forwardRef(() => NumericMaskDirective),
570
+ multi: true,
571
+ },
572
+ {
573
+ provide: NG_VALIDATORS,
574
+ useExisting: forwardRef(() => NumericMaskDirective),
575
+ multi: true,
576
+ },
577
+ ],
578
+ }]
579
+ }], ctorParameters: () => [] });
580
+
581
+ class CurrencyMaskModule {
582
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CurrencyMaskModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
583
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: CurrencyMaskModule, imports: [NumericMaskDirective], exports: [NumericMaskDirective] });
584
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CurrencyMaskModule });
585
+ }
586
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CurrencyMaskModule, decorators: [{
587
+ type: NgModule,
588
+ args: [{
589
+ imports: [NumericMaskDirective],
590
+ exports: [NumericMaskDirective],
591
+ }]
592
+ }] });
593
+
594
+ /**
595
+ * Generated bundle index. Do not edit.
596
+ */
597
+
598
+ export { CurrencyMaskModule, NumericMaskDirective };
599
+ //# sourceMappingURL=seniorsistemas-angular-components-numeric-mask.mjs.map