@ptsecurity/mosaic 15.9.3 → 15.9.5
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/datepicker/calendar-header.component.d.ts +13 -13
- package/datepicker/datepicker-input.directive.d.ts +10 -0
- package/esm2020/core/version.mjs +2 -2
- package/esm2020/datepicker/calendar-header.component.mjs +42 -13
- package/esm2020/datepicker/datepicker-input.directive.mjs +103 -23
- package/esm2020/input/input-number.mjs +196 -41
- package/fesm2015/ptsecurity-mosaic-core.mjs +1 -1
- package/fesm2015/ptsecurity-mosaic-core.mjs.map +1 -1
- package/fesm2015/ptsecurity-mosaic-datepicker.mjs +143 -34
- package/fesm2015/ptsecurity-mosaic-datepicker.mjs.map +1 -1
- package/fesm2015/ptsecurity-mosaic-input.mjs +198 -41
- package/fesm2015/ptsecurity-mosaic-input.mjs.map +1 -1
- package/fesm2020/ptsecurity-mosaic-core.mjs +1 -1
- package/fesm2020/ptsecurity-mosaic-core.mjs.map +1 -1
- package/fesm2020/ptsecurity-mosaic-datepicker.mjs +143 -34
- package/fesm2020/ptsecurity-mosaic-datepicker.mjs.map +1 -1
- package/fesm2020/ptsecurity-mosaic-input.mjs +195 -40
- package/fesm2020/ptsecurity-mosaic-input.mjs.map +1 -1
- package/input/input-number.d.ts +50 -10
- package/package.json +4 -4
@@ -2,17 +2,17 @@ import * as i3$1 from '@angular/cdk/a11y';
|
|
2
2
|
import { A11yModule } from '@angular/cdk/a11y';
|
3
3
|
import { CommonModule } from '@angular/common';
|
4
4
|
import * as i0 from '@angular/core';
|
5
|
-
import {
|
5
|
+
import { forwardRef, EventEmitter, Directive, Attribute, Input, InjectionToken, Optional, Self, Inject, Component, ChangeDetectionStrategy, ViewEncapsulation, NgModule } from '@angular/core';
|
6
6
|
import * as i1 from '@angular/forms';
|
7
|
-
import { NG_VALIDATORS, Validators, FormsModule } from '@angular/forms';
|
7
|
+
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, Validators, FormsModule } from '@angular/forms';
|
8
8
|
import * as i3 from '@ptsecurity/mosaic/core';
|
9
9
|
import { mixinErrorState, PopUpTriggers, McCommonModule } from '@ptsecurity/mosaic/core';
|
10
10
|
import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
|
11
11
|
import { getSupportedInputTypes } from '@angular/cdk/platform';
|
12
12
|
import * as i4 from '@ptsecurity/mosaic/form-field';
|
13
13
|
import { McFormFieldControl } from '@ptsecurity/mosaic/form-field';
|
14
|
-
import { Subject } from 'rxjs';
|
15
|
-
import { A, C, V, X, Z,
|
14
|
+
import { Subject, Subscription } from 'rxjs';
|
15
|
+
import { A, C, V, X, Z, NUMPAD_MINUS, DASH, FF_MINUS, DELETE, BACKSPACE, TAB, ESCAPE, ENTER, LEFT_ARROW, RIGHT_ARROW, HOME, END, isFunctionKey, isNumberKey, isNumpadKey, UP_ARROW, DOWN_ARROW } from '@ptsecurity/cdk/keycodes';
|
16
16
|
import * as i2 from '@angular/cdk/bidi';
|
17
17
|
import * as i1$1 from '@angular/cdk/overlay';
|
18
18
|
import { McTooltipTrigger, MC_TOOLTIP_SCROLL_STRATEGY } from '@ptsecurity/mosaic/tooltip';
|
@@ -23,6 +23,7 @@ function getMcInputUnsupportedTypeError(inputType) {
|
|
23
23
|
|
24
24
|
const BIG_STEP = 10;
|
25
25
|
const SMALL_STEP = 1;
|
26
|
+
// TODO: подставлять локализованный сплиттер
|
26
27
|
function normalizeSplitter(value) {
|
27
28
|
return value ? value.replace(/,/g, '.') : value;
|
28
29
|
}
|
@@ -46,16 +47,33 @@ function add(value1, value2) {
|
|
46
47
|
const precision = Math.max(getPrecision(value1), getPrecision(value2));
|
47
48
|
return (value1 * precision + value2 * precision) / precision;
|
48
49
|
}
|
50
|
+
const MC_NUMBER_INPUT_VALUE_ACCESSOR = {
|
51
|
+
provide: NG_VALUE_ACCESSOR,
|
52
|
+
useExisting: forwardRef(() => McNumberInput),
|
53
|
+
multi: true
|
54
|
+
};
|
49
55
|
class McNumberInput {
|
50
|
-
constructor(elementRef,
|
56
|
+
constructor(elementRef, renderer, step, bigStep, min, max) {
|
51
57
|
this.elementRef = elementRef;
|
52
|
-
this.
|
53
|
-
|
58
|
+
this.renderer = renderer;
|
59
|
+
/** Emits when the value changes (either due to user input or programmatic change). */
|
60
|
+
this.valueChange = new EventEmitter();
|
61
|
+
/** Emits when the disabled state has changed */
|
62
|
+
this.disabledChange = new EventEmitter();
|
54
63
|
this.stateChanges = new Subject();
|
64
|
+
this.controlType = 'input-number';
|
65
|
+
this._disabled = false;
|
66
|
+
this.focused = false;
|
67
|
+
this.localeSubscription = Subscription.EMPTY;
|
68
|
+
// tslint:disable-next-line:no-empty
|
69
|
+
this.onTouched = () => { };
|
70
|
+
// tslint:disable-next-line:no-empty
|
71
|
+
this.cvaOnChange = () => { };
|
55
72
|
this.step = isDigit(step) ? parseFloat(step) : SMALL_STEP;
|
56
73
|
this.bigStep = isDigit(bigStep) ? parseFloat(bigStep) : BIG_STEP;
|
57
74
|
this.min = isDigit(min) ? parseFloat(min) : -Infinity;
|
58
75
|
this.max = isDigit(max) ? parseFloat(max) : Infinity;
|
76
|
+
setTimeout(() => this.nativeElement.type = 'text', 0);
|
59
77
|
if ('valueAsNumber' in this.nativeElement) {
|
60
78
|
Object.defineProperty(Object.getPrototypeOf(this.nativeElement), 'valueAsNumber', {
|
61
79
|
// tslint:disable-next-line:no-reserved-keywords
|
@@ -66,9 +84,71 @@ class McNumberInput {
|
|
66
84
|
});
|
67
85
|
}
|
68
86
|
}
|
87
|
+
get value() {
|
88
|
+
return this._value;
|
89
|
+
}
|
90
|
+
set value(value) {
|
91
|
+
const oldValue = this.value;
|
92
|
+
this._value = value;
|
93
|
+
if (oldValue !== value) {
|
94
|
+
this.setViewValue(this.formatNumber(value));
|
95
|
+
this.valueChange.emit(value);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
get disabled() {
|
99
|
+
return this._disabled;
|
100
|
+
}
|
101
|
+
set disabled(value) {
|
102
|
+
const newValue = coerceBooleanProperty(value);
|
103
|
+
const element = this.nativeElement;
|
104
|
+
if (this._disabled !== newValue) {
|
105
|
+
this._disabled = newValue;
|
106
|
+
this.disabledChange.emit(newValue);
|
107
|
+
}
|
108
|
+
// We need to null check the `blur` method, because it's undefined during SSR.
|
109
|
+
if (newValue && element.blur) {
|
110
|
+
// Normally, native input elements automatically blur if they turn disabled. This behavior
|
111
|
+
// is problematic, because it would mean that it triggers another change detection cycle,
|
112
|
+
// which then causes a changed after checked error if the input element was focused before.
|
113
|
+
element.blur();
|
114
|
+
}
|
115
|
+
}
|
69
116
|
get nativeElement() {
|
70
117
|
return this.elementRef.nativeElement;
|
71
118
|
}
|
119
|
+
get viewValue() {
|
120
|
+
return this.nativeElement.value;
|
121
|
+
}
|
122
|
+
get ngControl() {
|
123
|
+
return this.control;
|
124
|
+
}
|
125
|
+
ngOnDestroy() {
|
126
|
+
this.localeSubscription.unsubscribe();
|
127
|
+
this.valueChange.complete();
|
128
|
+
this.disabledChange.complete();
|
129
|
+
}
|
130
|
+
onContainerClick() {
|
131
|
+
this.focus();
|
132
|
+
}
|
133
|
+
focus() {
|
134
|
+
this.nativeElement.focus();
|
135
|
+
}
|
136
|
+
// Implemented as part of ControlValueAccessor.
|
137
|
+
writeValue(value) {
|
138
|
+
this.value = value;
|
139
|
+
}
|
140
|
+
// Implemented as part of ControlValueAccessor.
|
141
|
+
registerOnChange(fn) {
|
142
|
+
this.cvaOnChange = fn;
|
143
|
+
}
|
144
|
+
// Implemented as part of ControlValueAccessor.
|
145
|
+
registerOnTouched(fn) {
|
146
|
+
this.onTouched = fn;
|
147
|
+
}
|
148
|
+
// Implemented as part of ControlValueAccessor.
|
149
|
+
setDisabledState(isDisabled) {
|
150
|
+
this.disabled = isDisabled;
|
151
|
+
}
|
72
152
|
focusChanged(isFocused) {
|
73
153
|
if (isFocused !== this.focused) {
|
74
154
|
this.focused = isFocused;
|
@@ -83,32 +163,31 @@ class McNumberInput {
|
|
83
163
|
const isCtrlV = (e) => e.keyCode === V && (e.ctrlKey || e.metaKey);
|
84
164
|
const isCtrlX = (e) => e.keyCode === X && (e.ctrlKey || e.metaKey);
|
85
165
|
const isCtrlZ = (e) => e.keyCode === Z && (e.ctrlKey || e.metaKey);
|
86
|
-
const isFKey = (e) => e.keyCode >= F1 && e.keyCode <= F12;
|
87
|
-
const isNumber = (e) => (e.keyCode >= ZERO && e.keyCode <= NINE) ||
|
88
|
-
(e.keyCode >= NUMPAD_ZERO && e.keyCode <= NUMPAD_NINE);
|
89
166
|
const isPeriod = (e) => e.key === '.' || e.key === ',';
|
90
167
|
const minuses = [NUMPAD_MINUS, DASH, FF_MINUS];
|
91
168
|
const serviceKeys = [DELETE, BACKSPACE, TAB, ESCAPE, ENTER];
|
92
169
|
const arrows = [LEFT_ARROW, RIGHT_ARROW];
|
93
170
|
const allowedKeys = [HOME, END].concat(arrows).concat(serviceKeys).concat(minuses);
|
94
171
|
if (minuses.includes(keyCode) &&
|
95
|
-
(this.
|
172
|
+
(this.viewValue.includes(event.key) || this.min >= 0)) {
|
96
173
|
event.preventDefault();
|
97
174
|
return;
|
98
175
|
}
|
99
176
|
if (allowedKeys.indexOf(keyCode) !== -1 ||
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
177
|
+
[
|
178
|
+
isCtrlA,
|
179
|
+
isCtrlC,
|
180
|
+
isCtrlV,
|
181
|
+
isCtrlX,
|
182
|
+
isCtrlZ,
|
183
|
+
isFunctionKey,
|
184
|
+
isPeriod
|
185
|
+
].some((fn) => fn(event))) {
|
107
186
|
// let it happen, don't do anything
|
108
187
|
return;
|
109
188
|
}
|
110
189
|
// Ensure that it is not a number and stop the keypress
|
111
|
-
if (event.shiftKey || !
|
190
|
+
if (event.shiftKey || !isNumberKey(event) && !isNumpadKey(event)) {
|
112
191
|
event.preventDefault();
|
113
192
|
// process steps
|
114
193
|
const step = event.shiftKey ? this.bigStep : this.step;
|
@@ -120,48 +199,120 @@ class McNumberInput {
|
|
120
199
|
}
|
121
200
|
}
|
122
201
|
}
|
202
|
+
onInput(event) {
|
203
|
+
const currentValueLength = this.formatNumber(this.value)?.length || 0;
|
204
|
+
setTimeout(() => {
|
205
|
+
const fromPaste = event.inputType === 'insertFromPaste';
|
206
|
+
let formattedValue;
|
207
|
+
if (fromPaste) {
|
208
|
+
formattedValue = this.formatNumber(this.valueFromPaste);
|
209
|
+
}
|
210
|
+
else {
|
211
|
+
/*this.viewValue is raw and should be reformatted to localized number */
|
212
|
+
formattedValue = this.formatViewValue();
|
213
|
+
const offsetWhenSeparatorAdded = 2;
|
214
|
+
Promise.resolve().then(() => {
|
215
|
+
if (Math.abs(this.viewValue.length - currentValueLength) === offsetWhenSeparatorAdded) {
|
216
|
+
const cursorPosition = Math.max(0, (this.nativeElement.selectionStart || 0) + Math.sign(this.viewValue.length - currentValueLength));
|
217
|
+
this.renderer.setProperty(this.nativeElement, 'selectionStart', cursorPosition);
|
218
|
+
this.renderer.setProperty(this.nativeElement, 'selectionEnd', cursorPosition);
|
219
|
+
}
|
220
|
+
});
|
221
|
+
}
|
222
|
+
this.setViewValue(formattedValue, !fromPaste);
|
223
|
+
this.viewToModelUpdate(formattedValue);
|
224
|
+
});
|
225
|
+
}
|
123
226
|
onPaste(event) {
|
124
|
-
|
227
|
+
this.valueFromPaste = this.checkAndNormalizeLocalizedNumber(event.clipboardData?.getData('text'));
|
228
|
+
if (this.valueFromPaste === null) {
|
125
229
|
event.preventDefault();
|
126
230
|
}
|
127
231
|
}
|
128
232
|
stepUp(step) {
|
129
|
-
this.
|
130
|
-
const res = Math.max(Math.min(add(this.
|
131
|
-
this.
|
132
|
-
this.
|
233
|
+
this.nativeElement.focus();
|
234
|
+
const res = Math.max(Math.min(add(this.value || 0, step), this.max), this.min);
|
235
|
+
this.setViewValue(this.formatNumber(res));
|
236
|
+
this._value = res;
|
237
|
+
this.cvaOnChange(res);
|
238
|
+
this.valueChange.emit(res);
|
133
239
|
}
|
134
240
|
stepDown(step) {
|
135
|
-
this.
|
136
|
-
const res = Math.min(Math.max(add(this.
|
137
|
-
this.
|
138
|
-
this.
|
241
|
+
this.nativeElement.focus();
|
242
|
+
const res = Math.min(Math.max(add(this.value || 0, -step), this.min), this.max);
|
243
|
+
this.setViewValue(this.formatNumber(res));
|
244
|
+
this._value = res;
|
245
|
+
this.cvaOnChange(res);
|
246
|
+
this.valueChange.emit(res);
|
247
|
+
}
|
248
|
+
setViewValue(value, savePosition = false) {
|
249
|
+
const cursorPosition = this.nativeElement.selectionStart;
|
250
|
+
this.renderer.setProperty(this.nativeElement, 'value', value);
|
251
|
+
if (savePosition) {
|
252
|
+
this.renderer.setProperty(this.nativeElement, 'selectionStart', cursorPosition);
|
253
|
+
this.renderer.setProperty(this.nativeElement, 'selectionEnd', cursorPosition);
|
254
|
+
}
|
139
255
|
}
|
140
|
-
viewToModelUpdate(
|
141
|
-
|
142
|
-
|
256
|
+
viewToModelUpdate(newValue) {
|
257
|
+
const normalizedValue = newValue === null ? null : +this.normalizeNumber(newValue);
|
258
|
+
if (normalizedValue !== this.value) {
|
259
|
+
this._value = normalizedValue;
|
260
|
+
this.cvaOnChange(normalizedValue);
|
261
|
+
this.valueChange.emit(normalizedValue);
|
262
|
+
}
|
263
|
+
this.ngControl?.updateValueAndValidity({ emitEvent: false });
|
264
|
+
}
|
265
|
+
formatViewValue() {
|
266
|
+
if (this.viewValue === null || this.viewValue === '' || Number.isNaN(+this.normalizeNumber(this.viewValue))) {
|
267
|
+
return null;
|
268
|
+
}
|
269
|
+
return this.viewValue;
|
270
|
+
}
|
271
|
+
formatNumber(value) {
|
272
|
+
if (value === null || value === undefined) {
|
273
|
+
return null;
|
274
|
+
}
|
275
|
+
return value.toString();
|
276
|
+
}
|
277
|
+
/**
|
278
|
+
* Method that returns a string representation of a number without localized separators
|
279
|
+
*/
|
280
|
+
normalizeNumber(value, _) {
|
281
|
+
if (value === null || value === undefined) {
|
282
|
+
return '';
|
283
|
+
}
|
284
|
+
return value.toString();
|
285
|
+
}
|
286
|
+
checkAndNormalizeLocalizedNumber(num) {
|
287
|
+
if (num === null || num === undefined) {
|
288
|
+
return null;
|
289
|
+
}
|
290
|
+
/* if some locale input config satisfies pasted number, try to normalise with selected locale config */
|
291
|
+
let numberOutput = null;
|
292
|
+
const normalized = +this.normalizeNumber(num);
|
293
|
+
if (!Number.isNaN(normalized)) {
|
294
|
+
numberOutput = normalized;
|
143
295
|
}
|
296
|
+
return numberOutput;
|
144
297
|
}
|
145
298
|
}
|
146
|
-
/** @nocollapse */ McNumberInput.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: McNumberInput, deps: [{ token: i0.ElementRef }, { token:
|
147
|
-
/** @nocollapse */ McNumberInput.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: McNumberInput, selector: "input[mcInput][type=\"number\"]", inputs: { bigStep: "bigStep", step: "step", min: "min", max: "max" }, host: { listeners: { "blur": "focusChanged(false)", "focus": "focusChanged(true)", "paste": "onPaste($event)", "keydown": "onKeyDown($event)" } }, exportAs: ["mcNumericalInput"], ngImport: i0 });
|
299
|
+
/** @nocollapse */ McNumberInput.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: McNumberInput, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: 'step', attribute: true }, { token: 'big-step', attribute: true }, { token: 'min', attribute: true }, { token: 'max', attribute: true }], target: i0.ɵɵFactoryTarget.Directive });
|
300
|
+
/** @nocollapse */ McNumberInput.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: McNumberInput, selector: "input[mcInput][type=\"number\"]", inputs: { bigStep: "bigStep", step: "step", min: "min", max: "max", value: "value", disabled: "disabled" }, host: { listeners: { "blur": "focusChanged(false)", "focus": "focusChanged(true)", "paste": "onPaste($event)", "keydown": "onKeyDown($event)", "input": "onInput($event)" } }, providers: [MC_NUMBER_INPUT_VALUE_ACCESSOR], exportAs: ["mcNumericalInput"], ngImport: i0 });
|
148
301
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: McNumberInput, decorators: [{
|
149
302
|
type: Directive,
|
150
303
|
args: [{
|
151
304
|
selector: `input[mcInput][type="number"]`,
|
152
305
|
exportAs: 'mcNumericalInput',
|
306
|
+
providers: [MC_NUMBER_INPUT_VALUE_ACCESSOR],
|
153
307
|
host: {
|
154
308
|
'(blur)': 'focusChanged(false)',
|
155
309
|
'(focus)': 'focusChanged(true)',
|
156
310
|
'(paste)': 'onPaste($event)',
|
157
|
-
'(keydown)': 'onKeyDown($event)'
|
311
|
+
'(keydown)': 'onKeyDown($event)',
|
312
|
+
'(input)': 'onInput($event)'
|
158
313
|
}
|
159
314
|
}]
|
160
|
-
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type:
|
161
|
-
type: Optional
|
162
|
-
}, {
|
163
|
-
type: Self
|
164
|
-
}] }, { type: undefined, decorators: [{
|
315
|
+
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: undefined, decorators: [{
|
165
316
|
type: Attribute,
|
166
317
|
args: ['step']
|
167
318
|
}] }, { type: undefined, decorators: [{
|
@@ -181,6 +332,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
|
|
181
332
|
type: Input
|
182
333
|
}], max: [{
|
183
334
|
type: Input
|
335
|
+
}], value: [{
|
336
|
+
type: Input
|
337
|
+
}], disabled: [{
|
338
|
+
type: Input
|
184
339
|
}] } });
|
185
340
|
|
186
341
|
const MC_INPUT_VALUE_ACCESSOR = new InjectionToken('MC_INPUT_VALUE_ACCESSOR');
|
@@ -934,5 +1089,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
|
|
934
1089
|
* Generated bundle index. Do not edit.
|
935
1090
|
*/
|
936
1091
|
|
937
|
-
export { BIG_STEP, MAX_VALIDATOR, MC_INPUT_VALUE_ACCESSOR, MIN_VALIDATOR, MaxValidator, McInput, McInputBase, McInputMixinBase, McInputModule, McInputMono, McInputPassword, McNumberInput, McPasswordToggle, MinValidator, SMALL_STEP, add, getPrecision, isDigit, isFloat, isInt, normalizeSplitter };
|
1092
|
+
export { BIG_STEP, MAX_VALIDATOR, MC_INPUT_VALUE_ACCESSOR, MC_NUMBER_INPUT_VALUE_ACCESSOR, MIN_VALIDATOR, MaxValidator, McInput, McInputBase, McInputMixinBase, McInputModule, McInputMono, McInputPassword, McNumberInput, McPasswordToggle, MinValidator, SMALL_STEP, add, getPrecision, isDigit, isFloat, isInt, normalizeSplitter };
|
938
1093
|
//# sourceMappingURL=ptsecurity-mosaic-input.mjs.map
|