@nanahoshi/mona-ui 0.23.3 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +2 -0
  2. package/fesm2022/nanahoshi-mona-ui-breadcrumb.mjs +2 -0
  3. package/fesm2022/nanahoshi-mona-ui-button-group.mjs +2 -0
  4. package/fesm2022/nanahoshi-mona-ui-calendar.mjs +13 -11
  5. package/fesm2022/nanahoshi-mona-ui-card.mjs +2 -0
  6. package/fesm2022/nanahoshi-mona-ui-chart.mjs +4 -2
  7. package/fesm2022/nanahoshi-mona-ui-chip.mjs +2 -0
  8. package/fesm2022/nanahoshi-mona-ui-color-gradient.mjs +5 -3
  9. package/fesm2022/nanahoshi-mona-ui-color-palette.mjs +2 -0
  10. package/fesm2022/nanahoshi-mona-ui-color-picker.mjs +2 -0
  11. package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +2 -0
  12. package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +2 -0
  13. package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +2 -0
  14. package/fesm2022/nanahoshi-mona-ui-dialog.mjs +2 -0
  15. package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +2 -0
  16. package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +5 -3
  17. package/fesm2022/nanahoshi-mona-ui-editor.mjs +5 -3
  18. package/fesm2022/nanahoshi-mona-ui-filter.mjs +3 -1
  19. package/fesm2022/{nanahoshi-mona-ui-grid-grid-footer-row.component-BSVlcB9_.mjs → nanahoshi-mona-ui-grid-grid-footer-row.component-CnPhVIr4.mjs} +2 -2
  20. package/fesm2022/{nanahoshi-mona-ui-grid-grid-list.component-B2pBOuLa.mjs → nanahoshi-mona-ui-grid-grid-list.component-DxY6bfTX.mjs} +4 -4
  21. package/fesm2022/{nanahoshi-mona-ui-grid-grid-row.component-Buf4evf5.mjs → nanahoshi-mona-ui-grid-grid-row.component-CaO5Lae6.mjs} +3 -3
  22. package/fesm2022/{nanahoshi-mona-ui-grid-grid-virtual-list.component-1RdqLEa9.mjs → nanahoshi-mona-ui-grid-grid-virtual-list.component-jNYtqg5B.mjs} +4 -4
  23. package/fesm2022/{nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-DeRc_QcP.mjs → nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-9FtfCutf.mjs} +12 -10
  24. package/fesm2022/nanahoshi-mona-ui-grid.mjs +1 -1
  25. package/fesm2022/nanahoshi-mona-ui-i18n-icu.mjs +888 -0
  26. package/fesm2022/nanahoshi-mona-ui-i18n.mjs +337 -104
  27. package/fesm2022/nanahoshi-mona-ui-internal-list.mjs +2 -0
  28. package/fesm2022/nanahoshi-mona-ui-internal-tree.mjs +2 -0
  29. package/fesm2022/nanahoshi-mona-ui-list-box.mjs +2 -0
  30. package/fesm2022/nanahoshi-mona-ui-locales-ar-sa.mjs +401 -0
  31. package/fesm2022/nanahoshi-mona-ui-locales-de-de.mjs +399 -0
  32. package/fesm2022/nanahoshi-mona-ui-locales-es-es.mjs +399 -0
  33. package/fesm2022/nanahoshi-mona-ui-locales-fr-fr.mjs +399 -0
  34. package/fesm2022/nanahoshi-mona-ui-locales-id-id.mjs +397 -0
  35. package/fesm2022/nanahoshi-mona-ui-locales-it-it.mjs +399 -0
  36. package/fesm2022/nanahoshi-mona-ui-locales-ja-jp.mjs +397 -0
  37. package/fesm2022/nanahoshi-mona-ui-locales-ko-kr.mjs +397 -0
  38. package/fesm2022/nanahoshi-mona-ui-locales-pt-br.mjs +399 -0
  39. package/fesm2022/nanahoshi-mona-ui-locales-ru-ru.mjs +401 -0
  40. package/fesm2022/nanahoshi-mona-ui-locales-tr-tr.mjs +397 -0
  41. package/fesm2022/nanahoshi-mona-ui-locales-zh-cn.mjs +397 -0
  42. package/fesm2022/nanahoshi-mona-ui-locales-zh-tw.mjs +397 -0
  43. package/fesm2022/nanahoshi-mona-ui-locales.mjs +76 -5060
  44. package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +5 -3
  45. package/fesm2022/nanahoshi-mona-ui-notification.mjs +2 -0
  46. package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +299 -167
  47. package/fesm2022/nanahoshi-mona-ui-otp-input.mjs +2 -0
  48. package/fesm2022/nanahoshi-mona-ui-pager.mjs +5 -3
  49. package/fesm2022/nanahoshi-mona-ui-rating.mjs +4 -2
  50. package/fesm2022/nanahoshi-mona-ui-scroll-view.mjs +5 -3
  51. package/fesm2022/nanahoshi-mona-ui-sheet.mjs +2 -0
  52. package/fesm2022/nanahoshi-mona-ui-slider.mjs +2 -0
  53. package/fesm2022/nanahoshi-mona-ui-spinner.mjs +2 -0
  54. package/fesm2022/nanahoshi-mona-ui-split-button.mjs +2 -0
  55. package/fesm2022/nanahoshi-mona-ui-splitter.mjs +2 -0
  56. package/fesm2022/nanahoshi-mona-ui-stepper.mjs +2 -0
  57. package/fesm2022/nanahoshi-mona-ui-tabs.mjs +2 -0
  58. package/fesm2022/nanahoshi-mona-ui-text-box.mjs +2 -0
  59. package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +2 -0
  60. package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +2 -0
  61. package/fesm2022/nanahoshi-mona-ui-window.mjs +2 -0
  62. package/i18n/catalogs/en-US.messages.json +373 -0
  63. package/i18n/icu/package.json +4 -0
  64. package/locales/ar-sa/ar-sa.messages.json +373 -0
  65. package/locales/ar-sa/package.json +4 -0
  66. package/locales/de-de/de-de.messages.json +373 -0
  67. package/locales/de-de/package.json +4 -0
  68. package/locales/es-es/es-es.messages.json +373 -0
  69. package/locales/es-es/package.json +4 -0
  70. package/locales/fr-fr/fr-fr.messages.json +373 -0
  71. package/locales/fr-fr/package.json +4 -0
  72. package/locales/id-id/id-id.messages.json +373 -0
  73. package/locales/id-id/package.json +4 -0
  74. package/locales/it-it/it-it.messages.json +373 -0
  75. package/locales/it-it/package.json +4 -0
  76. package/locales/ja-jp/ja-jp.messages.json +373 -0
  77. package/locales/ja-jp/package.json +4 -0
  78. package/locales/ko-kr/ko-kr.messages.json +373 -0
  79. package/locales/ko-kr/package.json +4 -0
  80. package/locales/pt-br/package.json +4 -0
  81. package/locales/pt-br/pt-br.messages.json +373 -0
  82. package/locales/ru-ru/package.json +4 -0
  83. package/locales/ru-ru/ru-ru.messages.json +373 -0
  84. package/locales/tr-tr/package.json +4 -0
  85. package/locales/tr-tr/tr-tr.messages.json +373 -0
  86. package/locales/zh-cn/package.json +4 -0
  87. package/locales/zh-cn/zh-cn.messages.json +373 -0
  88. package/locales/zh-tw/package.json +4 -0
  89. package/locales/zh-tw/zh-tw.messages.json +373 -0
  90. package/package.json +111 -53
  91. package/types/nanahoshi-mona-ui-i18n-icu.d.ts +74 -0
  92. package/types/nanahoshi-mona-ui-i18n.d.ts +108 -6
  93. package/types/nanahoshi-mona-ui-locales-ar-sa.d.ts +379 -0
  94. package/types/nanahoshi-mona-ui-locales-de-de.d.ts +379 -0
  95. package/types/nanahoshi-mona-ui-locales-es-es.d.ts +379 -0
  96. package/types/nanahoshi-mona-ui-locales-fr-fr.d.ts +379 -0
  97. package/types/nanahoshi-mona-ui-locales-id-id.d.ts +379 -0
  98. package/types/nanahoshi-mona-ui-locales-it-it.d.ts +379 -0
  99. package/types/nanahoshi-mona-ui-locales-ja-jp.d.ts +379 -0
  100. package/types/nanahoshi-mona-ui-locales-ko-kr.d.ts +379 -0
  101. package/types/nanahoshi-mona-ui-locales-pt-br.d.ts +379 -0
  102. package/types/nanahoshi-mona-ui-locales-ru-ru.d.ts +379 -0
  103. package/types/nanahoshi-mona-ui-locales-tr-tr.d.ts +379 -0
  104. package/types/nanahoshi-mona-ui-locales-zh-cn.d.ts +379 -0
  105. package/types/nanahoshi-mona-ui-locales-zh-tw.d.ts +379 -0
  106. package/types/nanahoshi-mona-ui-locales.d.ts +30 -4915
  107. package/types/nanahoshi-mona-ui-numeric-text-box.d.ts +113 -37
@@ -1,19 +1,79 @@
1
- import { FocusMonitor } from '@angular/cdk/a11y';
2
1
  import { NgTemplateOutlet } from '@angular/common';
3
2
  import * as i0 from '@angular/core';
4
- import { Directive, inject, DestroyRef, ElementRef, computed, signal, contentChildren, TemplateRef, viewChild, input, output, model, effect, untracked, afterNextRender, Component } from '@angular/core';
5
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
+ import { Directive, inject, DestroyRef, ElementRef, computed, signal, contentChildren, TemplateRef, viewChild, input, output, effect, untracked, afterNextRender, model, Component } from '@angular/core';
6
4
  import * as i1 from '@angular/forms';
7
5
  import { FormsModule } from '@angular/forms';
8
6
  import { LucideChevronUp, LucideChevronDown } from '@lucide/angular';
9
7
  import { ButtonDirective } from '@nanahoshi/mona-ui/button';
8
+ import { MonaI18nService, formatNumber, getNumberSymbols, validateLocalizedDecimalEdit, validateLocalizedDecimal, validateLocalizedNumberEdit, validateLocalizedNumber } from '@nanahoshi/mona-ui/i18n';
9
+ import { TextBoxDirective } from '@nanahoshi/mona-ui/text-box';
10
+ import { FocusMonitor } from '@angular/cdk/a11y';
11
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
10
12
  import { themeControlSurfaceClasses, rxTimeout } from '@nanahoshi/mona-ui/internal';
11
13
  import { Subject, filter, switchMap, of, tap, delay, concatMap, timer, takeUntil, distinctUntilChanged, map } from 'rxjs';
12
14
  import { twMerge } from 'tailwind-merge';
13
- import { MonaI18nService, formatNumber, validateLocalizedNumber, getNumberSymbols, validateLocalizedNumberEdit } from '@nanahoshi/mona-ui/i18n';
14
- import { TextBoxDirective } from '@nanahoshi/mona-ui/text-box';
15
15
  import { cva } from 'class-variance-authority';
16
16
 
17
+ /**
18
+ * Exact arithmetic on canonical decimal strings (see `parseLocalizedDecimal`), using a `bigint` scaled by a power
19
+ * of ten. Only what the decimal text box needs: adding a step and comparing against bounds.
20
+ */
21
+ const DECIMAL_REGEX = /^(-)?(\d+)(?:\.(\d+))?$/;
22
+ /** Writes a number in plain decimal notation, never with an exponent. */
23
+ const PLAIN_NUMBER_FORMAT = new Intl.NumberFormat("en-US", { maximumFractionDigits: 100, useGrouping: false });
24
+ function toScaled(value) {
25
+ const match = DECIMAL_REGEX.exec(value);
26
+ if (!match) {
27
+ throw new Error(`"${value}" is not a decimal string.`);
28
+ }
29
+ const fraction = match[3] ?? "";
30
+ const units = BigInt(match[2] + fraction);
31
+ return { scale: fraction.length, units: match[1] ? -units : units };
32
+ }
33
+ function toCommonScale(a, b) {
34
+ const scale = Math.max(a.scale, b.scale);
35
+ return [a.units * 10n ** BigInt(scale - a.scale), b.units * 10n ** BigInt(scale - b.scale), scale];
36
+ }
37
+ function fromScaled(units, scale) {
38
+ const negative = units < 0n;
39
+ const digits = (negative ? -units : units).toString().padStart(scale + 1, "0");
40
+ const integer = digits.slice(0, digits.length - scale);
41
+ const fraction = digits.slice(digits.length - scale).replace(/0+$/, "");
42
+ const text = fraction ? `${integer}.${fraction}` : integer;
43
+ return negative ? `-${text}` : text;
44
+ }
45
+ /**
46
+ * Canonical decimal string for a decimal string or a finite number, or `null` for anything else. Leading zeros,
47
+ * trailing fraction zeros and the sign of zero are dropped, so equal values have equal strings.
48
+ */
49
+ function toDecimalString(value) {
50
+ if (value == null) {
51
+ return null;
52
+ }
53
+ if (typeof value === "number") {
54
+ return Number.isFinite(value) ? toDecimalString(PLAIN_NUMBER_FORMAT.format(value)) : null;
55
+ }
56
+ const text = value.trim();
57
+ if (!DECIMAL_REGEX.test(text)) {
58
+ return null;
59
+ }
60
+ const { scale, units } = toScaled(text);
61
+ return fromScaled(units, scale);
62
+ }
63
+ function addDecimals(a, b) {
64
+ const [x, y, scale] = toCommonScale(toScaled(a), toScaled(b));
65
+ return fromScaled(x + y, scale);
66
+ }
67
+ function subtractDecimals(a, b) {
68
+ const [x, y, scale] = toCommonScale(toScaled(a), toScaled(b));
69
+ return fromScaled(x - y, scale);
70
+ }
71
+ /** Negative when `a < b`, zero when equal, positive when `a > b`. */
72
+ function compareDecimals(a, b) {
73
+ const [x, y] = toCommonScale(toScaled(a), toScaled(b));
74
+ return x === y ? 0 : x < y ? -1 : 1;
75
+ }
76
+
17
77
  class NumericTextBoxPrefixTemplateDirective {
18
78
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NumericTextBoxPrefixTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
19
79
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.6", type: NumericTextBoxPrefixTemplateDirective, isStandalone: true, selector: "ng-template[monaNumericTextBoxPrefixTemplate]", ngImport: i0 }); }
@@ -26,6 +86,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
26
86
  }]
27
87
  }] });
28
88
 
89
+ // Generated from i18n/catalogs/en-US.messages.json by scripts/generate-locale-catalogs.ts. Do not edit.
90
+ // Edit the JSON file and run `npm run generate:locale-catalogs`.
29
91
  const NUMERIC_TEXT_BOX_DEFAULT_MESSAGES = {
30
92
  decrease: "Decrease value",
31
93
  increase: "Increase value"
@@ -135,7 +197,11 @@ const numericTextboxButtonThemeVariants = cva(`
135
197
  }
136
198
  });
137
199
 
138
- class NumericTextBoxComponent {
200
+ /**
201
+ * Typing, pasting, spinning, formatting and ARIA for a numeric input, shared by the number and decimal text boxes.
202
+ * Subclasses declare the value-typed inputs and say how to parse, compare and step their value type.
203
+ */
204
+ class NumericTextBoxBaseComponent {
139
205
  #destroyRef;
140
206
  #focusMonitor;
141
207
  #hostElementRef;
@@ -217,11 +283,6 @@ class NumericTextBoxComponent {
217
283
  */
218
284
  this.disabled = input(false, /* @ts-ignore */
219
285
  ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
220
- /**
221
- * @description Formats the value to be displayed in the input when the input is not focused.
222
- */
223
- this.formatter = input(null, /* @ts-ignore */
224
- ...(ngDevMode ? [{ debugName: "formatter" }] : /* istanbul ignore next */ []));
225
286
  /**
226
287
  * @description Emits when the inner input element is blurred.
227
288
  */
@@ -235,22 +296,12 @@ class NumericTextBoxComponent {
235
296
  */
236
297
  this.inputFocusOut = output();
237
298
  /**
238
- * @description Marks the numeric text box as invalid. When bound to a signal form field via `[formField]`,
299
+ * @description Marks the text box as invalid. When bound to a signal form field via `[formField]`,
239
300
  * this is written by the `FormField` directive.
240
301
  * @default false
241
302
  */
242
303
  this.invalid = input(false, /* @ts-ignore */
243
304
  ...(ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []));
244
- /**
245
- * @description Maximum value that can be entered.
246
- */
247
- this.maxValue = input(null, /* @ts-ignore */
248
- ...(ngDevMode ? [{ debugName: "maxValue" }] : /* istanbul ignore next */ []));
249
- /**
250
- * @description Minimum value that can be entered.
251
- */
252
- this.minValue = input(null, /* @ts-ignore */
253
- ...(ngDevMode ? [{ debugName: "minValue" }] : /* istanbul ignore next */ []));
254
305
  /**
255
306
  * @description Sets whether the input can be empty.
256
307
  */
@@ -281,23 +332,18 @@ class NumericTextBoxComponent {
281
332
  */
282
333
  this.spinners = input(true, /* @ts-ignore */
283
334
  ...(ngDevMode ? [{ debugName: "spinners" }] : /* istanbul ignore next */ []));
284
- /**
285
- * @description Step value to increment or decrement the value.
286
- */
287
- this.step = input(1, /* @ts-ignore */
288
- ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
289
335
  /**
290
336
  * @description Tab index of the input.
291
337
  */
292
338
  this.tabindex = input(0, /* @ts-ignore */
293
339
  ...(ngDevMode ? [{ debugName: "tabindex" }] : /* istanbul ignore next */ []));
294
340
  /**
295
- * @description Emitted when the numeric text box is interacted with on blur, value change, or spinner update.
341
+ * @description Emitted when the text box is interacted with on blur, value change, or spinner update.
296
342
  * The `FormField` directive listens to this to mark the field as touched.
297
343
  */
298
344
  this.touch = output();
299
345
  /**
300
- * @description Sets the touched state of the numeric text box. When bound to a signal form field via `[formField]`,
346
+ * @description Sets the touched state of the text box. When bound to a signal form field via `[formField]`,
301
347
  * this is written by the `FormField` directive.
302
348
  * @default false
303
349
  */
@@ -308,12 +354,6 @@ class NumericTextBoxComponent {
308
354
  * @default ""
309
355
  */
310
356
  this.userClass = input("", { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: "class" });
311
- /**
312
- * @description Two-way bindable current value of the numeric text box.
313
- * @default null
314
- */
315
- this.value = model(null, /* @ts-ignore */
316
- ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
317
357
  effect(() => {
318
358
  this.#i18n.localeId();
319
359
  untracked(() => {
@@ -342,50 +382,8 @@ class NumericTextBoxComponent {
342
382
  });
343
383
  this.#destroyRef.onDestroy(() => this.#focusMonitor.stopMonitoring(this.#hostElementRef.nativeElement));
344
384
  }
345
- static calculate(value, step, type) {
346
- const precision = Math.max(NumericTextBoxComponent.getPrecision(value), NumericTextBoxComponent.getPrecision(step));
347
- const factor = Math.pow(10, precision);
348
- const signFactor = type === "+" ? 1 : -1;
349
- const newValue = (value * factor + signFactor * step * factor) / factor;
350
- return precision > 0 ? parseFloat(newValue.toFixed(precision)) : newValue;
351
- }
352
- static getPrecision(value) {
353
- const valueString = value.toString();
354
- if (valueString.includes(".")) {
355
- const parts = valueString.split(".");
356
- return parts[1].length;
357
- }
358
- return 0;
359
- }
360
- static isNumeric(value) {
361
- if (value === "" || value === "-") {
362
- return true;
363
- }
364
- return ((typeof value === "number" || (typeof value === "string" && value.trim() !== "")) && !isNaN(value));
365
- }
366
385
  decrease() {
367
- const value = this.value();
368
- if (value == null) {
369
- const min = this.minValue();
370
- const max = this.maxValue();
371
- let initial = 0;
372
- if (min != null && initial < min) {
373
- initial = min;
374
- }
375
- if (max != null && initial > max) {
376
- initial = max;
377
- }
378
- this.commitNumericValue(initial);
379
- }
380
- else {
381
- let result = NumericTextBoxComponent.calculate(value, this.step(), "-");
382
- const min = this.minValue();
383
- if (min != null && result < min) {
384
- result = min;
385
- }
386
- this.commitNumericValue(result);
387
- }
388
- this.focus();
386
+ this.spinValue("-");
389
387
  }
390
388
  focus() {
391
389
  this.#focusMonitor.focusVia(this.valueTextBoxRef(), "keyboard");
@@ -394,28 +392,7 @@ class NumericTextBoxComponent {
394
392
  });
395
393
  }
396
394
  increase() {
397
- const value = this.value();
398
- if (value == null) {
399
- const min = this.minValue();
400
- const max = this.maxValue();
401
- let initial = 0;
402
- if (min != null && initial < min) {
403
- initial = min;
404
- }
405
- if (max != null && initial > max) {
406
- initial = max;
407
- }
408
- this.commitNumericValue(initial);
409
- }
410
- else {
411
- let result = NumericTextBoxComponent.calculate(value, this.step(), "+");
412
- const max = this.maxValue();
413
- if (max != null && result > max) {
414
- result = max;
415
- }
416
- this.commitNumericValue(result);
417
- }
418
- this.focus();
395
+ this.spinValue("+");
419
396
  }
420
397
  onBlur(event) {
421
398
  this.#pendingPaste = false;
@@ -434,11 +411,32 @@ class NumericTextBoxComponent {
434
411
  this.rawInputValue.set(text);
435
412
  this.valueChange$.next(text);
436
413
  }
437
- commitNumericValue(value) {
414
+ onPaste(event) {
415
+ const pastedText = event.clipboardData?.getData("text/plain");
416
+ if (pastedText == null) {
417
+ this.#pendingPaste = false;
418
+ return;
419
+ }
420
+ const inputElement = this.valueTextBoxRef()?.nativeElement;
421
+ if (!inputElement) {
422
+ this.#pendingPaste = false;
423
+ return;
424
+ }
425
+ const { value, selectionStart, selectionEnd } = inputElement;
426
+ const start = selectionStart ?? value.length;
427
+ const end = selectionEnd ?? value.length;
428
+ const proposedValue = value.slice(0, start) + pastedText + value.slice(end);
429
+ const validation = this.readLocaleText(proposedValue, this.#i18n.localeId(), this.decimals());
430
+ if (!validation.valid || validation.value === null) {
431
+ event.preventDefault();
432
+ this.#pendingPaste = false;
433
+ return;
434
+ }
435
+ this.#pendingPaste = true;
436
+ }
437
+ commitValue(value) {
438
438
  this.value.set(value);
439
- this.rawInputValue.set(this.focused() && !this.readonly()
440
- ? this.formatEditValue(value)
441
- : this.formatValueForDisplay(value));
439
+ this.rawInputValue.set(this.focused() && !this.readonly() ? this.formatEditValue(value) : this.formatValueForDisplay(value));
442
440
  this.touch.emit();
443
441
  }
444
442
  correctValue() {
@@ -453,20 +451,20 @@ class NumericTextBoxComponent {
453
451
  return false;
454
452
  }
455
453
  else if (min != null) {
456
- this.commitNumericValue(min);
454
+ this.commitValue(min);
457
455
  return true;
458
456
  }
459
457
  else {
460
- this.commitNumericValue(0);
458
+ this.commitValue(this.zeroValue);
461
459
  return true;
462
460
  }
463
461
  }
464
- if (min != null && value < min) {
465
- this.commitNumericValue(min);
462
+ if (min != null && this.compareValues(value, min) < 0) {
463
+ this.commitValue(min);
466
464
  return true;
467
465
  }
468
- if (max != null && value > max) {
469
- this.commitNumericValue(max);
466
+ if (max != null && this.compareValues(value, max) > 0) {
467
+ this.commitValue(max);
470
468
  return true;
471
469
  }
472
470
  return false;
@@ -476,7 +474,7 @@ class NumericTextBoxComponent {
476
474
  return "";
477
475
  }
478
476
  return formatNumber(value, this.#i18n.localeId(), {
479
- maximumFractionDigits: 20,
477
+ maximumFractionDigits: this.editFractionDigits,
480
478
  useGrouping: false
481
479
  });
482
480
  }
@@ -495,32 +493,6 @@ class NumericTextBoxComponent {
495
493
  useGrouping: false
496
494
  });
497
495
  }
498
- onPaste(event) {
499
- const pastedText = event.clipboardData?.getData("text/plain");
500
- if (pastedText == null) {
501
- this.#pendingPaste = false;
502
- return;
503
- }
504
- const inputElement = this.valueTextBoxRef()?.nativeElement;
505
- if (!inputElement) {
506
- this.#pendingPaste = false;
507
- return;
508
- }
509
- const { value, selectionStart, selectionEnd } = inputElement;
510
- const start = selectionStart ?? value.length;
511
- const end = selectionEnd ?? value.length;
512
- const proposedValue = value.slice(0, start) + pastedText + value.slice(end);
513
- const validation = validateLocalizedNumber(proposedValue, this.#i18n.localeId(), {
514
- mode: "locale",
515
- decimals: this.decimals()
516
- });
517
- if (!validation.valid || validation.value === null) {
518
- event.preventDefault();
519
- this.#pendingPaste = false;
520
- return;
521
- }
522
- this.#pendingPaste = true;
523
- }
524
496
  /**
525
497
  * The numpad decimal key types "." or "," depending on the keyboard layout, not the locale. Insert the
526
498
  * locale's decimal separator instead, so a de-DE layout used with an en-US locale still types a decimal.
@@ -537,7 +509,7 @@ class NumericTextBoxComponent {
537
509
  const start = selectionStart ?? value.length;
538
510
  const end = selectionEnd ?? value.length;
539
511
  const proposedValue = value.slice(0, start) + decimal + value.slice(end);
540
- if (!validateLocalizedNumberEdit(proposedValue, localeId, { decimals: this.decimals() }).valid) {
512
+ if (!this.readEditText(proposedValue, localeId, this.decimals()).valid) {
541
513
  return;
542
514
  }
543
515
  inputElement.setRangeText(decimal, start, end, "end");
@@ -549,10 +521,7 @@ class NumericTextBoxComponent {
549
521
  const isPaste = this.#pendingPaste;
550
522
  this.#pendingPaste = false;
551
523
  if (isPaste) {
552
- const validation = validateLocalizedNumber(raw, this.#i18n.localeId(), {
553
- mode: "locale",
554
- decimals: this.decimals()
555
- });
524
+ const validation = this.readLocaleText(raw, this.#i18n.localeId(), this.decimals());
556
525
  return validation.valid && validation.value !== null ? validation.value : this.value();
557
526
  }
558
527
  if (raw === "") {
@@ -561,16 +530,11 @@ class NumericTextBoxComponent {
561
530
  if (raw.trim() !== raw) {
562
531
  return this.value();
563
532
  }
564
- const edit = validateLocalizedNumberEdit(raw, this.#i18n.localeId(), {
565
- decimals: this.decimals()
566
- });
533
+ const edit = this.readEditText(raw, this.#i18n.localeId(), this.decimals());
567
534
  if (edit.valid) {
568
535
  return edit.value === null ? this.value() : edit.value;
569
536
  }
570
- const localeValidation = validateLocalizedNumber(raw, this.#i18n.localeId(), {
571
- mode: "locale",
572
- decimals: this.decimals()
573
- });
537
+ const localeValidation = this.readLocaleText(raw, this.#i18n.localeId(), this.decimals());
574
538
  if (localeValidation.valid && localeValidation.value !== null) {
575
539
  return localeValidation.value;
576
540
  }
@@ -583,8 +547,7 @@ class NumericTextBoxComponent {
583
547
  if (!isPaste) {
584
548
  this.#pendingPaste = false;
585
549
  }
586
- const insertedText = event.data ??
587
- event.dataTransfer?.getData("text/plain");
550
+ const insertedText = event.data ?? event.dataTransfer?.getData("text/plain");
588
551
  if (insertedText == null) {
589
552
  return;
590
553
  }
@@ -596,10 +559,7 @@ class NumericTextBoxComponent {
596
559
  const localeId = this.#i18n.localeId();
597
560
  const decimals = this.decimals();
598
561
  if (isPaste) {
599
- const validation = validateLocalizedNumber(proposedValue, localeId, {
600
- mode: "locale",
601
- decimals
602
- });
562
+ const validation = this.readLocaleText(proposedValue, localeId, decimals);
603
563
  if (!validation.valid || validation.value === null) {
604
564
  event.preventDefault();
605
565
  this.#pendingPaste = false;
@@ -610,10 +570,7 @@ class NumericTextBoxComponent {
610
570
  return;
611
571
  }
612
572
  this.#pendingPaste = false;
613
- const editValidation = validateLocalizedNumberEdit(proposedValue, localeId, {
614
- decimals
615
- });
616
- if (!editValidation.valid) {
573
+ if (!this.readEditText(proposedValue, localeId, decimals).valid) {
617
574
  event.preventDefault();
618
575
  }
619
576
  });
@@ -674,21 +631,196 @@ class NumericTextBoxComponent {
674
631
  }
675
632
  });
676
633
  }
677
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NumericTextBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
678
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: NumericTextBoxComponent, isStandalone: true, selector: "mona-numeric-text-box", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, decimals: { classPropertyName: "decimals", publicName: "decimals", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, formatter: { classPropertyName: "formatter", publicName: "formatter", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, nullable: { classPropertyName: "nullable", publicName: "nullable", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, spinners: { classPropertyName: "spinners", publicName: "spinners", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, tabindex: { classPropertyName: "tabindex", publicName: "tabindex", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { inputBlur: "inputBlur", inputFocus: "inputFocus", inputFocusOut: "inputFocusOut", touch: "touch", value: "valueChange" }, host: { properties: { "class": "classes()", "attr.data-disabled": "disabled() || null", "attr.data-invalid": "invalidInput() || null", "attr.data-readonly": "readonly() || null", "attr.data-required": "required() || null" } }, queries: [{ propertyName: "prefixTemplateList", predicate: NumericTextBoxPrefixTemplateDirective, read: TemplateRef, isSignal: true }], viewQueries: [{ propertyName: "valueTextBoxRef", first: true, predicate: ["valueTextBox"], descendants: true, isSignal: true }], ngImport: i0, template: "@for (prefixTemplate of prefixTemplateList(); track $index) {\n <span class=\"flex h-full flex-none flex-wrap items-center overflow-hidden border-none\">\n <ng-container *ngTemplateOutlet=\"prefixTemplate\"></ng-container>\n </span>\n}\n<input\n monaTextBox\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [type]=\"'text'\"\n [attr.inputmode]=\"decimals() > 0 ? 'decimal' : 'numeric'\"\n [readonly]=\"readonly()\"\n [tabIndex]=\"tabindex()\"\n [ngModel]=\"formattedValue()\"\n (ngModelChange)=\"applyRawValue($event)\"\n (keydown)=\"keydown$.next($event)\"\n (focus)=\"inputFocus.emit($event)\"\n (focusout)=\"inputFocusOut.emit($event)\"\n (blur)=\"onBlur($event)\"\n (beforeinput)=\"beforeInput$.next($event)\"\n (paste)=\"onPaste($event)\"\n (wheel)=\"wheel$.next($event)\"\n [size]=\"size()\"\n [class]=\"inputClasses()\"\n autocomplete=\"off\"\n role=\"spinbutton\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-invalid]=\"invalidInput() || null\"\n [attr.aria-readonly]=\"readonly()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-valuemin]=\"minValue()\"\n [attr.aria-valuemax]=\"maxValue()\"\n [attr.aria-valuetext]=\"formattedValue()\"\n [attr.data-spinners]=\"spinners()\"\n #valueTextBox />\n@if (spinners()) {\n <div [class]=\"spinButtonClasses()\">\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('+')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().increase\">\n <svg lucideChevronUp [size]=\"spinButtonIconSize()\"></svg>\n </button>\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('-')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().decrease\">\n <svg lucideChevronDown [size]=\"spinButtonIconSize()\"></svg>\n </button>\n </div>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TextBoxDirective, selector: "input[monaTextBox]", inputs: ["invalid", "rounded", "size", "touched", "class"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: ButtonDirective, selector: "button[monaButton]", inputs: ["aria-haspopup", "disabled", "iconOnly", "loading", "look", "rounded", "selected", "size", "tabindex", "type", "toggleable", "class"], outputs: ["disabledChange", "loadingChange", "lookChange", "selectedChange"] }, { kind: "component", type: LucideChevronUp, selector: "svg[lucideChevronUp]" }, { kind: "component", type: LucideChevronDown, selector: "svg[lucideChevronDown]" }] }); }
634
+ spinValue(direction) {
635
+ const value = this.value();
636
+ const min = this.minValue();
637
+ const max = this.maxValue();
638
+ if (value == null) {
639
+ let initial = this.zeroValue;
640
+ if (min != null && this.compareValues(initial, min) < 0) {
641
+ initial = min;
642
+ }
643
+ if (max != null && this.compareValues(initial, max) > 0) {
644
+ initial = max;
645
+ }
646
+ this.commitValue(initial);
647
+ }
648
+ else {
649
+ let result = this.stepValue(value, direction);
650
+ if (direction === "-" && min != null && this.compareValues(result, min) < 0) {
651
+ result = min;
652
+ }
653
+ if (direction === "+" && max != null && this.compareValues(result, max) > 0) {
654
+ result = max;
655
+ }
656
+ this.commitValue(result);
657
+ }
658
+ this.focus();
659
+ }
660
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NumericTextBoxBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
661
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.0.6", type: NumericTextBoxBaseComponent, isStandalone: true, inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, decimals: { classPropertyName: "decimals", publicName: "decimals", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, nullable: { classPropertyName: "nullable", publicName: "nullable", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, spinners: { classPropertyName: "spinners", publicName: "spinners", isSignal: true, isRequired: false, transformFunction: null }, tabindex: { classPropertyName: "tabindex", publicName: "tabindex", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { inputBlur: "inputBlur", inputFocus: "inputFocus", inputFocusOut: "inputFocusOut", touch: "touch" }, host: { properties: { "class": "classes()", "attr.data-disabled": "disabled() || null", "attr.data-invalid": "invalidInput() || null", "attr.data-readonly": "readonly() || null", "attr.data-required": "required() || null" } }, queries: [{ propertyName: "prefixTemplateList", predicate: NumericTextBoxPrefixTemplateDirective, read: TemplateRef, isSignal: true }], viewQueries: [{ propertyName: "valueTextBoxRef", first: true, predicate: ["valueTextBox"], descendants: true, isSignal: true }], ngImport: i0 }); }
679
662
  }
680
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NumericTextBoxComponent, decorators: [{
681
- type: Component,
682
- args: [{ selector: "mona-numeric-text-box", imports: [NgTemplateOutlet, TextBoxDirective, FormsModule, ButtonDirective, LucideChevronUp, LucideChevronDown], host: {
663
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NumericTextBoxBaseComponent, decorators: [{
664
+ type: Directive,
665
+ args: [{
666
+ host: {
683
667
  "[class]": "classes()",
684
668
  "[attr.data-disabled]": "disabled() || null",
685
669
  "[attr.data-invalid]": "invalidInput() || null",
686
670
  "[attr.data-readonly]": "readonly() || null",
687
671
  "[attr.data-required]": "required() || null"
688
- }, template: "@for (prefixTemplate of prefixTemplateList(); track $index) {\n <span class=\"flex h-full flex-none flex-wrap items-center overflow-hidden border-none\">\n <ng-container *ngTemplateOutlet=\"prefixTemplate\"></ng-container>\n </span>\n}\n<input\n monaTextBox\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [type]=\"'text'\"\n [attr.inputmode]=\"decimals() > 0 ? 'decimal' : 'numeric'\"\n [readonly]=\"readonly()\"\n [tabIndex]=\"tabindex()\"\n [ngModel]=\"formattedValue()\"\n (ngModelChange)=\"applyRawValue($event)\"\n (keydown)=\"keydown$.next($event)\"\n (focus)=\"inputFocus.emit($event)\"\n (focusout)=\"inputFocusOut.emit($event)\"\n (blur)=\"onBlur($event)\"\n (beforeinput)=\"beforeInput$.next($event)\"\n (paste)=\"onPaste($event)\"\n (wheel)=\"wheel$.next($event)\"\n [size]=\"size()\"\n [class]=\"inputClasses()\"\n autocomplete=\"off\"\n role=\"spinbutton\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-invalid]=\"invalidInput() || null\"\n [attr.aria-readonly]=\"readonly()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-valuemin]=\"minValue()\"\n [attr.aria-valuemax]=\"maxValue()\"\n [attr.aria-valuetext]=\"formattedValue()\"\n [attr.data-spinners]=\"spinners()\"\n #valueTextBox />\n@if (spinners()) {\n <div [class]=\"spinButtonClasses()\">\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('+')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().increase\">\n <svg lucideChevronUp [size]=\"spinButtonIconSize()\"></svg>\n </button>\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('-')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().decrease\">\n <svg lucideChevronDown [size]=\"spinButtonIconSize()\"></svg>\n </button>\n </div>\n}\n" }]
672
+ }
673
+ }]
689
674
  }], ctorParameters: () => [], propDecorators: { prefixTemplateList: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => NumericTextBoxPrefixTemplateDirective), { ...{
690
675
  read: TemplateRef
691
- }, isSignal: true }] }], valueTextBoxRef: [{ type: i0.ViewChild, args: ["valueTextBox", { isSignal: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], decimals: [{ type: i0.Input, args: [{ isSignal: true, alias: "decimals", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], formatter: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatter", required: false }] }], inputBlur: [{ type: i0.Output, args: ["inputBlur"] }], inputFocus: [{ type: i0.Output, args: ["inputFocus"] }], inputFocusOut: [{ type: i0.Output, args: ["inputFocusOut"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], minValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "minValue", required: false }] }], nullable: [{ type: i0.Input, args: [{ isSignal: true, alias: "nullable", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], spinners: [{ type: i0.Input, args: [{ isSignal: true, alias: "spinners", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], tabindex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabindex", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
676
+ }, isSignal: true }] }], valueTextBoxRef: [{ type: i0.ViewChild, args: ["valueTextBox", { isSignal: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], decimals: [{ type: i0.Input, args: [{ isSignal: true, alias: "decimals", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], inputBlur: [{ type: i0.Output, args: ["inputBlur"] }], inputFocus: [{ type: i0.Output, args: ["inputFocus"] }], inputFocusOut: [{ type: i0.Output, args: ["inputFocusOut"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], nullable: [{ type: i0.Input, args: [{ isSignal: true, alias: "nullable", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], spinners: [{ type: i0.Input, args: [{ isSignal: true, alias: "spinners", required: false }] }], tabindex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabindex", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
677
+
678
+ function warnInvalidDecimal(name, value) {
679
+ if (typeof ngDevMode !== "undefined" && ngDevMode) {
680
+ console.warn(`mona-decimal-text-box: ${name} ${JSON.stringify(value)} is not a decimal string; it is ignored.`);
681
+ }
682
+ }
683
+ function decimalInput(name) {
684
+ return value => {
685
+ const decimal = toDecimalString(value);
686
+ if (decimal === null && value != null) {
687
+ warnInvalidDecimal(name, value);
688
+ }
689
+ return decimal;
690
+ };
691
+ }
692
+ /**
693
+ * A numeric input whose value is a decimal string, for amounts a JavaScript `number` cannot hold exactly (money,
694
+ * quantities with many digits, identifiers). Typing, paste, spin buttons and bounds use exact decimal arithmetic,
695
+ * so there is no precision limit. The value is canonical: `"-1234.5"`, with `.` as the separator and no grouping,
696
+ * exponent, leading zeros or trailing fraction zeros.
697
+ */
698
+ class DecimalTextBoxComponent extends NumericTextBoxBaseComponent {
699
+ constructor() {
700
+ super();
701
+ // Intl.NumberFormat's limit: a decimal string can carry more digits than a number.
702
+ this.editFractionDigits = 100;
703
+ this.zeroValue = "0";
704
+ /**
705
+ * @description Formats the value to be displayed in the input when the input is not focused.
706
+ */
707
+ this.formatter = input(null, /* @ts-ignore */
708
+ ...(ngDevMode ? [{ debugName: "formatter" }] : /* istanbul ignore next */ []));
709
+ /**
710
+ * @description Maximum value that can be entered, as a decimal string or a number.
711
+ */
712
+ this.maxValue = input(null, { ...(ngDevMode ? { debugName: "maxValue" } : /* istanbul ignore next */ {}), transform: decimalInput("maxValue") });
713
+ /**
714
+ * @description Minimum value that can be entered, as a decimal string or a number.
715
+ */
716
+ this.minValue = input(null, { ...(ngDevMode ? { debugName: "minValue" } : /* istanbul ignore next */ {}), transform: decimalInput("minValue") });
717
+ /**
718
+ * @description Step value to increment or decrement the value, as a decimal string or a number.
719
+ * @default "1"
720
+ */
721
+ this.step = input("1", { ...(ngDevMode ? { debugName: "step" } : /* istanbul ignore next */ {}), transform: value => decimalInput("step")(value) ?? "1" });
722
+ /**
723
+ * @description Two-way bindable current value, as a canonical decimal string such as `"-1234.5"`.
724
+ * @default null
725
+ */
726
+ this.value = model(null, /* @ts-ignore */
727
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
728
+ effect(() => {
729
+ const value = this.value();
730
+ if (value != null && toDecimalString(value) === null) {
731
+ warnInvalidDecimal("value", value);
732
+ }
733
+ });
734
+ }
735
+ compareValues(a, b) {
736
+ return compareDecimals(toDecimalString(a) ?? "0", toDecimalString(b) ?? "0");
737
+ }
738
+ readEditText(text, localeId, decimals) {
739
+ return validateLocalizedDecimalEdit(text, localeId, { decimals });
740
+ }
741
+ readLocaleText(text, localeId, decimals) {
742
+ return validateLocalizedDecimal(text, localeId, { mode: "locale", decimals });
743
+ }
744
+ stepValue(value, direction) {
745
+ const current = toDecimalString(value) ?? "0";
746
+ return direction === "+" ? addDecimals(current, this.step()) : subtractDecimals(current, this.step());
747
+ }
748
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DecimalTextBoxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
749
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: DecimalTextBoxComponent, isStandalone: true, selector: "mona-decimal-text-box", inputs: { formatter: { classPropertyName: "formatter", publicName: "formatter", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, usesInheritance: true, ngImport: i0, template: "@for (prefixTemplate of prefixTemplateList(); track $index) {\n <span class=\"flex h-full flex-none flex-wrap items-center overflow-hidden border-none\">\n <ng-container *ngTemplateOutlet=\"prefixTemplate\"></ng-container>\n </span>\n}\n<input\n monaTextBox\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [type]=\"'text'\"\n [attr.inputmode]=\"decimals() > 0 ? 'decimal' : 'numeric'\"\n [readonly]=\"readonly()\"\n [tabIndex]=\"tabindex()\"\n [ngModel]=\"formattedValue()\"\n (ngModelChange)=\"applyRawValue($event)\"\n (keydown)=\"keydown$.next($event)\"\n (focus)=\"inputFocus.emit($event)\"\n (focusout)=\"inputFocusOut.emit($event)\"\n (blur)=\"onBlur($event)\"\n (beforeinput)=\"beforeInput$.next($event)\"\n (paste)=\"onPaste($event)\"\n (wheel)=\"wheel$.next($event)\"\n [size]=\"size()\"\n [class]=\"inputClasses()\"\n autocomplete=\"off\"\n role=\"spinbutton\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-invalid]=\"invalidInput() || null\"\n [attr.aria-readonly]=\"readonly()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-valuemin]=\"minValue()\"\n [attr.aria-valuemax]=\"maxValue()\"\n [attr.aria-valuetext]=\"formattedValue()\"\n [attr.data-spinners]=\"spinners()\"\n #valueTextBox />\n@if (spinners()) {\n <div [class]=\"spinButtonClasses()\">\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('+')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().increase\">\n <svg lucideChevronUp [size]=\"spinButtonIconSize()\"></svg>\n </button>\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('-')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().decrease\">\n <svg lucideChevronDown [size]=\"spinButtonIconSize()\"></svg>\n </button>\n </div>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TextBoxDirective, selector: "input[monaTextBox]", inputs: ["invalid", "rounded", "size", "touched", "class"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: ButtonDirective, selector: "button[monaButton]", inputs: ["aria-haspopup", "disabled", "iconOnly", "loading", "look", "rounded", "selected", "size", "tabindex", "type", "toggleable", "class"], outputs: ["disabledChange", "loadingChange", "lookChange", "selectedChange"] }, { kind: "component", type: LucideChevronUp, selector: "svg[lucideChevronUp]" }, { kind: "component", type: LucideChevronDown, selector: "svg[lucideChevronDown]" }] }); }
750
+ }
751
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: DecimalTextBoxComponent, decorators: [{
752
+ type: Component,
753
+ args: [{ selector: "mona-decimal-text-box", imports: [NgTemplateOutlet, TextBoxDirective, FormsModule, ButtonDirective, LucideChevronUp, LucideChevronDown], template: "@for (prefixTemplate of prefixTemplateList(); track $index) {\n <span class=\"flex h-full flex-none flex-wrap items-center overflow-hidden border-none\">\n <ng-container *ngTemplateOutlet=\"prefixTemplate\"></ng-container>\n </span>\n}\n<input\n monaTextBox\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [type]=\"'text'\"\n [attr.inputmode]=\"decimals() > 0 ? 'decimal' : 'numeric'\"\n [readonly]=\"readonly()\"\n [tabIndex]=\"tabindex()\"\n [ngModel]=\"formattedValue()\"\n (ngModelChange)=\"applyRawValue($event)\"\n (keydown)=\"keydown$.next($event)\"\n (focus)=\"inputFocus.emit($event)\"\n (focusout)=\"inputFocusOut.emit($event)\"\n (blur)=\"onBlur($event)\"\n (beforeinput)=\"beforeInput$.next($event)\"\n (paste)=\"onPaste($event)\"\n (wheel)=\"wheel$.next($event)\"\n [size]=\"size()\"\n [class]=\"inputClasses()\"\n autocomplete=\"off\"\n role=\"spinbutton\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-invalid]=\"invalidInput() || null\"\n [attr.aria-readonly]=\"readonly()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-valuemin]=\"minValue()\"\n [attr.aria-valuemax]=\"maxValue()\"\n [attr.aria-valuetext]=\"formattedValue()\"\n [attr.data-spinners]=\"spinners()\"\n #valueTextBox />\n@if (spinners()) {\n <div [class]=\"spinButtonClasses()\">\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('+')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().increase\">\n <svg lucideChevronUp [size]=\"spinButtonIconSize()\"></svg>\n </button>\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('-')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().decrease\">\n <svg lucideChevronDown [size]=\"spinButtonIconSize()\"></svg>\n </button>\n </div>\n}\n" }]
754
+ }], ctorParameters: () => [], propDecorators: { formatter: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatter", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], minValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "minValue", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
755
+
756
+ class NumericTextBoxComponent extends NumericTextBoxBaseComponent {
757
+ constructor() {
758
+ super(...arguments);
759
+ this.editFractionDigits = 20;
760
+ this.zeroValue = 0;
761
+ /**
762
+ * @description Formats the value to be displayed in the input when the input is not focused.
763
+ */
764
+ this.formatter = input(null, /* @ts-ignore */
765
+ ...(ngDevMode ? [{ debugName: "formatter" }] : /* istanbul ignore next */ []));
766
+ /**
767
+ * @description Maximum value that can be entered.
768
+ */
769
+ this.maxValue = input(null, /* @ts-ignore */
770
+ ...(ngDevMode ? [{ debugName: "maxValue" }] : /* istanbul ignore next */ []));
771
+ /**
772
+ * @description Minimum value that can be entered.
773
+ */
774
+ this.minValue = input(null, /* @ts-ignore */
775
+ ...(ngDevMode ? [{ debugName: "minValue" }] : /* istanbul ignore next */ []));
776
+ /**
777
+ * @description Step value to increment or decrement the value.
778
+ */
779
+ this.step = input(1, /* @ts-ignore */
780
+ ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
781
+ /**
782
+ * @description Two-way bindable current value of the numeric text box.
783
+ * @default null
784
+ */
785
+ this.value = model(null, /* @ts-ignore */
786
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
787
+ }
788
+ static calculate(value, step, type) {
789
+ const precision = Math.max(NumericTextBoxComponent.getPrecision(value), NumericTextBoxComponent.getPrecision(step));
790
+ const factor = Math.pow(10, precision);
791
+ const signFactor = type === "+" ? 1 : -1;
792
+ const newValue = (value * factor + signFactor * step * factor) / factor;
793
+ return precision > 0 ? parseFloat(newValue.toFixed(precision)) : newValue;
794
+ }
795
+ static getPrecision(value) {
796
+ const valueString = value.toString();
797
+ if (valueString.includes(".")) {
798
+ const parts = valueString.split(".");
799
+ return parts[1].length;
800
+ }
801
+ return 0;
802
+ }
803
+ compareValues(a, b) {
804
+ return a - b;
805
+ }
806
+ readEditText(text, localeId, decimals) {
807
+ return validateLocalizedNumberEdit(text, localeId, { decimals });
808
+ }
809
+ readLocaleText(text, localeId, decimals) {
810
+ return validateLocalizedNumber(text, localeId, { mode: "locale", decimals });
811
+ }
812
+ stepValue(value, direction) {
813
+ const result = NumericTextBoxComponent.calculate(value, this.step(), direction);
814
+ // Past the safe range a number can no longer hold every step exactly.
815
+ return Math.min(Math.max(result, Number.MIN_SAFE_INTEGER), Number.MAX_SAFE_INTEGER);
816
+ }
817
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NumericTextBoxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
818
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: NumericTextBoxComponent, isStandalone: true, selector: "mona-numeric-text-box", inputs: { formatter: { classPropertyName: "formatter", publicName: "formatter", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, usesInheritance: true, ngImport: i0, template: "@for (prefixTemplate of prefixTemplateList(); track $index) {\n <span class=\"flex h-full flex-none flex-wrap items-center overflow-hidden border-none\">\n <ng-container *ngTemplateOutlet=\"prefixTemplate\"></ng-container>\n </span>\n}\n<input\n monaTextBox\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [type]=\"'text'\"\n [attr.inputmode]=\"decimals() > 0 ? 'decimal' : 'numeric'\"\n [readonly]=\"readonly()\"\n [tabIndex]=\"tabindex()\"\n [ngModel]=\"formattedValue()\"\n (ngModelChange)=\"applyRawValue($event)\"\n (keydown)=\"keydown$.next($event)\"\n (focus)=\"inputFocus.emit($event)\"\n (focusout)=\"inputFocusOut.emit($event)\"\n (blur)=\"onBlur($event)\"\n (beforeinput)=\"beforeInput$.next($event)\"\n (paste)=\"onPaste($event)\"\n (wheel)=\"wheel$.next($event)\"\n [size]=\"size()\"\n [class]=\"inputClasses()\"\n autocomplete=\"off\"\n role=\"spinbutton\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-invalid]=\"invalidInput() || null\"\n [attr.aria-readonly]=\"readonly()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-valuemin]=\"minValue()\"\n [attr.aria-valuemax]=\"maxValue()\"\n [attr.aria-valuetext]=\"formattedValue()\"\n [attr.data-spinners]=\"spinners()\"\n #valueTextBox />\n@if (spinners()) {\n <div [class]=\"spinButtonClasses()\">\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('+')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().increase\">\n <svg lucideChevronUp [size]=\"spinButtonIconSize()\"></svg>\n </button>\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('-')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().decrease\">\n <svg lucideChevronDown [size]=\"spinButtonIconSize()\"></svg>\n </button>\n </div>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TextBoxDirective, selector: "input[monaTextBox]", inputs: ["invalid", "rounded", "size", "touched", "class"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: ButtonDirective, selector: "button[monaButton]", inputs: ["aria-haspopup", "disabled", "iconOnly", "loading", "look", "rounded", "selected", "size", "tabindex", "type", "toggleable", "class"], outputs: ["disabledChange", "loadingChange", "lookChange", "selectedChange"] }, { kind: "component", type: LucideChevronUp, selector: "svg[lucideChevronUp]" }, { kind: "component", type: LucideChevronDown, selector: "svg[lucideChevronDown]" }] }); }
819
+ }
820
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: NumericTextBoxComponent, decorators: [{
821
+ type: Component,
822
+ args: [{ selector: "mona-numeric-text-box", imports: [NgTemplateOutlet, TextBoxDirective, FormsModule, ButtonDirective, LucideChevronUp, LucideChevronDown], template: "@for (prefixTemplate of prefixTemplateList(); track $index) {\n <span class=\"flex h-full flex-none flex-wrap items-center overflow-hidden border-none\">\n <ng-container *ngTemplateOutlet=\"prefixTemplate\"></ng-container>\n </span>\n}\n<input\n monaTextBox\n [disabled]=\"disabled()\"\n [required]=\"required()\"\n [type]=\"'text'\"\n [attr.inputmode]=\"decimals() > 0 ? 'decimal' : 'numeric'\"\n [readonly]=\"readonly()\"\n [tabIndex]=\"tabindex()\"\n [ngModel]=\"formattedValue()\"\n (ngModelChange)=\"applyRawValue($event)\"\n (keydown)=\"keydown$.next($event)\"\n (focus)=\"inputFocus.emit($event)\"\n (focusout)=\"inputFocusOut.emit($event)\"\n (blur)=\"onBlur($event)\"\n (beforeinput)=\"beforeInput$.next($event)\"\n (paste)=\"onPaste($event)\"\n (wheel)=\"wheel$.next($event)\"\n [size]=\"size()\"\n [class]=\"inputClasses()\"\n autocomplete=\"off\"\n role=\"spinbutton\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.aria-invalid]=\"invalidInput() || null\"\n [attr.aria-readonly]=\"readonly()\"\n [attr.aria-required]=\"required()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-valuenow]=\"value()\"\n [attr.aria-valuemin]=\"minValue()\"\n [attr.aria-valuemax]=\"maxValue()\"\n [attr.aria-valuetext]=\"formattedValue()\"\n [attr.data-spinners]=\"spinners()\"\n #valueTextBox />\n@if (spinners()) {\n <div [class]=\"spinButtonClasses()\">\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('+')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().increase\">\n <svg lucideChevronUp [size]=\"spinButtonIconSize()\"></svg>\n </button>\n <button\n monaButton\n [disabled]=\"disabled()\"\n [tabindex]=\"-1\"\n look=\"ghost\"\n [size]=\"size()\"\n (mousedown)=\"$event.preventDefault()\"\n (pointerdown)=\"spin$.next('-')\"\n (pointerup)=\"spinStop$.next()\"\n (pointerleave)=\"spinStop$.next()\"\n [attr.aria-label]=\"messages().decrease\">\n <svg lucideChevronDown [size]=\"spinButtonIconSize()\"></svg>\n </button>\n </div>\n}\n" }]
823
+ }], propDecorators: { formatter: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatter", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], minValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "minValue", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
692
824
 
693
825
  /*
694
826
  * Public API Surface of @nanahoshi/mona-ui/numeric-text-box
@@ -698,5 +830,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImpor
698
830
  * Generated bundle index. Do not edit.
699
831
  */
700
832
 
701
- export { NUMERIC_TEXT_BOX_DEFAULT_MESSAGES, NumericTextBoxComponent, NumericTextBoxPrefixTemplateDirective };
833
+ export { DecimalTextBoxComponent, NUMERIC_TEXT_BOX_DEFAULT_MESSAGES, NumericTextBoxComponent, NumericTextBoxPrefixTemplateDirective };
702
834
  //# sourceMappingURL=nanahoshi-mona-ui-numeric-text-box.mjs.map