@colijnit/corecomponents_v12 262.1.13 → 262.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/colijnit-corecomponents_v12.mjs +330 -132
- package/fesm2022/colijnit-corecomponents_v12.mjs.map +1 -1
- package/index.d.ts +40 -8
- package/lib/components/grid-toolbar/style/_layout.scss +1 -0
- package/lib/components/grid-toolbar-button/style/_layout.scss +1 -0
- package/lib/components/input-number-picker/style/_layout.scss +8 -0
- package/lib/components/list-of-values/style/_theme.scss +8 -8
- package/lib/components/simple-grid/style/_layout.scss +1 -0
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __decorate } from 'tslib';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { Input, Injectable, HostBinding, ViewEncapsulation, Component, Directive, ElementRef, Pipe, EventEmitter, Output, ViewChildren, ViewContainerRef, HostListener, ViewChild, Optional, NgModule, SkipSelf, InjectionToken, Inject, forwardRef, ChangeDetectionStrategy, ContentChildren, NO_ERRORS_SCHEMA, Injector, QueryList } from '@angular/core';
|
|
3
|
+
import { Input, Injectable, HostBinding, ViewEncapsulation, Component, Directive, ElementRef, Pipe, EventEmitter, Output, ViewChildren, ViewContainerRef, HostListener, ViewChild, Optional, NgModule, SkipSelf, InjectionToken, Inject, forwardRef, ChangeDetectionStrategy, ContentChildren, LOCALE_ID, NO_ERRORS_SCHEMA, Injector, QueryList } from '@angular/core';
|
|
4
4
|
import * as i5 from '@angular/forms';
|
|
5
5
|
import { NgModel, UntypedFormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
6
6
|
import * as i1 from '@angular/platform-browser';
|
|
@@ -532,6 +532,28 @@ class NumberUtils {
|
|
|
532
532
|
return { isOk: false, nearestOkNr: nearestOkNr };
|
|
533
533
|
}
|
|
534
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Decides whether typing one more digit onto the given numeric text would exceed the configured
|
|
537
|
+
* digit limits. When `decimals` (scale) is set, `maxLength` is treated as the total precision: the
|
|
538
|
+
* integer part is capped at (maxLength - decimals) digits and the fractional part at `decimals`
|
|
539
|
+
* digits. When `decimals` is not set, `maxLength` caps the total number of digits.
|
|
540
|
+
*
|
|
541
|
+
* Note: assumes the digit is appended at the end of the value, because native number inputs expose
|
|
542
|
+
* no caret/selection information to constrain mid-string edits.
|
|
543
|
+
*/
|
|
544
|
+
static WouldExceedDigitLimits(currentValue, maxLength, decimals) {
|
|
545
|
+
const digits = ('' + (currentValue ?? '')).replace('-', '');
|
|
546
|
+
if (decimals > 0) {
|
|
547
|
+
const separatorIndex = digits.search(/[.,]/);
|
|
548
|
+
if (separatorIndex === -1) {
|
|
549
|
+
const maxIntegerDigits = maxLength > 0 ? maxLength - decimals : Number.POSITIVE_INFINITY;
|
|
550
|
+
return digits.length >= maxIntegerDigits;
|
|
551
|
+
}
|
|
552
|
+
const decimalDigits = digits.length - separatorIndex - 1;
|
|
553
|
+
return decimalDigits >= decimals;
|
|
554
|
+
}
|
|
555
|
+
return maxLength > 0 && digits.length >= maxLength;
|
|
556
|
+
}
|
|
535
557
|
static _GetLargestDecimalPrecisionOf(...args) {
|
|
536
558
|
return ArrayUtils.GetMaxCalculatedValue(args, (arg) => {
|
|
537
559
|
return NumberUtils.GetDecimalPlaces(arg);
|
|
@@ -934,8 +956,12 @@ function requiredValidator(control) {
|
|
|
934
956
|
function precisionScaleValidator(precision, scale) {
|
|
935
957
|
return function (control) {
|
|
936
958
|
let isValid = true;
|
|
937
|
-
if (control) {
|
|
938
|
-
|
|
959
|
+
if (control && control.value !== null && control.value !== undefined && control.value !== '') {
|
|
960
|
+
// The value may be a locale display string (e.g. "1234567,89"); normalize it to a number so the
|
|
961
|
+
// decimal separator is not counted as an integer digit by CheckPrecisionAndScale.
|
|
962
|
+
const raw = control.value;
|
|
963
|
+
const numeric = typeof raw === 'string' ? Number(raw.replace(',', '.')) : raw;
|
|
964
|
+
isValid = isNaN(numeric) || NumberUtils.CheckPrecisionAndScale(numeric, precision, scale).isOk;
|
|
939
965
|
}
|
|
940
966
|
return isValid ? null : { 'precision-scale': "MESSAGE_FIELD_PRECISION_OVERRIDDEN||" + precision };
|
|
941
967
|
};
|
|
@@ -2031,27 +2057,28 @@ class CommitButtonsComponent {
|
|
|
2031
2057
|
event.currentTarget.removeEventListener('animationiteration', this._handleAnimationIteration);
|
|
2032
2058
|
};
|
|
2033
2059
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CommitButtonsComponent, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
|
|
2034
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CommitButtonsComponent, isStandalone: false, selector: "co-commit-buttons", inputs: { committing: "committing", commitFinished: "commitFinished", parentForOverlay: "parentForOverlay" }, outputs: { cancelClick: "cancelClick", commitClick: "commitClick" }, host: { properties: { "class.co-commit-buttons": "this.showClass" } }, viewQueries: [{ propertyName: "content", predicate: ["animatediv"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
2035
|
-
<div class="commit-buttons-wrapper" [overlay]="parentForOverlay" [rightAlign]="true" @showHideSaveCancel>
|
|
2036
|
-
<div class="commit-buttons-button save" [class.finished]="commitFinished"
|
|
2037
|
-
(
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
<div #animatediv></div>
|
|
2042
|
-
<div #animatediv></div>
|
|
2043
|
-
<div #animatediv></div>
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
<
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2060
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CommitButtonsComponent, isStandalone: false, selector: "co-commit-buttons", inputs: { committing: "committing", commitFinished: "commitFinished", parentForOverlay: "parentForOverlay" }, outputs: { cancelClick: "cancelClick", commitClick: "commitClick" }, host: { properties: { "class.co-commit-buttons": "this.showClass" } }, viewQueries: [{ propertyName: "content", predicate: ["animatediv"], descendants: true, read: ElementRef }], ngImport: i0, template: `
|
|
2061
|
+
<div class="commit-buttons-wrapper" [overlay]="parentForOverlay" [rightAlign]="true" @showHideSaveCancel>
|
|
2062
|
+
<div class="commit-buttons-button save" [class.finished]="commitFinished"
|
|
2063
|
+
(mousedown)="$event.preventDefault()"
|
|
2064
|
+
(click)="commitClick.emit($event)">
|
|
2065
|
+
@if (committing) {
|
|
2066
|
+
<div class="save-button-spinner">
|
|
2067
|
+
<div #animatediv></div>
|
|
2068
|
+
<div #animatediv></div>
|
|
2069
|
+
<div #animatediv></div>
|
|
2070
|
+
<div #animatediv></div>
|
|
2071
|
+
</div>
|
|
2072
|
+
}
|
|
2073
|
+
@if (firstShow || commitFinished) {
|
|
2074
|
+
<svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
|
|
2075
|
+
<path class="checkmark-check" [class.first-show]="firstShow" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/></svg>
|
|
2076
|
+
}
|
|
2077
|
+
</div>
|
|
2078
|
+
<div class="commit-buttons-button cancel" (mousedown)="$event.preventDefault()" (click)="cancelClick.emit($event)">
|
|
2079
|
+
<div class="cancel-button"></div>
|
|
2080
|
+
</div>
|
|
2081
|
+
</div>
|
|
2055
2082
|
`, isInline: true, dependencies: [{ kind: "directive", type: OverlayDirective, selector: "[overlay]", inputs: ["overlay", "view", "inline", "keepInView", "inheritWidth", "rightAlign", "fullSize"] }], animations: [
|
|
2056
2083
|
trigger('showHideSaveCancel', [
|
|
2057
2084
|
state('*', style({ transform: 'scaleY(1)', opacity: 1 })),
|
|
@@ -2064,27 +2091,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2064
2091
|
type: Component,
|
|
2065
2092
|
args: [{
|
|
2066
2093
|
selector: 'co-commit-buttons',
|
|
2067
|
-
template: `
|
|
2068
|
-
<div class="commit-buttons-wrapper" [overlay]="parentForOverlay" [rightAlign]="true" @showHideSaveCancel>
|
|
2069
|
-
<div class="commit-buttons-button save" [class.finished]="commitFinished"
|
|
2070
|
-
(
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
<div #animatediv></div>
|
|
2075
|
-
<div #animatediv></div>
|
|
2076
|
-
<div #animatediv></div>
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
<
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2094
|
+
template: `
|
|
2095
|
+
<div class="commit-buttons-wrapper" [overlay]="parentForOverlay" [rightAlign]="true" @showHideSaveCancel>
|
|
2096
|
+
<div class="commit-buttons-button save" [class.finished]="commitFinished"
|
|
2097
|
+
(mousedown)="$event.preventDefault()"
|
|
2098
|
+
(click)="commitClick.emit($event)">
|
|
2099
|
+
@if (committing) {
|
|
2100
|
+
<div class="save-button-spinner">
|
|
2101
|
+
<div #animatediv></div>
|
|
2102
|
+
<div #animatediv></div>
|
|
2103
|
+
<div #animatediv></div>
|
|
2104
|
+
<div #animatediv></div>
|
|
2105
|
+
</div>
|
|
2106
|
+
}
|
|
2107
|
+
@if (firstShow || commitFinished) {
|
|
2108
|
+
<svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52">
|
|
2109
|
+
<path class="checkmark-check" [class.first-show]="firstShow" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/></svg>
|
|
2110
|
+
}
|
|
2111
|
+
</div>
|
|
2112
|
+
<div class="commit-buttons-button cancel" (mousedown)="$event.preventDefault()" (click)="cancelClick.emit($event)">
|
|
2113
|
+
<div class="cancel-button"></div>
|
|
2114
|
+
</div>
|
|
2115
|
+
</div>
|
|
2088
2116
|
`,
|
|
2089
2117
|
animations: [
|
|
2090
2118
|
trigger('showHideSaveCancel', [
|
|
@@ -2267,7 +2295,7 @@ class BaseInputComponent {
|
|
|
2267
2295
|
get model() {
|
|
2268
2296
|
return this._model;
|
|
2269
2297
|
}
|
|
2270
|
-
label;
|
|
2298
|
+
label = '';
|
|
2271
2299
|
noValidation = false;
|
|
2272
2300
|
initFocus;
|
|
2273
2301
|
noClickFocus;
|
|
@@ -2517,7 +2545,6 @@ class BaseInputComponent {
|
|
|
2517
2545
|
// @implements ConfigurationAdapterComponent
|
|
2518
2546
|
objectConfigName;
|
|
2519
2547
|
validationError = '';
|
|
2520
|
-
shouldCommit = true;
|
|
2521
2548
|
_markedAsUserTouched = false;
|
|
2522
2549
|
_destroyed = false;
|
|
2523
2550
|
_hasOnPushCdStrategy = false;
|
|
@@ -2543,6 +2570,7 @@ class BaseInputComponent {
|
|
|
2543
2570
|
_formReadonlyChangeSub;
|
|
2544
2571
|
_clearMarkedAsUserTouchedSub;
|
|
2545
2572
|
_canSaveOrCancel = false;
|
|
2573
|
+
_committing = false;
|
|
2546
2574
|
_commitButtonsComponentRef;
|
|
2547
2575
|
_validationComponentRef;
|
|
2548
2576
|
constructor(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
@@ -2614,7 +2642,6 @@ class BaseInputComponent {
|
|
|
2614
2642
|
return Promise.resolve(true);
|
|
2615
2643
|
};
|
|
2616
2644
|
cancelClick(event) {
|
|
2617
|
-
this.shouldCommit = false;
|
|
2618
2645
|
this.keepFocus = true;
|
|
2619
2646
|
if (this._initialModelSet) {
|
|
2620
2647
|
this.model = this._initialModel;
|
|
@@ -2669,7 +2696,7 @@ class BaseInputComponent {
|
|
|
2669
2696
|
this.focus.next();
|
|
2670
2697
|
}
|
|
2671
2698
|
async doBlur(event, handleCommit = true) {
|
|
2672
|
-
if (this.showSaveCancel && handleCommit && this._modelDirtyForCommit
|
|
2699
|
+
if (this.showSaveCancel && handleCommit && this._modelDirtyForCommit) {
|
|
2673
2700
|
await this._handleCommit(event, false);
|
|
2674
2701
|
}
|
|
2675
2702
|
setTimeout(() => {
|
|
@@ -2799,23 +2826,37 @@ class BaseInputComponent {
|
|
|
2799
2826
|
}
|
|
2800
2827
|
}
|
|
2801
2828
|
async _handleCommit(event, doBlur = true) {
|
|
2802
|
-
if (!this.showSaveCancel ||
|
|
2829
|
+
if (!this.showSaveCancel || !this._modelDirtyForCommit || this._committing) {
|
|
2803
2830
|
return true;
|
|
2804
2831
|
}
|
|
2832
|
+
this._committing = true;
|
|
2805
2833
|
this.keepFocus = true;
|
|
2806
|
-
this.shouldCommit = true;
|
|
2807
2834
|
if (this._commitButtonsComponentRef) {
|
|
2808
2835
|
this._commitButtonsComponentRef.instance.commitFinished = false;
|
|
2809
2836
|
this._commitButtonsComponentRef.instance.committing = true;
|
|
2810
2837
|
}
|
|
2811
2838
|
this._modelDirtyForCommit = false;
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2839
|
+
try {
|
|
2840
|
+
const success = await this.commit(this.model);
|
|
2841
|
+
if (success) {
|
|
2842
|
+
// keep the committed value as the new baseline, otherwise a later model re-emission
|
|
2843
|
+
// would compare against a stale _initialModel and re-open the commit guard.
|
|
2844
|
+
this._initialModel = this._model;
|
|
2845
|
+
this._modelDirtyForCommit = false;
|
|
2846
|
+
}
|
|
2847
|
+
else {
|
|
2848
|
+
this._modelDirtyForCommit = true;
|
|
2849
|
+
}
|
|
2850
|
+
this.keepFocus = false;
|
|
2851
|
+
await this._commitFinished();
|
|
2852
|
+
if (success && doBlur) {
|
|
2853
|
+
this.doBlur(event, false);
|
|
2854
|
+
}
|
|
2855
|
+
return success;
|
|
2856
|
+
}
|
|
2857
|
+
finally {
|
|
2858
|
+
this._committing = false;
|
|
2817
2859
|
}
|
|
2818
|
-
return success;
|
|
2819
2860
|
}
|
|
2820
2861
|
_commitFinished() {
|
|
2821
2862
|
return new Promise((resolve) => {
|
|
@@ -2848,6 +2889,8 @@ class BaseInputComponent {
|
|
|
2848
2889
|
this.input.disabled = disabled;
|
|
2849
2890
|
}
|
|
2850
2891
|
}
|
|
2892
|
+
// protected so numeric components can suppress the native maxlength (which, on a text input, would
|
|
2893
|
+
// wrongly count the decimal separator/sign as characters); they enforce precision/scale in keydown.
|
|
2851
2894
|
_setNativeMaxLength(maxlength) {
|
|
2852
2895
|
if (this.input && !isNaN(maxlength)) {
|
|
2853
2896
|
this.input.maxLength = maxlength;
|
|
@@ -5802,48 +5845,40 @@ class GridToolbarComponent {
|
|
|
5802
5845
|
}
|
|
5803
5846
|
}
|
|
5804
5847
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: GridToolbarComponent, deps: [{ token: IconCacheService }], target: i0.ɵɵFactoryTarget.Component });
|
|
5805
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: GridToolbarComponent, isStandalone: false, selector: "co-grid-toolbar", inputs: { showEdit: "showEdit", showAdd: "showAdd", showDelete: "showDelete", deleteEnabled: "deleteEnabled" }, outputs: { editClick: "editClick", cancelClick: "cancelClick", saveClick: "saveClick", addClick: "addClick", deleteClick: "deleteClick" }, host: { properties: { "class.co-grid-toolbar": "this.showClass" } }, ngImport: i0, template: `
|
|
5806
|
-
<div class="grid-toolbar-wrapper">
|
|
5807
|
-
@if (showEdit) {
|
|
5808
|
-
<co-icon [iconData]="iconsService.getIcon(icons.PenToSquareSolid)" [title]="'edit'" (click)="editClick.emit($event)"></co-icon>
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
@if (showDelete) {
|
|
5820
|
-
<co-icon [iconData]="iconsService.getIcon(icons.TrashCanSolid)" [title]="'delete'" [class.disabled]="!deleteEnabled" (click)="handleDeleteClick()"></co-icon>
|
|
5821
|
-
}
|
|
5822
|
-
</div>
|
|
5848
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: GridToolbarComponent, isStandalone: false, selector: "co-grid-toolbar", inputs: { showEdit: "showEdit", showAdd: "showAdd", showDelete: "showDelete", deleteEnabled: "deleteEnabled" }, outputs: { editClick: "editClick", cancelClick: "cancelClick", saveClick: "saveClick", addClick: "addClick", deleteClick: "deleteClick" }, host: { properties: { "class.co-grid-toolbar": "this.showClass" } }, ngImport: i0, template: `
|
|
5849
|
+
<div class="grid-toolbar-wrapper">
|
|
5850
|
+
@if (showEdit) {
|
|
5851
|
+
<co-icon [iconData]="iconsService.getIcon(icons.PenToSquareSolid)" [title]="'edit'" (click)="editClick.emit($event)"></co-icon>
|
|
5852
|
+
<co-icon [iconData]="iconsService.getIcon(icons.RotateLeftSolid)" [title]="'cancel'" (click)="cancelClick.emit()"></co-icon>
|
|
5853
|
+
<co-icon [iconData]="iconsService.getIcon(icons.FloppyDiskSolid)" [title]="'save'" (click)="saveClick.emit()"></co-icon>
|
|
5854
|
+
}
|
|
5855
|
+
@if (showAdd || showEdit) {
|
|
5856
|
+
<co-icon [iconData]="iconsService.getIcon(icons.PlusSolid)" [title]="'add'" (click)="addClick.emit()"></co-icon>
|
|
5857
|
+
}
|
|
5858
|
+
@if (showDelete) {
|
|
5859
|
+
<co-icon [iconData]="iconsService.getIcon(icons.TrashCanSolid)" [title]="'delete'" [class.disabled]="!deleteEnabled" (click)="handleDeleteClick()"></co-icon>
|
|
5860
|
+
}
|
|
5861
|
+
</div>
|
|
5823
5862
|
`, isInline: true, dependencies: [{ kind: "component", type: IconComponent, selector: "co-icon", inputs: ["icon", "iconData"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
5824
5863
|
}
|
|
5825
5864
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: GridToolbarComponent, decorators: [{
|
|
5826
5865
|
type: Component,
|
|
5827
5866
|
args: [{
|
|
5828
5867
|
selector: "co-grid-toolbar",
|
|
5829
|
-
template: `
|
|
5830
|
-
<div class="grid-toolbar-wrapper">
|
|
5831
|
-
@if (showEdit) {
|
|
5832
|
-
<co-icon [iconData]="iconsService.getIcon(icons.PenToSquareSolid)" [title]="'edit'" (click)="editClick.emit($event)"></co-icon>
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
@if (showDelete) {
|
|
5844
|
-
<co-icon [iconData]="iconsService.getIcon(icons.TrashCanSolid)" [title]="'delete'" [class.disabled]="!deleteEnabled" (click)="handleDeleteClick()"></co-icon>
|
|
5845
|
-
}
|
|
5846
|
-
</div>
|
|
5868
|
+
template: `
|
|
5869
|
+
<div class="grid-toolbar-wrapper">
|
|
5870
|
+
@if (showEdit) {
|
|
5871
|
+
<co-icon [iconData]="iconsService.getIcon(icons.PenToSquareSolid)" [title]="'edit'" (click)="editClick.emit($event)"></co-icon>
|
|
5872
|
+
<co-icon [iconData]="iconsService.getIcon(icons.RotateLeftSolid)" [title]="'cancel'" (click)="cancelClick.emit()"></co-icon>
|
|
5873
|
+
<co-icon [iconData]="iconsService.getIcon(icons.FloppyDiskSolid)" [title]="'save'" (click)="saveClick.emit()"></co-icon>
|
|
5874
|
+
}
|
|
5875
|
+
@if (showAdd || showEdit) {
|
|
5876
|
+
<co-icon [iconData]="iconsService.getIcon(icons.PlusSolid)" [title]="'add'" (click)="addClick.emit()"></co-icon>
|
|
5877
|
+
}
|
|
5878
|
+
@if (showDelete) {
|
|
5879
|
+
<co-icon [iconData]="iconsService.getIcon(icons.TrashCanSolid)" [title]="'delete'" [class.disabled]="!deleteEnabled" (click)="handleDeleteClick()"></co-icon>
|
|
5880
|
+
}
|
|
5881
|
+
</div>
|
|
5847
5882
|
`,
|
|
5848
5883
|
encapsulation: ViewEncapsulation.None,
|
|
5849
5884
|
standalone: false
|
|
@@ -7164,10 +7199,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7164
7199
|
args: ["class.co-calendar"]
|
|
7165
7200
|
}] } });
|
|
7166
7201
|
|
|
7202
|
+
/**
|
|
7203
|
+
* Resolves the locale-specific decimal separator (e.g. ',' for nl-NL) from the app-wide LOCALE_ID and
|
|
7204
|
+
* converts between a numeric model value and its user-facing display string. Injected app-wide, so no
|
|
7205
|
+
* component has to be given a locale explicitly.
|
|
7206
|
+
*
|
|
7207
|
+
* The model always stays a real number (dot-based / JSON-safe); the separator only affects the display
|
|
7208
|
+
* string shown in the input, never the stored value.
|
|
7209
|
+
*/
|
|
7210
|
+
class NumberLocaleService {
|
|
7211
|
+
_decimalSeparator;
|
|
7212
|
+
constructor(localeId) {
|
|
7213
|
+
// Intl uses the locale string directly, so this works without registerLocaleData().
|
|
7214
|
+
const parts = new Intl.NumberFormat(localeId).formatToParts(1.1);
|
|
7215
|
+
const decimalPart = parts.find((part) => part.type === 'decimal');
|
|
7216
|
+
this._decimalSeparator = decimalPart ? decimalPart.value : '.';
|
|
7217
|
+
}
|
|
7218
|
+
get decimalSeparator() {
|
|
7219
|
+
return this._decimalSeparator;
|
|
7220
|
+
}
|
|
7221
|
+
// Parses a user-typed display string to a number. Accepts both ',' and '.' as decimal separator so the
|
|
7222
|
+
// field is forgiving. Returns NaN when the text is not a parsable number.
|
|
7223
|
+
parse(text) {
|
|
7224
|
+
if (text === null || text === undefined) {
|
|
7225
|
+
return NaN;
|
|
7226
|
+
}
|
|
7227
|
+
const normalized = ('' + text).trim().replace(',', '.');
|
|
7228
|
+
if (normalized === '') {
|
|
7229
|
+
return NaN;
|
|
7230
|
+
}
|
|
7231
|
+
return Number(normalized);
|
|
7232
|
+
}
|
|
7233
|
+
// Formats a numeric model value to a display string using the locale decimal separator. Returns '' for
|
|
7234
|
+
// null/undefined/NaN. No grouping (thousands) separators are added, as this targets an editable field.
|
|
7235
|
+
format(value) {
|
|
7236
|
+
if (value === null || value === undefined || isNaN(value)) {
|
|
7237
|
+
return '';
|
|
7238
|
+
}
|
|
7239
|
+
return ('' + value).replace('.', this._decimalSeparator);
|
|
7240
|
+
}
|
|
7241
|
+
// Inserts the locale decimal separator at the input's caret and notifies Angular via an 'input' event.
|
|
7242
|
+
// Used to normalize a typed '.' to the locale separator (e.g. numpad '.' -> ',' for nl-NL).
|
|
7243
|
+
insertDecimalSeparator(input) {
|
|
7244
|
+
const start = input.selectionStart ?? input.value.length;
|
|
7245
|
+
const end = input.selectionEnd ?? input.value.length;
|
|
7246
|
+
input.value = input.value.slice(0, start) + this._decimalSeparator + input.value.slice(end);
|
|
7247
|
+
const caret = start + this._decimalSeparator.length;
|
|
7248
|
+
input.setSelectionRange(caret, caret);
|
|
7249
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
7250
|
+
}
|
|
7251
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NumberLocaleService, deps: [{ token: LOCALE_ID }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7252
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NumberLocaleService, providedIn: 'root' });
|
|
7253
|
+
}
|
|
7254
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NumberLocaleService, decorators: [{
|
|
7255
|
+
type: Injectable,
|
|
7256
|
+
args: [{ providedIn: 'root' }]
|
|
7257
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
7258
|
+
type: Inject,
|
|
7259
|
+
args: [LOCALE_ID]
|
|
7260
|
+
}] }] });
|
|
7261
|
+
|
|
7167
7262
|
class InputTextComponent extends BaseInputComponent {
|
|
7168
7263
|
formComponent;
|
|
7169
7264
|
changeDetector;
|
|
7170
7265
|
overlayService;
|
|
7266
|
+
_numberLocale;
|
|
7171
7267
|
formUserChangeListener;
|
|
7172
7268
|
ngZoneWrapper;
|
|
7173
7269
|
elementRef;
|
|
@@ -7243,6 +7339,26 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7243
7339
|
get model() {
|
|
7244
7340
|
return super.model;
|
|
7245
7341
|
}
|
|
7342
|
+
// keep the display string in sync when the model changes from outside typing (init / programmatic)
|
|
7343
|
+
modelSet() {
|
|
7344
|
+
if (this.digitsOnly && !this._userTyping) {
|
|
7345
|
+
this._displayValue = this._numberLocale.format(this.model);
|
|
7346
|
+
}
|
|
7347
|
+
}
|
|
7348
|
+
// For digitsOnly the input is a text field showing a locale-formatted string; parse it back to a number
|
|
7349
|
+
// before emitting so the model (and thus what is stored) stays numeric. Other types emit the raw value.
|
|
7350
|
+
handleInputModelChange(value) {
|
|
7351
|
+
if (this.digitsOnly) {
|
|
7352
|
+
this._userTyping = true;
|
|
7353
|
+
this._displayValue = value === null || value === undefined ? '' : '' + value;
|
|
7354
|
+
const parsed = this._numberLocale.parse(value);
|
|
7355
|
+
this.modelChange.emit(isNaN(parsed) ? null : parsed);
|
|
7356
|
+
this._userTyping = false;
|
|
7357
|
+
}
|
|
7358
|
+
else {
|
|
7359
|
+
this.modelChange.emit(value);
|
|
7360
|
+
}
|
|
7361
|
+
}
|
|
7246
7362
|
get pipedModel() {
|
|
7247
7363
|
if (this.formatPipe) {
|
|
7248
7364
|
try {
|
|
@@ -7254,16 +7370,23 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7254
7370
|
}
|
|
7255
7371
|
return this.model;
|
|
7256
7372
|
}
|
|
7373
|
+
// Locale-formatted string bound to the input when digitsOnly (comma for nl-NL); the model stays numeric.
|
|
7374
|
+
get displayValue() {
|
|
7375
|
+
return this._displayValue;
|
|
7376
|
+
}
|
|
7257
7377
|
isFocusedOnDate = false;
|
|
7258
7378
|
weekInputBuffer = '';
|
|
7259
7379
|
isWeekInputMode = false;
|
|
7260
7380
|
_isLeftIconMouseDown = false;
|
|
7261
7381
|
_isRightIconMouseDown = false;
|
|
7262
|
-
|
|
7382
|
+
_userTyping = false;
|
|
7383
|
+
_displayValue = '';
|
|
7384
|
+
constructor(formComponent, changeDetector, overlayService, _numberLocale, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
7263
7385
|
super(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef);
|
|
7264
7386
|
this.formComponent = formComponent;
|
|
7265
7387
|
this.changeDetector = changeDetector;
|
|
7266
7388
|
this.overlayService = overlayService;
|
|
7389
|
+
this._numberLocale = _numberLocale;
|
|
7267
7390
|
this.formUserChangeListener = formUserChangeListener;
|
|
7268
7391
|
this.ngZoneWrapper = ngZoneWrapper;
|
|
7269
7392
|
this.elementRef = elementRef;
|
|
@@ -7343,6 +7466,10 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7343
7466
|
if (this.type === 'date') {
|
|
7344
7467
|
this.isFocusedOnDate = false;
|
|
7345
7468
|
}
|
|
7469
|
+
if (this.digitsOnly) {
|
|
7470
|
+
// normalize the display once editing stops (e.g. "12," -> "12")
|
|
7471
|
+
this._displayValue = this._numberLocale.format(this.model);
|
|
7472
|
+
}
|
|
7346
7473
|
this.isFocused.emit(false);
|
|
7347
7474
|
}
|
|
7348
7475
|
handleDoFocus(event) {
|
|
@@ -7350,10 +7477,17 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7350
7477
|
this.doFocus(event);
|
|
7351
7478
|
}
|
|
7352
7479
|
}
|
|
7480
|
+
// For digitsOnly the field is a text input and precision/scale is enforced in keydown; the native
|
|
7481
|
+
// maxlength would wrongly count the decimal separator as a character. Plain text keeps native maxlength.
|
|
7482
|
+
_setNativeMaxLength(maxlength) {
|
|
7483
|
+
if (this.digitsOnly) {
|
|
7484
|
+
return;
|
|
7485
|
+
}
|
|
7486
|
+
super._setNativeMaxLength(maxlength);
|
|
7487
|
+
}
|
|
7353
7488
|
clearInput(event) {
|
|
7354
7489
|
this.setModel(null);
|
|
7355
7490
|
this.keepFocus = true;
|
|
7356
|
-
this.shouldCommit = false;
|
|
7357
7491
|
this.clearIconClick.emit(event);
|
|
7358
7492
|
}
|
|
7359
7493
|
handleKeyDownInput(event) {
|
|
@@ -7389,16 +7523,39 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7389
7523
|
}
|
|
7390
7524
|
}
|
|
7391
7525
|
if (this.digitsOnly && !this.isWeekInputMode) {
|
|
7392
|
-
|
|
7393
|
-
if (
|
|
7394
|
-
event.
|
|
7526
|
+
// the field is a text input (so a locale comma is allowed), so actively permit only numeric characters
|
|
7527
|
+
if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
|
|
7528
|
+
const isDigit = /\d/.test(event.key);
|
|
7529
|
+
const isSeparator = event.key === '.' || event.key === ',';
|
|
7530
|
+
const isSign = !this.excludePlusMinus && (event.key === '-' || event.key === '+');
|
|
7531
|
+
if (!isDigit && !isSeparator && !isSign) {
|
|
7532
|
+
event.preventDefault();
|
|
7533
|
+
return;
|
|
7534
|
+
}
|
|
7535
|
+
if (isSeparator) {
|
|
7536
|
+
// only one decimal separator, and only the locale one: normalize a foreign '.'/',' to it
|
|
7537
|
+
if (/[.,]/.test(this.input?.value ?? '')) {
|
|
7538
|
+
event.preventDefault();
|
|
7539
|
+
return;
|
|
7540
|
+
}
|
|
7541
|
+
if (event.key !== this._numberLocale.decimalSeparator) {
|
|
7542
|
+
event.preventDefault();
|
|
7543
|
+
if (this.input) {
|
|
7544
|
+
this._numberLocale.insertDecimalSeparator(this.input);
|
|
7545
|
+
}
|
|
7546
|
+
return;
|
|
7547
|
+
}
|
|
7548
|
+
}
|
|
7395
7549
|
}
|
|
7396
7550
|
}
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7551
|
+
// Native <input> ignores maxlength on numeric inputs, so enforce maxLength (as precision) and
|
|
7552
|
+
// decimals (as scale) ourselves for digit keys. Non-numeric text inputs keep the native maxlength.
|
|
7553
|
+
// Read the live element value (not this.model): a numeric input reports "" for an in-progress value
|
|
7554
|
+
// like "1234567.", so this.model would still hold "1234567" and wrongly block the first decimal digit.
|
|
7555
|
+
const currentText = this.input ? this.input.value : String(this.model ?? "");
|
|
7556
|
+
if ((this.digitsOnly || this.type === "number") &&
|
|
7557
|
+
/^\d$/.test(key) &&
|
|
7558
|
+
NumberUtils.WouldExceedDigitLimits(currentText, this.maxLength, this.decimals)) {
|
|
7402
7559
|
event.preventDefault();
|
|
7403
7560
|
}
|
|
7404
7561
|
}
|
|
@@ -7448,7 +7605,7 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7448
7605
|
const day = String(date.getDate()).padStart(2, '0');
|
|
7449
7606
|
return `${year}-${month}-${day}`;
|
|
7450
7607
|
}
|
|
7451
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputTextComponent, deps: [{ token: FormComponent, optional: true }, { token: i0.ChangeDetectorRef }, { token: OverlayService }, { token: FormInputUserModelChangeListenerService }, { token: NgZoneWrapperService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
7608
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputTextComponent, deps: [{ token: FormComponent, optional: true }, { token: i0.ChangeDetectorRef }, { token: OverlayService }, { token: NumberLocaleService }, { token: FormInputUserModelChangeListenerService }, { token: NgZoneWrapperService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
7452
7609
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: InputTextComponent, isStandalone: false, selector: "co-input-text", inputs: { useContent: "useContent", placeholder: "placeholder", align: "align", type: "type", formatPipe: "formatPipe", min: "min", max: "max", pattern: "pattern", digitsOnly: "digitsOnly", excludePlusMinus: "excludePlusMinus", showClearButton: "showClearButton", keyDownWhiteList: "keyDownWhiteList", showPlaceholderOnFocus: "showPlaceholderOnFocus", leftIcon: "leftIcon", rightIcon: "rightIcon", leftIconData: "leftIconData", rightIconData: "rightIconData", selectOnFocus: "selectOnFocus", emptyPlace: "emptyPlace", firstDayOfWeek: "firstDayOfWeek", noStyle: "noStyle", hideArrowButtons: "hideArrowButtons", model: "model" }, outputs: { leftIconClick: "leftIconClick", leftIconMouseDown: "leftIconMouseDown", leftIconMouseUp: "leftIconMouseUp", rightIconClick: "rightIconClick", rightIconMouseDown: "rightIconMouseDown", rightIconMouseUp: "rightIconMouseUp", clearIconClick: "clearIconClick", isFocused: "isFocused" }, host: { listeners: { "document:pointerup": "handleDocumentPointerUp($event)", "document:pointercancel": "handleDocumentPointerUp($event)" }, properties: { "class.no-style": "this.noStyle", "class.hide-arrows": "this.hideArrowButtons", "class.isDate": "this.isDate", "class.co-input-text": "this.showClass", "class.has-left-icon": "this.hasLeftIcon", "class.has-right-icon": "this.hasRightIcon", "class.has-own-label": "this.hasOwnLabel" } }, providers: [
|
|
7453
7610
|
OverlayService, {
|
|
7454
7611
|
provide: SCREEN_CONFIG_ADAPTER_COMPONENT_INTERFACE_NAME,
|
|
@@ -7483,15 +7640,16 @@ class InputTextComponent extends BaseInputComponent {
|
|
|
7483
7640
|
<input [class.show]="focused || !formatPipe" #input
|
|
7484
7641
|
[class.input-input-hidden]="useContent"
|
|
7485
7642
|
[ngClass]="align"
|
|
7486
|
-
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? '
|
|
7643
|
+
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? 'text' : (type === 'date' ? 'text' : type))"
|
|
7644
|
+
[attr.inputmode]="digitsOnly ? 'decimal' : null"
|
|
7487
7645
|
[placeholder]="type === 'date' && !isFocusedOnDate ? '' : placeholder"
|
|
7488
7646
|
[pattern]="type === 'date' ? pattern : undefined"
|
|
7489
|
-
[ngModel]="model"
|
|
7647
|
+
[ngModel]="digitsOnly ? displayValue : model"
|
|
7490
7648
|
[min]="(type === 'number' || type === 'date') && this.min ? this.min : undefined"
|
|
7491
7649
|
[max]="(type === 'number' || type === 'date') && this.max ? this.max : undefined"
|
|
7492
7650
|
[readonly]="readonly"
|
|
7493
7651
|
[required]="required"
|
|
7494
|
-
(ngModelChange)="
|
|
7652
|
+
(ngModelChange)="handleInputModelChange($event)"
|
|
7495
7653
|
(keydown)="handleKeyDownInput($event)"
|
|
7496
7654
|
(keyup)="keyUp.emit($event)"
|
|
7497
7655
|
(focusin)="handleInputFocus($event)"
|
|
@@ -7559,15 +7717,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7559
7717
|
<input [class.show]="focused || !formatPipe" #input
|
|
7560
7718
|
[class.input-input-hidden]="useContent"
|
|
7561
7719
|
[ngClass]="align"
|
|
7562
|
-
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? '
|
|
7720
|
+
[type]="isWeekInputMode ? 'text' : (isFocusedOnDate || (hasValue && emptyPlace)) ? 'date' : (digitsOnly ? 'text' : (type === 'date' ? 'text' : type))"
|
|
7721
|
+
[attr.inputmode]="digitsOnly ? 'decimal' : null"
|
|
7563
7722
|
[placeholder]="type === 'date' && !isFocusedOnDate ? '' : placeholder"
|
|
7564
7723
|
[pattern]="type === 'date' ? pattern : undefined"
|
|
7565
|
-
[ngModel]="model"
|
|
7724
|
+
[ngModel]="digitsOnly ? displayValue : model"
|
|
7566
7725
|
[min]="(type === 'number' || type === 'date') && this.min ? this.min : undefined"
|
|
7567
7726
|
[max]="(type === 'number' || type === 'date') && this.max ? this.max : undefined"
|
|
7568
7727
|
[readonly]="readonly"
|
|
7569
7728
|
[required]="required"
|
|
7570
|
-
(ngModelChange)="
|
|
7729
|
+
(ngModelChange)="handleInputModelChange($event)"
|
|
7571
7730
|
(keydown)="handleKeyDownInput($event)"
|
|
7572
7731
|
(keyup)="keyUp.emit($event)"
|
|
7573
7732
|
(focusin)="handleInputFocus($event)"
|
|
@@ -7618,7 +7777,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7618
7777
|
}]
|
|
7619
7778
|
}], ctorParameters: () => [{ type: FormComponent, decorators: [{
|
|
7620
7779
|
type: Optional
|
|
7621
|
-
}] }, { type: i0.ChangeDetectorRef }, { type: OverlayService }, { type: FormInputUserModelChangeListenerService }, { type: NgZoneWrapperService }, { type: i0.ElementRef }], propDecorators: { useContent: [{
|
|
7780
|
+
}] }, { type: i0.ChangeDetectorRef }, { type: OverlayService }, { type: NumberLocaleService }, { type: FormInputUserModelChangeListenerService }, { type: NgZoneWrapperService }, { type: i0.ElementRef }], propDecorators: { useContent: [{
|
|
7622
7781
|
type: Input
|
|
7623
7782
|
}], placeholder: [{
|
|
7624
7783
|
type: Input
|
|
@@ -9054,16 +9213,25 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9054
9213
|
iconCacheService;
|
|
9055
9214
|
overlayService;
|
|
9056
9215
|
_ngZone;
|
|
9216
|
+
_numberLocale;
|
|
9057
9217
|
ngZoneWrapper;
|
|
9058
9218
|
elementRef;
|
|
9059
9219
|
// @override
|
|
9060
9220
|
set model(model) {
|
|
9061
9221
|
this.setValue(model, true);
|
|
9062
9222
|
super.model = model;
|
|
9223
|
+
// keep the display string in sync, unless the user is mid-typing (then their raw text is preserved)
|
|
9224
|
+
if (!this._userTyping) {
|
|
9225
|
+
this._displayValue = this._numberLocale.format(model);
|
|
9226
|
+
}
|
|
9063
9227
|
}
|
|
9064
9228
|
get model() {
|
|
9065
9229
|
return super.model;
|
|
9066
9230
|
}
|
|
9231
|
+
// Locale-formatted string bound to the native text input (comma for nl-NL); the model stays numeric.
|
|
9232
|
+
get displayValue() {
|
|
9233
|
+
return this._displayValue;
|
|
9234
|
+
}
|
|
9067
9235
|
modelChangeOnEnter = true;
|
|
9068
9236
|
showPermanentLabel = false;
|
|
9069
9237
|
leftIconData;
|
|
@@ -9084,8 +9252,14 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9084
9252
|
// @override Default true for us.
|
|
9085
9253
|
noValidation = true;
|
|
9086
9254
|
set decimals(decimals) {
|
|
9255
|
+
// Also store on the base so its precision/scale validator picks it up; a setter-only override
|
|
9256
|
+
// would otherwise shadow the inherited getter and make this.decimals read as undefined.
|
|
9257
|
+
super.decimals = decimals;
|
|
9087
9258
|
this.numberLogic.decimals = decimals;
|
|
9088
9259
|
}
|
|
9260
|
+
get decimals() {
|
|
9261
|
+
return super.decimals;
|
|
9262
|
+
}
|
|
9089
9263
|
// @override
|
|
9090
9264
|
modelChange = new EventEmitter();
|
|
9091
9265
|
iconClick = new EventEmitter();
|
|
@@ -9105,6 +9279,8 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9105
9279
|
plusSelected = false;
|
|
9106
9280
|
_numberInputHasFocus = false;
|
|
9107
9281
|
_changeFromButton = false;
|
|
9282
|
+
_userTyping = false;
|
|
9283
|
+
_displayValue = '';
|
|
9108
9284
|
_numberLogicValueChangeSub;
|
|
9109
9285
|
_delayBeforeStartAutoCountMs = 666;
|
|
9110
9286
|
// the 'speed gears' for auto counting
|
|
@@ -9119,12 +9295,13 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9119
9295
|
_autoCountTimeout;
|
|
9120
9296
|
_stepIncrementTimeout;
|
|
9121
9297
|
_startAutocountTimeout;
|
|
9122
|
-
constructor(formComponent, iconCacheService, overlayService, _ngZone, changeDetector, formUserChangeListener, ngZoneWrapper, elementRef) {
|
|
9298
|
+
constructor(formComponent, iconCacheService, overlayService, _ngZone, changeDetector, formUserChangeListener, _numberLocale, ngZoneWrapper, elementRef) {
|
|
9123
9299
|
super(changeDetector, overlayService, formUserChangeListener, ngZoneWrapper, elementRef);
|
|
9124
9300
|
this.formComponent = formComponent;
|
|
9125
9301
|
this.iconCacheService = iconCacheService;
|
|
9126
9302
|
this.overlayService = overlayService;
|
|
9127
9303
|
this._ngZone = _ngZone;
|
|
9304
|
+
this._numberLocale = _numberLocale;
|
|
9128
9305
|
this.ngZoneWrapper = ngZoneWrapper;
|
|
9129
9306
|
this.elementRef = elementRef;
|
|
9130
9307
|
this._numberLogicValueChangeSub = this.numberLogic.valueChange.subscribe((value) => {
|
|
@@ -9174,13 +9351,40 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9174
9351
|
if (this.myKeyDownWhiteList.find((k) => k === event.keyCode) === undefined) {
|
|
9175
9352
|
return false;
|
|
9176
9353
|
}
|
|
9354
|
+
const currentText = this.input ? this.input.value : String(this.model ?? '');
|
|
9355
|
+
if (event.key === '.' || event.key === ',') {
|
|
9356
|
+
// only one decimal separator, and only the locale one: normalize a foreign '.'/',' to it
|
|
9357
|
+
if (/[.,]/.test(currentText)) {
|
|
9358
|
+
return false;
|
|
9359
|
+
}
|
|
9360
|
+
if (event.key !== this._numberLocale.decimalSeparator) {
|
|
9361
|
+
if (this.input) {
|
|
9362
|
+
this._numberLocale.insertDecimalSeparator(this.input);
|
|
9363
|
+
}
|
|
9364
|
+
return false;
|
|
9365
|
+
}
|
|
9366
|
+
}
|
|
9367
|
+
// native text/number inputs ignore maxlength, so enforce maxLength (precision) and decimals (scale) here
|
|
9368
|
+
if (/^\d$/.test(event.key) && NumberUtils.WouldExceedDigitLimits(currentText, this.maxLength, this.decimals)) {
|
|
9369
|
+
return false;
|
|
9370
|
+
}
|
|
9371
|
+
}
|
|
9372
|
+
// precision/scale is enforced in keydown; the native maxlength on this text input would wrongly count
|
|
9373
|
+
// the decimal separator as a character (e.g. blocking "1234567,89" at maxLength 9), so don't set it.
|
|
9374
|
+
_setNativeMaxLength() {
|
|
9177
9375
|
}
|
|
9178
9376
|
handleBlur() {
|
|
9377
|
+
// normalize the display once editing stops (e.g. "12," -> "12", trailing zeros dropped)
|
|
9378
|
+
this._displayValue = this._numberLocale.format(this.model);
|
|
9179
9379
|
this.modelChange.next(this.model);
|
|
9180
9380
|
}
|
|
9181
|
-
handleChangeModel(
|
|
9381
|
+
handleChangeModel(text) {
|
|
9182
9382
|
this._changeFromButton = false;
|
|
9183
|
-
|
|
9383
|
+
// preserve exactly what the user typed while they are typing (avoids caret jumps / eating the separator)
|
|
9384
|
+
this._userTyping = true;
|
|
9385
|
+
this._displayValue = text === null || text === undefined ? '' : '' + text;
|
|
9386
|
+
this.numberLogic.setValue(this._numberLocale.parse(text));
|
|
9387
|
+
this._userTyping = false;
|
|
9184
9388
|
}
|
|
9185
9389
|
// Note: recursive through setTimeout().
|
|
9186
9390
|
doDecrementAuto() {
|
|
@@ -9282,7 +9486,7 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9282
9486
|
break;
|
|
9283
9487
|
}
|
|
9284
9488
|
}
|
|
9285
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputNumberPickerComponent, deps: [{ token: FormComponent, optional: true }, { token: IconCacheService }, { token: OverlayService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: FormInputUserModelChangeListenerService }, { token: NgZoneWrapperService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
9489
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InputNumberPickerComponent, deps: [{ token: FormComponent, optional: true }, { token: IconCacheService }, { token: OverlayService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: FormInputUserModelChangeListenerService }, { token: NumberLocaleService }, { token: NgZoneWrapperService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
9286
9490
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: InputNumberPickerComponent, isStandalone: false, selector: "co-input-number-picker", inputs: { model: "model", modelChangeOnEnter: "modelChangeOnEnter", showPermanentLabel: "showPermanentLabel", leftIconData: "leftIconData", min: "min", step: "step", max: "max", ngModelOptions: "ngModelOptions", minusIcon: "minusIcon", plusIcon: "plusIcon", buttonShowMode: "buttonShowMode", noValidation: "noValidation", decimals: "decimals" }, outputs: { modelChange: "modelChange", iconClick: "iconClick" }, host: { properties: { "class.has-icon": "this.leftIconData", "class.show-buttons-on-focus-only": "this.showButtonsOnFocusOnly", "class.has-label": "this.hasLabel", "class.co-input-number-picker": "this.showClass" } }, providers: [
|
|
9287
9491
|
OverlayService, {
|
|
9288
9492
|
provide: SCREEN_CONFIG_ADAPTER_COMPONENT_INTERFACE_NAME, useExisting: forwardRef(() => InputNumberPickerComponent)
|
|
@@ -9308,15 +9512,15 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9308
9512
|
</div>
|
|
9309
9513
|
<div class="input-wrapper">
|
|
9310
9514
|
@if (showPermanentLabel) {
|
|
9311
|
-
<span class='permanent-label' [textContent]="label"></span>
|
|
9515
|
+
<span class='permanent-label' [textContent]="label ?? ''"></span>
|
|
9312
9516
|
}
|
|
9313
|
-
<input type="
|
|
9517
|
+
<input type="text" inputmode="decimal"
|
|
9314
9518
|
[tabIndex]="readonly ? -1 : 0"
|
|
9315
|
-
[ngModel]="
|
|
9519
|
+
[ngModel]="displayValue"
|
|
9316
9520
|
[readonly]="readonly"
|
|
9317
9521
|
[disabled]="disabled"
|
|
9318
9522
|
[required]="required"
|
|
9319
|
-
[placeholder]="label"
|
|
9523
|
+
[placeholder]="label ?? ''"
|
|
9320
9524
|
(ngModelChange)="handleChangeModel($event)"
|
|
9321
9525
|
(keydown)="handleInputKeyDown($event)"
|
|
9322
9526
|
(blur)="handleBlur()"/>
|
|
@@ -9330,7 +9534,7 @@ class InputNumberPickerComponent extends BaseInputComponent {
|
|
|
9330
9534
|
(mouseup)="stopAutoCounting()" (mouseleave)="stopAutoCounting()"></co-button>
|
|
9331
9535
|
}
|
|
9332
9536
|
</div>
|
|
9333
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.
|
|
9537
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ButtonComponent, selector: "co-button", inputs: ["label", "iconData", "iconDataRight", "isToggleButton", "isToggled", "hidden", "disabled"], outputs: ["onClick", "clickedWhileDisabled", "isToggledChange"] }, { kind: "component", type: IconComponent, selector: "co-icon", inputs: ["icon", "iconData"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9334
9538
|
}
|
|
9335
9539
|
__decorate([
|
|
9336
9540
|
InputBoolean()
|
|
@@ -9357,15 +9561,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
9357
9561
|
</div>
|
|
9358
9562
|
<div class="input-wrapper">
|
|
9359
9563
|
@if (showPermanentLabel) {
|
|
9360
|
-
<span class='permanent-label' [textContent]="label"></span>
|
|
9564
|
+
<span class='permanent-label' [textContent]="label ?? ''"></span>
|
|
9361
9565
|
}
|
|
9362
|
-
<input type="
|
|
9566
|
+
<input type="text" inputmode="decimal"
|
|
9363
9567
|
[tabIndex]="readonly ? -1 : 0"
|
|
9364
|
-
[ngModel]="
|
|
9568
|
+
[ngModel]="displayValue"
|
|
9365
9569
|
[readonly]="readonly"
|
|
9366
9570
|
[disabled]="disabled"
|
|
9367
9571
|
[required]="required"
|
|
9368
|
-
[placeholder]="label"
|
|
9572
|
+
[placeholder]="label ?? ''"
|
|
9369
9573
|
(ngModelChange)="handleChangeModel($event)"
|
|
9370
9574
|
(keydown)="handleInputKeyDown($event)"
|
|
9371
9575
|
(blur)="handleBlur()"/>
|
|
@@ -9397,7 +9601,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
9397
9601
|
}] }, { type: IconCacheService, decorators: [{
|
|
9398
9602
|
type: Inject,
|
|
9399
9603
|
args: [IconCacheService]
|
|
9400
|
-
}] }, { type: OverlayService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: FormInputUserModelChangeListenerService }, { type: NgZoneWrapperService }, { type: i0.ElementRef }], propDecorators: { model: [{
|
|
9604
|
+
}] }, { type: OverlayService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: FormInputUserModelChangeListenerService }, { type: NumberLocaleService }, { type: NgZoneWrapperService }, { type: i0.ElementRef }], propDecorators: { model: [{
|
|
9401
9605
|
type: Input
|
|
9402
9606
|
}], modelChangeOnEnter: [{
|
|
9403
9607
|
type: Input
|
|
@@ -14110,7 +14314,7 @@ class ListOfValuesComponent extends BaseInputComponent {
|
|
|
14110
14314
|
collectionLoadFn;
|
|
14111
14315
|
collectionLoadFnProp;
|
|
14112
14316
|
leftIconData;
|
|
14113
|
-
searchPlaceholder;
|
|
14317
|
+
searchPlaceholder = '';
|
|
14114
14318
|
searchDisabled = false;
|
|
14115
14319
|
showChips = true;
|
|
14116
14320
|
showClass() {
|
|
@@ -16728,9 +16932,7 @@ class FilterItemModule {
|
|
|
16728
16932
|
ScrollingModule,
|
|
16729
16933
|
AppendPipeModule,
|
|
16730
16934
|
PrependPipeModule,
|
|
16731
|
-
InputTextModule,
|
|
16732
16935
|
InputRadioButtonModule,
|
|
16733
|
-
InputTextModule,
|
|
16734
16936
|
CoreComponentsTranslationModule,
|
|
16735
16937
|
InputDatePickerModule,
|
|
16736
16938
|
InputDateRangePickerModule], exports: [FilterItemComponent] });
|
|
@@ -16742,9 +16944,7 @@ class FilterItemModule {
|
|
|
16742
16944
|
ScrollingModule,
|
|
16743
16945
|
AppendPipeModule,
|
|
16744
16946
|
PrependPipeModule,
|
|
16745
|
-
InputTextModule,
|
|
16746
16947
|
InputRadioButtonModule,
|
|
16747
|
-
InputTextModule,
|
|
16748
16948
|
CoreComponentsTranslationModule,
|
|
16749
16949
|
InputDatePickerModule,
|
|
16750
16950
|
InputDateRangePickerModule] });
|
|
@@ -16761,9 +16961,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
16761
16961
|
ScrollingModule,
|
|
16762
16962
|
AppendPipeModule,
|
|
16763
16963
|
PrependPipeModule,
|
|
16764
|
-
InputTextModule,
|
|
16765
16964
|
InputRadioButtonModule,
|
|
16766
|
-
InputTextModule,
|
|
16767
16965
|
CoreComponentsTranslationModule,
|
|
16768
16966
|
InputDatePickerModule,
|
|
16769
16967
|
InputDateRangePickerModule
|