ng-zorro-antd-input-number.mjs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. import { FocusMonitor } from '@angular/cdk/a11y';
  2. import { Directionality } from '@angular/cdk/bidi';
  3. import { ENTER, DOWN_ARROW, UP_ARROW } from '@angular/cdk/keycodes';
  4. import { NgTemplateOutlet } from '@angular/common';
  5. import * as i0 from '@angular/core';
  6. import { input, numberAttribute, booleanAttribute, output, inject, viewChild, ElementRef, Injector, signal, linkedSignal, contentChild, computed, DestroyRef, afterNextRender, untracked, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
  7. import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
  8. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  9. import { NzFormStatusService, NzFormItemFeedbackIconComponent } from 'ng-zorro-antd/core/form';
  10. import { isNotNil, getStatusClassNames, isNil } from 'ng-zorro-antd/core/util';
  11. import * as i2 from 'ng-zorro-antd/icon';
  12. import { NzIconModule } from 'ng-zorro-antd/icon';
  13. import { NzInputPrefixDirective, NzInputSuffixDirective, NzInputAddonBeforeDirective, NzInputAddonAfterDirective } from 'ng-zorro-antd/input';
  14. import * as i1 from 'ng-zorro-antd/space';
  15. import { NZ_SPACE_COMPACT_SIZE, NZ_SPACE_COMPACT_ITEM_TYPE, NzSpaceCompactItemDirective } from 'ng-zorro-antd/space';
  16. /**
  17. * Use of this source code is governed by an MIT-style license that can be
  18. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  19. */
  20. class NzInputNumberComponent {
  21. nzId = input(null);
  22. nzSize = input('default');
  23. nzPlaceHolder = input(null);
  24. nzStatus = input('');
  25. nzStep = input(1, { transform: numberAttribute });
  26. nzMin = input(Number.MIN_SAFE_INTEGER, { transform: numberAttribute });
  27. nzMax = input(Number.MAX_SAFE_INTEGER, { transform: numberAttribute });
  28. nzPrecision = input(null);
  29. nzParser = input();
  30. nzFormatter = input();
  31. nzDisabled = input(false, { transform: booleanAttribute });
  32. nzReadOnly = input(false, { transform: booleanAttribute });
  33. nzAutoFocus = input(false, { transform: booleanAttribute });
  34. nzBordered = input(true, { transform: booleanAttribute });
  35. nzKeyboard = input(true, { transform: booleanAttribute });
  36. nzControls = input(true, { transform: booleanAttribute });
  37. nzBlur = output();
  38. nzFocus = output();
  39. nzOnStep = output();
  40. onChange = () => { };
  41. onTouched = () => { };
  42. isDisabledFirstChange = true;
  43. compactSize = inject(NZ_SPACE_COMPACT_SIZE, { optional: true });
  44. inputRef = viewChild.required('input');
  45. hostRef = viewChild('inputNumberHost');
  46. elementRef = inject(ElementRef);
  47. injector = inject(Injector);
  48. focusMonitor = inject(FocusMonitor);
  49. directionality = inject(Directionality);
  50. nzFormStatusService = inject(NzFormStatusService, { optional: true });
  51. autoStepTimer = null;
  52. defaultFormater = (value) => {
  53. const precision = this.nzPrecision();
  54. if (isNotNil(precision)) {
  55. return value.toFixed(precision);
  56. }
  57. return value.toString();
  58. };
  59. value = signal(null);
  60. displayValue = signal('');
  61. dir = toSignal(this.directionality.change, { initialValue: this.directionality.value });
  62. focused = signal(false);
  63. hasFeedback = signal(false);
  64. finalStatus = linkedSignal(() => this.nzStatus());
  65. finalDisabled = linkedSignal(() => this.nzDisabled());
  66. prefix = contentChild(NzInputPrefixDirective);
  67. suffix = contentChild(NzInputSuffixDirective);
  68. addonBefore = contentChild(NzInputAddonBeforeDirective);
  69. addonAfter = contentChild(NzInputAddonAfterDirective);
  70. hasAffix = computed(() => !!this.prefix() || !!this.suffix() || this.hasFeedback());
  71. hasAddon = computed(() => !!this.addonBefore() || !!this.addonAfter());
  72. class = computed(() => {
  73. if (this.hasAddon()) {
  74. return this.groupWrapperClass();
  75. }
  76. if (this.hasAffix()) {
  77. return this.affixWrapperClass();
  78. }
  79. return this.inputNumberClass();
  80. });
  81. inputNumberClass = computed(() => {
  82. return {
  83. 'ant-input-number': true,
  84. 'ant-input-number-lg': this.finalSize() === 'large',
  85. 'ant-input-number-sm': this.finalSize() === 'small',
  86. 'ant-input-number-disabled': this.finalDisabled(),
  87. 'ant-input-number-readonly': this.nzReadOnly(),
  88. 'ant-input-number-borderless': !this.nzBordered(),
  89. 'ant-input-number-focused': this.focused(),
  90. 'ant-input-number-rtl': this.dir() === 'rtl',
  91. 'ant-input-number-in-form-item': !!this.nzFormStatusService,
  92. 'ant-input-number-out-of-range': this.value() !== null && !isInRange(this.value(), this.nzMin(), this.nzMax()),
  93. ...getStatusClassNames('ant-input-number', this.finalStatus(), this.hasFeedback())
  94. };
  95. });
  96. affixWrapperClass = computed(() => {
  97. return {
  98. 'ant-input-number-affix-wrapper': true,
  99. 'ant-input-number-affix-wrapper-disabled': this.finalDisabled(),
  100. 'ant-input-number-affix-wrapper-readonly': this.nzReadOnly(),
  101. 'ant-input-number-affix-wrapper-borderless': !this.nzBordered(),
  102. 'ant-input-number-affix-wrapper-focused': this.focused(),
  103. 'ant-input-number-affix-wrapper-rtl': this.dir() === 'rtl',
  104. ...getStatusClassNames('ant-input-number-affix-wrapper', this.finalStatus(), this.hasFeedback())
  105. };
  106. });
  107. groupWrapperClass = computed(() => {
  108. return {
  109. 'ant-input-number-group-wrapper': true,
  110. 'ant-input-number-group-wrapper-rtl': this.dir() === 'rtl',
  111. ...getStatusClassNames('ant-input-number-group-wrapper', this.finalStatus(), this.hasFeedback())
  112. };
  113. });
  114. finalSize = computed(() => {
  115. if (this.compactSize) {
  116. return this.compactSize();
  117. }
  118. return this.nzSize();
  119. });
  120. upDisabled = computed(() => {
  121. return !isNil(this.value()) && this.value() >= this.nzMax();
  122. });
  123. downDisabled = computed(() => {
  124. return !isNil(this.value()) && this.value() <= this.nzMin();
  125. });
  126. constructor() {
  127. const destroyRef = inject(DestroyRef);
  128. afterNextRender(() => {
  129. const hostRef = this.hostRef();
  130. const element = hostRef ? hostRef : this.elementRef;
  131. this.focusMonitor
  132. .monitor(element, true)
  133. .pipe(takeUntilDestroyed(destroyRef))
  134. .subscribe(origin => {
  135. this.focused.set(!!origin);
  136. if (origin) {
  137. this.nzFocus.emit();
  138. }
  139. else {
  140. this.fixValue();
  141. this.onTouched();
  142. this.nzBlur.emit();
  143. }
  144. });
  145. destroyRef.onDestroy(() => {
  146. this.focusMonitor.stopMonitoring(element);
  147. });
  148. });
  149. this.nzFormStatusService?.formStatusChanges.pipe(takeUntilDestroyed()).subscribe(({ status, hasFeedback }) => {
  150. this.finalStatus.set(status);
  151. this.hasFeedback.set(hasFeedback);
  152. });
  153. }
  154. ngOnInit() {
  155. if (this.nzAutoFocus()) {
  156. afterNextRender(() => this.focus(), { injector: this.injector });
  157. }
  158. }
  159. writeValue(value) {
  160. untracked(() => {
  161. this.value.set(value);
  162. this.setValue(value);
  163. });
  164. }
  165. registerOnChange(fn) {
  166. this.onChange = fn;
  167. }
  168. registerOnTouched(fn) {
  169. this.onTouched = fn;
  170. }
  171. setDisabledState(disabled) {
  172. untracked(() => {
  173. this.finalDisabled.set((this.isDisabledFirstChange && this.nzDisabled()) || disabled);
  174. });
  175. this.isDisabledFirstChange = false;
  176. }
  177. focus() {
  178. this.inputRef().nativeElement.focus();
  179. }
  180. blur() {
  181. this.inputRef().nativeElement.blur();
  182. }
  183. step(event, up) {
  184. // Ignore step since out of range
  185. if ((up && this.upDisabled()) || (!up && this.downDisabled())) {
  186. return;
  187. }
  188. // When hold the shift key, the step is 10 times
  189. let step = event.shiftKey ? this.nzStep() * 10 : this.nzStep();
  190. if (!up) {
  191. step = -step;
  192. }
  193. const places = getDecimalPlaces(step);
  194. const multiple = 10 ** places;
  195. const nextValue = getRangeValue(
  196. // Convert floating point numbers to integers to avoid floating point math errors
  197. (Math.round((this.value() || 0) * multiple) + Math.round(step * multiple)) / multiple, this.nzMin(), this.nzMax(), this.nzPrecision());
  198. this.setValue(nextValue);
  199. this.nzOnStep.emit({
  200. type: up ? 'up' : 'down',
  201. value: this.value(),
  202. offset: this.nzStep()
  203. });
  204. this.focus();
  205. }
  206. setValue(value) {
  207. const formatter = this.nzFormatter() ?? this.defaultFormater;
  208. const precision = this.nzPrecision();
  209. if (isNotNil(precision)) {
  210. value &&= +value.toFixed(precision);
  211. }
  212. const formatedValue = value === null ? '' : formatter(value);
  213. this.displayValue.set(formatedValue);
  214. this.updateValue(value);
  215. }
  216. setValueByTyping(value) {
  217. if (value === '') {
  218. this.displayValue.set('');
  219. this.updateValue(null);
  220. return;
  221. }
  222. const parser = this.nzParser() ?? defaultParser;
  223. const parsedValue = parser(value);
  224. if (isNotCompleteNumber(value) || Number.isNaN(parsedValue)) {
  225. this.displayValue.set(value);
  226. return;
  227. }
  228. const formattedValue = this.nzFormatter()?.(parsedValue) ?? parsedValue.toString();
  229. this.displayValue.set(formattedValue);
  230. if (!isInRange(parsedValue, this.nzMin(), this.nzMax())) {
  231. return;
  232. }
  233. this.updateValue(parsedValue);
  234. }
  235. updateValue(value) {
  236. if (this.value() !== value) {
  237. this.value.set(value);
  238. this.onChange(value);
  239. }
  240. }
  241. fixValue() {
  242. const displayValue = this.displayValue();
  243. if (displayValue === '') {
  244. return;
  245. }
  246. const parser = this.nzParser() ?? defaultParser;
  247. let fixedValue = parser(displayValue);
  248. // If parsing fails, revert to the previous value
  249. if (Number.isNaN(fixedValue)) {
  250. fixedValue = this.value();
  251. }
  252. else {
  253. const precision = this.nzPrecision();
  254. // fix precision
  255. if (isNotNil(precision) && getDecimalPlaces(fixedValue) !== precision) {
  256. fixedValue = +fixedValue.toFixed(precision);
  257. }
  258. // fix range
  259. if (!isInRange(fixedValue, this.nzMin(), this.nzMax())) {
  260. fixedValue = getRangeValue(fixedValue, this.nzMin(), this.nzMax(), precision);
  261. }
  262. }
  263. this.setValue(fixedValue);
  264. }
  265. stopAutoStep() {
  266. if (this.autoStepTimer !== null) {
  267. clearTimeout(this.autoStepTimer);
  268. this.autoStepTimer = null;
  269. }
  270. }
  271. onStepMouseDown(event, up) {
  272. event.preventDefault();
  273. this.stopAutoStep();
  274. this.step(event, up);
  275. // Loop step for interval
  276. const loopStep = () => {
  277. this.step(event, up);
  278. this.autoStepTimer = setTimeout(loopStep, STEP_INTERVAL);
  279. };
  280. // First time press will wait some time to trigger loop step update
  281. this.autoStepTimer = setTimeout(loopStep, STEP_DELAY);
  282. }
  283. onKeyDown(event) {
  284. switch (event.keyCode) {
  285. case UP_ARROW:
  286. event.preventDefault();
  287. this.nzKeyboard() && this.step(event, true);
  288. break;
  289. case DOWN_ARROW:
  290. event.preventDefault();
  291. this.nzKeyboard() && this.step(event, false);
  292. break;
  293. case ENTER:
  294. this.fixValue();
  295. break;
  296. }
  297. }
  298. onInput(value) {
  299. this.setValueByTyping(value);
  300. }
  301. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzInputNumberComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
  302. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.2", type: NzInputNumberComponent, isStandalone: true, selector: "nz-input-number", inputs: { nzId: { classPropertyName: "nzId", publicName: "nzId", isSignal: true, isRequired: false, transformFunction: null }, nzSize: { classPropertyName: "nzSize", publicName: "nzSize", isSignal: true, isRequired: false, transformFunction: null }, nzPlaceHolder: { classPropertyName: "nzPlaceHolder", publicName: "nzPlaceHolder", isSignal: true, isRequired: false, transformFunction: null }, nzStatus: { classPropertyName: "nzStatus", publicName: "nzStatus", isSignal: true, isRequired: false, transformFunction: null }, nzStep: { classPropertyName: "nzStep", publicName: "nzStep", isSignal: true, isRequired: false, transformFunction: null }, nzMin: { classPropertyName: "nzMin", publicName: "nzMin", isSignal: true, isRequired: false, transformFunction: null }, nzMax: { classPropertyName: "nzMax", publicName: "nzMax", isSignal: true, isRequired: false, transformFunction: null }, nzPrecision: { classPropertyName: "nzPrecision", publicName: "nzPrecision", isSignal: true, isRequired: false, transformFunction: null }, nzParser: { classPropertyName: "nzParser", publicName: "nzParser", isSignal: true, isRequired: false, transformFunction: null }, nzFormatter: { classPropertyName: "nzFormatter", publicName: "nzFormatter", isSignal: true, isRequired: false, transformFunction: null }, nzDisabled: { classPropertyName: "nzDisabled", publicName: "nzDisabled", isSignal: true, isRequired: false, transformFunction: null }, nzReadOnly: { classPropertyName: "nzReadOnly", publicName: "nzReadOnly", isSignal: true, isRequired: false, transformFunction: null }, nzAutoFocus: { classPropertyName: "nzAutoFocus", publicName: "nzAutoFocus", isSignal: true, isRequired: false, transformFunction: null }, nzBordered: { classPropertyName: "nzBordered", publicName: "nzBordered", isSignal: true, isRequired: false, transformFunction: null }, nzKeyboard: { classPropertyName: "nzKeyboard", publicName: "nzKeyboard", isSignal: true, isRequired: false, transformFunction: null }, nzControls: { classPropertyName: "nzControls", publicName: "nzControls", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nzBlur: "nzBlur", nzFocus: "nzFocus", nzOnStep: "nzOnStep" }, host: { listeners: { "keydown": "onKeyDown($event)" }, properties: { "class": "class()" } }, providers: [
  303. {
  304. provide: NG_VALUE_ACCESSOR,
  305. useExisting: forwardRef(() => NzInputNumberComponent),
  306. multi: true
  307. },
  308. { provide: NZ_SPACE_COMPACT_ITEM_TYPE, useValue: 'input-number' }
  309. ], queries: [{ propertyName: "prefix", first: true, predicate: NzInputPrefixDirective, descendants: true, isSignal: true }, { propertyName: "suffix", first: true, predicate: NzInputSuffixDirective, descendants: true, isSignal: true }, { propertyName: "addonBefore", first: true, predicate: NzInputAddonBeforeDirective, descendants: true, isSignal: true }, { propertyName: "addonAfter", first: true, predicate: NzInputAddonAfterDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["input"], descendants: true, isSignal: true }, { propertyName: "hostRef", first: true, predicate: ["inputNumberHost"], descendants: true, isSignal: true }], exportAs: ["nzInputNumber"], hostDirectives: [{ directive: i1.NzSpaceCompactItemDirective }], ngImport: i0, template: `
  310. @if (hasAddon()) {
  311. <ng-template [ngTemplateOutlet]="inputNumberWithAddonInner" />
  312. } @else if (hasAffix()) {
  313. <ng-template [ngTemplateOutlet]="inputNumberWithAffixInner" />
  314. } @else {
  315. <ng-template [ngTemplateOutlet]="inputNumberInner" />
  316. }
  317. <ng-template #inputNumberWithAddonInner>
  318. <div class="ant-input-number-wrapper ant-input-number-group">
  319. @if (addonBefore()) {
  320. <div class="ant-input-number-group-addon">
  321. <ng-content select="[nzInputAddonBefore]"></ng-content>
  322. </div>
  323. }
  324. @if (hasAffix()) {
  325. <ng-template [ngTemplateOutlet]="inputNumberWithAffix" />
  326. } @else {
  327. <ng-template [ngTemplateOutlet]="inputNumber" />
  328. }
  329. @if (addonAfter()) {
  330. <div class="ant-input-number-group-addon">
  331. <ng-content select="[nzInputAddonAfter]"></ng-content>
  332. </div>
  333. }
  334. </div>
  335. </ng-template>
  336. <ng-template #inputNumberWithAffix>
  337. <div [class]="affixWrapperClass()">
  338. <ng-template [ngTemplateOutlet]="inputNumberWithAffixInner" />
  339. </div>
  340. </ng-template>
  341. <ng-template #inputNumberWithAffixInner>
  342. @if (prefix()) {
  343. <span class="ant-input-number-prefix">
  344. <ng-content select="[nzInputPrefix]"></ng-content>
  345. </span>
  346. }
  347. <ng-template [ngTemplateOutlet]="inputNumber" />
  348. @if (suffix() || hasFeedback()) {
  349. <span class="ant-input-number-suffix">
  350. <ng-content select="[nzInputSuffix]"></ng-content>
  351. @if (hasFeedback() && finalStatus()) {
  352. <nz-form-item-feedback-icon [status]="finalStatus()" />
  353. }
  354. </span>
  355. }
  356. </ng-template>
  357. <ng-template #inputNumber>
  358. <div #inputNumberHost [class]="inputNumberClass()">
  359. <ng-template [ngTemplateOutlet]="inputNumberInner" />
  360. </div>
  361. </ng-template>
  362. <ng-template #inputNumberInner>
  363. @if (nzControls()) {
  364. <div #handlers class="ant-input-number-handler-wrap" (mouseup)="stopAutoStep()" (mouseleave)="stopAutoStep()">
  365. <span
  366. role="button"
  367. unselectable="on"
  368. class="ant-input-number-handler ant-input-number-handler-up"
  369. [class.ant-input-number-handler-up-disabled]="upDisabled()"
  370. [attr.aria-disabled]="upDisabled()"
  371. (mousedown)="onStepMouseDown($event, true)"
  372. >
  373. <ng-content select="[nzInputNumberUpIcon]">
  374. <nz-icon nzType="up" class="ant-input-number-handler-up-inner" />
  375. </ng-content>
  376. </span>
  377. <span
  378. role="button"
  379. unselectable="on"
  380. class="ant-input-number-handler ant-input-number-handler-down"
  381. [class.ant-input-number-handler-down-disabled]="downDisabled()"
  382. [attr.aria-disabled]="downDisabled()"
  383. (mousedown)="onStepMouseDown($event, false)"
  384. >
  385. <ng-content select="[nzInputNumberDownIcon]">
  386. <nz-icon nzType="down" class="ant-input-number-handler-down-inner" />
  387. </ng-content>
  388. </span>
  389. </div>
  390. }
  391. <div class="ant-input-number-input-wrap">
  392. <input
  393. #input
  394. autocomplete="off"
  395. role="spinbutton"
  396. class="ant-input-number-input"
  397. [attr.aria-valuemin]="nzMin()"
  398. [attr.aria-valuemax]="nzMax()"
  399. [attr.id]="nzId()"
  400. [attr.step]="nzStep()"
  401. [attr.value]="displayValue()"
  402. [value]="displayValue()"
  403. [placeholder]="nzPlaceHolder() ?? ''"
  404. [disabled]="finalDisabled()"
  405. [readOnly]="nzReadOnly()"
  406. (input)="onInput(input.value)"
  407. />
  408. </div>
  409. </ng-template>
  410. `, isInline: true, dependencies: [{ kind: "ngmodule", type: NzIconModule }, { kind: "directive", type: i2.NzIconDirective, selector: "nz-icon,[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "component", type: NzFormItemFeedbackIconComponent, selector: "nz-form-item-feedback-icon", inputs: ["status"], exportAs: ["nzFormFeedbackIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
  411. }
  412. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzInputNumberComponent, decorators: [{
  413. type: Component,
  414. args: [{
  415. selector: 'nz-input-number',
  416. exportAs: 'nzInputNumber',
  417. imports: [NzIconModule, NzFormItemFeedbackIconComponent, NgTemplateOutlet],
  418. template: `
  419. @if (hasAddon()) {
  420. <ng-template [ngTemplateOutlet]="inputNumberWithAddonInner" />
  421. } @else if (hasAffix()) {
  422. <ng-template [ngTemplateOutlet]="inputNumberWithAffixInner" />
  423. } @else {
  424. <ng-template [ngTemplateOutlet]="inputNumberInner" />
  425. }
  426. <ng-template #inputNumberWithAddonInner>
  427. <div class="ant-input-number-wrapper ant-input-number-group">
  428. @if (addonBefore()) {
  429. <div class="ant-input-number-group-addon">
  430. <ng-content select="[nzInputAddonBefore]"></ng-content>
  431. </div>
  432. }
  433. @if (hasAffix()) {
  434. <ng-template [ngTemplateOutlet]="inputNumberWithAffix" />
  435. } @else {
  436. <ng-template [ngTemplateOutlet]="inputNumber" />
  437. }
  438. @if (addonAfter()) {
  439. <div class="ant-input-number-group-addon">
  440. <ng-content select="[nzInputAddonAfter]"></ng-content>
  441. </div>
  442. }
  443. </div>
  444. </ng-template>
  445. <ng-template #inputNumberWithAffix>
  446. <div [class]="affixWrapperClass()">
  447. <ng-template [ngTemplateOutlet]="inputNumberWithAffixInner" />
  448. </div>
  449. </ng-template>
  450. <ng-template #inputNumberWithAffixInner>
  451. @if (prefix()) {
  452. <span class="ant-input-number-prefix">
  453. <ng-content select="[nzInputPrefix]"></ng-content>
  454. </span>
  455. }
  456. <ng-template [ngTemplateOutlet]="inputNumber" />
  457. @if (suffix() || hasFeedback()) {
  458. <span class="ant-input-number-suffix">
  459. <ng-content select="[nzInputSuffix]"></ng-content>
  460. @if (hasFeedback() && finalStatus()) {
  461. <nz-form-item-feedback-icon [status]="finalStatus()" />
  462. }
  463. </span>
  464. }
  465. </ng-template>
  466. <ng-template #inputNumber>
  467. <div #inputNumberHost [class]="inputNumberClass()">
  468. <ng-template [ngTemplateOutlet]="inputNumberInner" />
  469. </div>
  470. </ng-template>
  471. <ng-template #inputNumberInner>
  472. @if (nzControls()) {
  473. <div #handlers class="ant-input-number-handler-wrap" (mouseup)="stopAutoStep()" (mouseleave)="stopAutoStep()">
  474. <span
  475. role="button"
  476. unselectable="on"
  477. class="ant-input-number-handler ant-input-number-handler-up"
  478. [class.ant-input-number-handler-up-disabled]="upDisabled()"
  479. [attr.aria-disabled]="upDisabled()"
  480. (mousedown)="onStepMouseDown($event, true)"
  481. >
  482. <ng-content select="[nzInputNumberUpIcon]">
  483. <nz-icon nzType="up" class="ant-input-number-handler-up-inner" />
  484. </ng-content>
  485. </span>
  486. <span
  487. role="button"
  488. unselectable="on"
  489. class="ant-input-number-handler ant-input-number-handler-down"
  490. [class.ant-input-number-handler-down-disabled]="downDisabled()"
  491. [attr.aria-disabled]="downDisabled()"
  492. (mousedown)="onStepMouseDown($event, false)"
  493. >
  494. <ng-content select="[nzInputNumberDownIcon]">
  495. <nz-icon nzType="down" class="ant-input-number-handler-down-inner" />
  496. </ng-content>
  497. </span>
  498. </div>
  499. }
  500. <div class="ant-input-number-input-wrap">
  501. <input
  502. #input
  503. autocomplete="off"
  504. role="spinbutton"
  505. class="ant-input-number-input"
  506. [attr.aria-valuemin]="nzMin()"
  507. [attr.aria-valuemax]="nzMax()"
  508. [attr.id]="nzId()"
  509. [attr.step]="nzStep()"
  510. [attr.value]="displayValue()"
  511. [value]="displayValue()"
  512. [placeholder]="nzPlaceHolder() ?? ''"
  513. [disabled]="finalDisabled()"
  514. [readOnly]="nzReadOnly()"
  515. (input)="onInput(input.value)"
  516. />
  517. </div>
  518. </ng-template>
  519. `,
  520. providers: [
  521. {
  522. provide: NG_VALUE_ACCESSOR,
  523. useExisting: forwardRef(() => NzInputNumberComponent),
  524. multi: true
  525. },
  526. { provide: NZ_SPACE_COMPACT_ITEM_TYPE, useValue: 'input-number' }
  527. ],
  528. changeDetection: ChangeDetectionStrategy.OnPush,
  529. encapsulation: ViewEncapsulation.None,
  530. host: {
  531. '[class]': 'class()',
  532. '(keydown)': 'onKeyDown($event)'
  533. },
  534. hostDirectives: [NzSpaceCompactItemDirective]
  535. }]
  536. }], ctorParameters: () => [] });
  537. /**
  538. * When click and hold on a button - the speed of auto changing the value.
  539. */
  540. const STEP_INTERVAL = 200;
  541. /**
  542. * When click and hold on a button - the delay before auto changing the value.
  543. */
  544. const STEP_DELAY = 600;
  545. function defaultParser(value) {
  546. return +value.trim().replace(/。/g, '.');
  547. }
  548. function isInRange(value, min, max) {
  549. return value >= min && value <= max;
  550. }
  551. /**
  552. * if max > 0, round down with precision. Example: input= 3.5, max= 3.5, precision=0; output= 3
  553. * if max < 0, round up with precision. Example: input=-3.5, max=-3.5, precision=0; output=-4
  554. * if min > 0, round up with precision. Example: input= 3.5, min= 3.5, precision=0; output= 4
  555. * if min < 0, round down with precision. Example: input=-3.5, min=-3.5, precision=0; output=-3
  556. */
  557. function getRangeValue(value, min, max, precision = null) {
  558. if (precision === null) {
  559. if (value < min) {
  560. return min;
  561. }
  562. if (value > max) {
  563. return max;
  564. }
  565. return value;
  566. }
  567. const fixedValue = +value.toFixed(precision);
  568. const multiple = Math.pow(10, precision);
  569. if (fixedValue < min) {
  570. return Math.ceil(min * multiple) / multiple;
  571. }
  572. if (fixedValue > max) {
  573. return Math.floor(max * multiple) / multiple;
  574. }
  575. return fixedValue;
  576. }
  577. function getDecimalPlaces(num) {
  578. return num.toString().split('.')[1]?.length || 0;
  579. }
  580. function isNotCompleteNumber(value) {
  581. return /[.。](\d*0)?$/.test(value.toString());
  582. }
  583. /**
  584. * Use of this source code is governed by an MIT-style license that can be
  585. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  586. */
  587. class NzInputNumberModule {
  588. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzInputNumberModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
  589. static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.2", ngImport: i0, type: NzInputNumberModule, imports: [NzInputNumberComponent,
  590. NzInputAddonBeforeDirective,
  591. NzInputAddonAfterDirective,
  592. NzInputPrefixDirective,
  593. NzInputSuffixDirective], exports: [NzInputNumberComponent,
  594. NzInputAddonBeforeDirective,
  595. NzInputAddonAfterDirective,
  596. NzInputPrefixDirective,
  597. NzInputSuffixDirective] });
  598. static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzInputNumberModule, imports: [NzInputNumberComponent] });
  599. }
  600. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzInputNumberModule, decorators: [{
  601. type: NgModule,
  602. args: [{
  603. imports: [
  604. NzInputNumberComponent,
  605. NzInputAddonBeforeDirective,
  606. NzInputAddonAfterDirective,
  607. NzInputPrefixDirective,
  608. NzInputSuffixDirective
  609. ],
  610. exports: [
  611. NzInputNumberComponent,
  612. NzInputAddonBeforeDirective,
  613. NzInputAddonAfterDirective,
  614. NzInputPrefixDirective,
  615. NzInputSuffixDirective
  616. ]
  617. }]
  618. }] });
  619. /**
  620. * Use of this source code is governed by an MIT-style license that can be
  621. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  622. */
  623. /**
  624. * Generated bundle index. Do not edit.
  625. */
  626. export { NzInputNumberComponent, NzInputNumberModule };
  627. //# sourceMappingURL=ng-zorro-antd-input-number.mjs.map