@progress/kendo-angular-inputs 21.4.1 → 22.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/colorpicker/localization/messages.d.ts +1 -1
  2. package/common/radio-checkbox.base.d.ts +1 -1
  3. package/fesm2022/progress-kendo-angular-inputs.mjs +321 -321
  4. package/numerictextbox/localization/messages.d.ts +1 -1
  5. package/otpinput/localization/messages.d.ts +1 -1
  6. package/package.json +17 -25
  7. package/rangeslider/localization/messages.d.ts +1 -1
  8. package/signature/localization/messages.d.ts +1 -1
  9. package/slider/localization/messages.d.ts +1 -1
  10. package/sliders-common/slider-base.d.ts +1 -1
  11. package/switch/localization/messages.d.ts +1 -1
  12. package/text-fields-common/text-fields-base.d.ts +1 -1
  13. package/textbox/localization/messages.d.ts +1 -1
  14. package/esm2022/checkbox/checkbox.component.mjs +0 -227
  15. package/esm2022/checkbox/checkbox.directive.mjs +0 -96
  16. package/esm2022/checkbox/checked-state.mjs +0 -5
  17. package/esm2022/checkbox.module.mjs +0 -42
  18. package/esm2022/colorpicker/adaptiveness/adaptive-close-button.component.mjs +0 -62
  19. package/esm2022/colorpicker/adaptiveness/adaptive-renderer.component.mjs +0 -219
  20. package/esm2022/colorpicker/color-contrast-svg.component.mjs +0 -108
  21. package/esm2022/colorpicker/color-gradient-numeric-label.directive.mjs +0 -37
  22. package/esm2022/colorpicker/color-gradient-text-label.directive.mjs +0 -34
  23. package/esm2022/colorpicker/color-gradient.component.mjs +0 -1110
  24. package/esm2022/colorpicker/color-input.component.mjs +0 -498
  25. package/esm2022/colorpicker/color-palette.component.mjs +0 -629
  26. package/esm2022/colorpicker/colorpicker.component.mjs +0 -1315
  27. package/esm2022/colorpicker/constants.mjs +0 -40
  28. package/esm2022/colorpicker/contrast-validation.component.mjs +0 -83
  29. package/esm2022/colorpicker/contrast.component.mjs +0 -114
  30. package/esm2022/colorpicker/events/active-color-click-event.mjs +0 -55
  31. package/esm2022/colorpicker/events/cancel-event.mjs +0 -18
  32. package/esm2022/colorpicker/events/close-event.mjs +0 -10
  33. package/esm2022/colorpicker/events/kendo-drag-event.mjs +0 -5
  34. package/esm2022/colorpicker/events/open-event.mjs +0 -10
  35. package/esm2022/colorpicker/events.mjs +0 -8
  36. package/esm2022/colorpicker/flatcolorpicker-actions.component.mjs +0 -112
  37. package/esm2022/colorpicker/flatcolorpicker-header.component.mjs +0 -244
  38. package/esm2022/colorpicker/flatcolorpicker.component.mjs +0 -942
  39. package/esm2022/colorpicker/localization/colorgradient-localization.service.mjs +0 -46
  40. package/esm2022/colorpicker/localization/colorpalette-localization.service.mjs +0 -46
  41. package/esm2022/colorpicker/localization/colorpicker-localization.service.mjs +0 -31
  42. package/esm2022/colorpicker/localization/custom-messages.component.mjs +0 -51
  43. package/esm2022/colorpicker/localization/flatcolorpicker-localization.service.mjs +0 -46
  44. package/esm2022/colorpicker/localization/localized-colorpicker-messages.directive.mjs +0 -39
  45. package/esm2022/colorpicker/localization/messages.mjs +0 -201
  46. package/esm2022/colorpicker/models/actions-layout.mjs +0 -5
  47. package/esm2022/colorpicker/models/adaptive-mode.mjs +0 -8
  48. package/esm2022/colorpicker/models/colorpicker-view.mjs +0 -5
  49. package/esm2022/colorpicker/models/gradient-settings.mjs +0 -5
  50. package/esm2022/colorpicker/models/hsva.mjs +0 -5
  51. package/esm2022/colorpicker/models/output-format.mjs +0 -5
  52. package/esm2022/colorpicker/models/palette-presets.mjs +0 -62
  53. package/esm2022/colorpicker/models/palette-settings.mjs +0 -5
  54. package/esm2022/colorpicker/models/popup-settings.mjs +0 -5
  55. package/esm2022/colorpicker/models/rgb.mjs +0 -5
  56. package/esm2022/colorpicker/models/rgba.mjs +0 -5
  57. package/esm2022/colorpicker/models/table-cell.mjs +0 -5
  58. package/esm2022/colorpicker/models/tile-size.mjs +0 -5
  59. package/esm2022/colorpicker/models.mjs +0 -16
  60. package/esm2022/colorpicker/services/color-palette.service.mjs +0 -65
  61. package/esm2022/colorpicker/services/flatcolorpicker.service.mjs +0 -39
  62. package/esm2022/colorpicker/utils/color-parser.mjs +0 -164
  63. package/esm2022/colorpicker/utils/contrast-curve.mjs +0 -85
  64. package/esm2022/colorpicker/utils.mjs +0 -6
  65. package/esm2022/colorpicker.module.mjs +0 -50
  66. package/esm2022/common/dom-utils.mjs +0 -36
  67. package/esm2022/common/formservice.service.mjs +0 -21
  68. package/esm2022/common/math.mjs +0 -65
  69. package/esm2022/common/models/fillmode.mjs +0 -5
  70. package/esm2022/common/models/gutters.mjs +0 -5
  71. package/esm2022/common/models/responsive-breakpoints.mjs +0 -5
  72. package/esm2022/common/models/rounded.mjs +0 -5
  73. package/esm2022/common/models/size.mjs +0 -5
  74. package/esm2022/common/models/styling-classes.mjs +0 -5
  75. package/esm2022/common/models/type.mjs +0 -5
  76. package/esm2022/common/models.mjs +0 -9
  77. package/esm2022/common/radio-checkbox.base.mjs +0 -295
  78. package/esm2022/common/utils.mjs +0 -88
  79. package/esm2022/directives.mjs +0 -430
  80. package/esm2022/form/form.component.mjs +0 -163
  81. package/esm2022/form/formseparator.component.mjs +0 -80
  82. package/esm2022/form/utils.mjs +0 -147
  83. package/esm2022/form.module.mjs +0 -46
  84. package/esm2022/formfield/error.component.mjs +0 -70
  85. package/esm2022/formfield/formfield.component.mjs +0 -353
  86. package/esm2022/formfield/hint.component.mjs +0 -65
  87. package/esm2022/formfield/models/message-align.mjs +0 -5
  88. package/esm2022/formfield/models/orientation.mjs +0 -5
  89. package/esm2022/formfield/models/show-options.mjs +0 -5
  90. package/esm2022/formfield.module.mjs +0 -43
  91. package/esm2022/formfieldset/formfieldset.component.mjs +0 -174
  92. package/esm2022/index.mjs +0 -91
  93. package/esm2022/inputs.module.mjs +0 -91
  94. package/esm2022/maskedtextbox/maskedtextbox.component.mjs +0 -876
  95. package/esm2022/maskedtextbox/masking.service.mjs +0 -189
  96. package/esm2022/maskedtextbox/parsing/combinators.mjs +0 -28
  97. package/esm2022/maskedtextbox/parsing/parsers.mjs +0 -148
  98. package/esm2022/maskedtextbox/parsing/result.mjs +0 -44
  99. package/esm2022/maskedtextbox/parsing/stream.mjs +0 -43
  100. package/esm2022/maskedtextbox.module.mjs +0 -43
  101. package/esm2022/numerictextbox/arrow-direction.mjs +0 -13
  102. package/esm2022/numerictextbox/constants.mjs +0 -28
  103. package/esm2022/numerictextbox/localization/custom-messages.component.mjs +0 -55
  104. package/esm2022/numerictextbox/localization/localized-numerictextbox-messages.directive.mjs +0 -39
  105. package/esm2022/numerictextbox/localization/messages.mjs +0 -33
  106. package/esm2022/numerictextbox/numerictextbox.component.mjs +0 -1314
  107. package/esm2022/numerictextbox/utils.mjs +0 -92
  108. package/esm2022/numerictextbox.module.mjs +0 -46
  109. package/esm2022/otp.module.mjs +0 -44
  110. package/esm2022/otpinput/localization/custom-messages.component.mjs +0 -45
  111. package/esm2022/otpinput/localization/localized-textbox-messages.directive.mjs +0 -39
  112. package/esm2022/otpinput/localization/messages.mjs +0 -34
  113. package/esm2022/otpinput/models/otpinput-type.mjs +0 -5
  114. package/esm2022/otpinput/models/separator-icon.mjs +0 -5
  115. package/esm2022/otpinput/otpinput-separator.component.mjs +0 -93
  116. package/esm2022/otpinput/otpinput.component.mjs +0 -936
  117. package/esm2022/package-metadata.mjs +0 -16
  118. package/esm2022/progress-kendo-angular-inputs.mjs +0 -8
  119. package/esm2022/radiobutton/radiobutton.component.mjs +0 -212
  120. package/esm2022/radiobutton/radiobutton.directive.mjs +0 -81
  121. package/esm2022/radiobutton.module.mjs +0 -43
  122. package/esm2022/rangeslider/localization/custom-messages.component.mjs +0 -53
  123. package/esm2022/rangeslider/localization/localized-rangeslider-messages.directive.mjs +0 -39
  124. package/esm2022/rangeslider/localization/messages.mjs +0 -33
  125. package/esm2022/rangeslider/rangeslider-model.mjs +0 -53
  126. package/esm2022/rangeslider/rangeslider-value.type.mjs +0 -5
  127. package/esm2022/rangeslider/rangeslider.component.mjs +0 -625
  128. package/esm2022/rangeslider.module.mjs +0 -46
  129. package/esm2022/rating/directives/rating-hovered-item.directive.mjs +0 -35
  130. package/esm2022/rating/directives/rating-item.directive.mjs +0 -34
  131. package/esm2022/rating/directives/rating-selected-item.directive.mjs +0 -36
  132. package/esm2022/rating/models/precision.mjs +0 -5
  133. package/esm2022/rating/models/rating-item.interface.mjs +0 -5
  134. package/esm2022/rating/models/selection.mjs +0 -5
  135. package/esm2022/rating/rating.component.mjs +0 -754
  136. package/esm2022/rating.module.mjs +0 -46
  137. package/esm2022/shared/input-separator.component.mjs +0 -55
  138. package/esm2022/shared/input-spacer.component.mjs +0 -56
  139. package/esm2022/shared/shared-events.directive.mjs +0 -102
  140. package/esm2022/shared/utils.mjs +0 -13
  141. package/esm2022/signature/events/close-event.mjs +0 -10
  142. package/esm2022/signature/events/index.mjs +0 -6
  143. package/esm2022/signature/events/open-event.mjs +0 -10
  144. package/esm2022/signature/localization/custom-messages.component.mjs +0 -43
  145. package/esm2022/signature/localization/index.mjs +0 -7
  146. package/esm2022/signature/localization/localized-signature-messages.directive.mjs +0 -39
  147. package/esm2022/signature/localization/messages.mjs +0 -45
  148. package/esm2022/signature/signature.component.mjs +0 -981
  149. package/esm2022/signature.module.mjs +0 -47
  150. package/esm2022/slider/localization/custom-messages.component.mjs +0 -43
  151. package/esm2022/slider/localization/localized-slider-messages.directive.mjs +0 -39
  152. package/esm2022/slider/localization/messages.mjs +0 -39
  153. package/esm2022/slider/slider-model.mjs +0 -32
  154. package/esm2022/slider/slider.component.mjs +0 -671
  155. package/esm2022/slider.module.mjs +0 -48
  156. package/esm2022/sliders-common/label-template.directive.mjs +0 -37
  157. package/esm2022/sliders-common/slider-base.mjs +0 -300
  158. package/esm2022/sliders-common/slider-model.base.mjs +0 -118
  159. package/esm2022/sliders-common/slider-ticks.component.mjs +0 -147
  160. package/esm2022/sliders-common/sliders-util.mjs +0 -206
  161. package/esm2022/sliders-common/title-callback.mjs +0 -5
  162. package/esm2022/switch/events/blur-event.mjs +0 -13
  163. package/esm2022/switch/events/focus-event.mjs +0 -13
  164. package/esm2022/switch/localization/custom-messages.component.mjs +0 -43
  165. package/esm2022/switch/localization/localized-switch-messages.directive.mjs +0 -39
  166. package/esm2022/switch/localization/messages.mjs +0 -33
  167. package/esm2022/switch/switch.component.mjs +0 -585
  168. package/esm2022/switch.module.mjs +0 -44
  169. package/esm2022/text-fields-common/text-fields-base.mjs +0 -150
  170. package/esm2022/textarea/models/adornments-orientation.mjs +0 -5
  171. package/esm2022/textarea/models/flow.mjs +0 -5
  172. package/esm2022/textarea/models/resize.mjs +0 -5
  173. package/esm2022/textarea/models/textarea-settings.mjs +0 -5
  174. package/esm2022/textarea/textarea-prefix.component.mjs +0 -67
  175. package/esm2022/textarea/textarea-suffix.component.mjs +0 -67
  176. package/esm2022/textarea/textarea.component.mjs +0 -740
  177. package/esm2022/textarea/textarea.directive.mjs +0 -288
  178. package/esm2022/textarea.module.mjs +0 -46
  179. package/esm2022/textbox/localization/custom-messages.component.mjs +0 -43
  180. package/esm2022/textbox/localization/localized-textbox-messages.directive.mjs +0 -39
  181. package/esm2022/textbox/localization/messages.mjs +0 -27
  182. package/esm2022/textbox/models/icon-show-options.mjs +0 -5
  183. package/esm2022/textbox/textbox-prefix.directive.mjs +0 -50
  184. package/esm2022/textbox/textbox-suffix.directive.mjs +0 -49
  185. package/esm2022/textbox/textbox.component.mjs +0 -933
  186. package/esm2022/textbox/textbox.directive.mjs +0 -125
  187. package/esm2022/textbox.module.mjs +0 -51
  188. package/esm2022/validators/max.validator.mjs +0 -21
  189. package/esm2022/validators/min.validator.mjs +0 -21
@@ -1,936 +0,0 @@
1
- /**-----------------------------------------------------------------------------------------
2
- * Copyright © 2026 Progress Software Corporation. All rights reserved.
3
- * Licensed under commercial license. See LICENSE.md in the project root for more information
4
- *-------------------------------------------------------------------------------------------*/
5
- import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, Injector, Input, NgZone, Output, QueryList, Renderer2, ViewChildren, forwardRef } from "@angular/core";
6
- import { SharedInputEventsDirective } from "../shared/shared-events.directive";
7
- import { KendoInput, Keys, hasObservers, isPresent, normalizeKeys, replaceMessagePlaceholder } from "@progress/kendo-angular-common";
8
- import { TextBoxComponent } from "../textbox/textbox.component";
9
- import { NG_VALUE_ACCESSOR, NgControl } from "@angular/forms";
10
- import { SIZE_MAP, areSame } from "../common/utils";
11
- import { L10N_PREFIX, LocalizationService } from "@progress/kendo-angular-l10n";
12
- import { OTPInputSeparatorComponent } from "./otpinput-separator.component";
13
- import { take } from "rxjs/operators";
14
- import { LocalizedOTPInputMessagesDirective } from "./localization/localized-textbox-messages.directive";
15
- import * as i0 from "@angular/core";
16
- import * as i1 from "@progress/kendo-angular-l10n";
17
- const DEFAULT_SIZE = 'medium';
18
- const DEFAULT_ROUNDED = 'medium';
19
- const DEFAULT_FILL_MODE = 'solid';
20
- const DEFAULT_OTPINPUT_LENGTH = 4;
21
- /**
22
- * Represents the Kendo UI OTP Input component for Angular.
23
- *
24
- * Use the OTP Input to enter one-time passwords or verification codes.
25
- *
26
- * @example
27
- * ```html
28
- * <kendo-otpinput type="number" [(ngModel)]="otpValue"></kendo-otpinput>
29
- * ```
30
- *
31
- * @remarks
32
- * Supported children components are: {@link OTPInputCustomMessagesComponent}.
33
- */
34
- export class OTPInputComponent {
35
- hostElement;
36
- cdr;
37
- injector;
38
- renderer;
39
- localizationService;
40
- zone;
41
- /**
42
- * Sets the total number of input fields.
43
- *
44
- * @default 4
45
- */
46
- set length(value) {
47
- if (value < 1 || this._length === value) {
48
- return;
49
- }
50
- this._length = value;
51
- this.inputsArray = new Array(this._length);
52
- }
53
- get length() {
54
- return this._length;
55
- }
56
- /**
57
- * Sets the input type.
58
- *
59
- *
60
- * @default 'text'
61
- */
62
- type = 'text';
63
- /**
64
- * Sets whether the input fields are separate or adjacent.
65
- *
66
- * @default true
67
- */
68
- spacing = true;
69
- /**
70
- * Sets the separator between groups of input fields. You can use this only when `groupLength` is set.
71
- */
72
- separator;
73
- /**
74
- * When `true`, disables the OTPInput.
75
- *
76
- * @default false
77
- */
78
- disabled = false;
79
- /**
80
- * When `true`, sets the OTPInput to read-only mode.
81
- *
82
- * @default false
83
- */
84
- readonly = false;
85
- /**
86
- * Sets the placeholder for the input fields.
87
- */
88
- placeholder;
89
- /**
90
- * Sets the length of the groups. If you set a number, all groups have the same length. If you set an array, each group can have a different length.
91
- */
92
- get groupLength() {
93
- return this._groupLength;
94
- }
95
- set groupLength(length) {
96
- const isNumber = typeof length === 'number';
97
- if (this._groupLength === length ||
98
- isPresent(length) &&
99
- ((isNumber && (length < 1 || length > this.length)) ||
100
- (!isNumber && !this.isValidGroupArray(length)))) {
101
- return;
102
- }
103
- if (!isPresent(length)) {
104
- this.clearGroups();
105
- }
106
- else if (isNumber) {
107
- this.populateGroupArray(length);
108
- }
109
- else {
110
- this.groupLengthArray = length;
111
- if (!this.spacing) {
112
- this.adjacentGroups = this.groupLengthArray;
113
- }
114
- }
115
- this._groupLength = length;
116
- this.populateSeparatorPositions();
117
- }
118
- /**
119
- * Sets the value of the component. Unfilled input fields are represented with а space.
120
- */
121
- get value() {
122
- return this._value;
123
- }
124
- set value(input) {
125
- const isInvalidInput = this.type === 'number' && isPresent(input) && !this.containsDigitsOrSpaces(input);
126
- if (this._value === input || isInvalidInput) {
127
- return;
128
- }
129
- if (!isPresent(input)) {
130
- this.clearInputValues();
131
- this._value = null;
132
- }
133
- else {
134
- this._value = input.slice(0, this.length);
135
- if (!this.inputFieldValueChanged) {
136
- this.fillInputs(input, 0, true);
137
- }
138
- }
139
- if (this.inputAttributes) {
140
- this.setInputAttributes();
141
- }
142
- else {
143
- this.setDefaultAttributes();
144
- }
145
- }
146
- /**
147
- * Sets the padding of the input fields.
148
- *
149
- * @default 'medium'
150
- */
151
- set size(size) {
152
- const newSize = size || DEFAULT_SIZE;
153
- const elem = this.hostElement.nativeElement;
154
- this.renderer.removeClass(elem, `k-otp-${SIZE_MAP[this._size]}`);
155
- this.renderer.addClass(elem, `k-otp-${SIZE_MAP[newSize]}`);
156
- this._size = newSize;
157
- }
158
- get size() {
159
- return this._size;
160
- }
161
- /**
162
- * Sets the border radius of the OTP Input.
163
- *
164
- * @default 'medium'
165
- */
166
- set rounded(rounded) {
167
- this._rounded = rounded || DEFAULT_ROUNDED;
168
- }
169
- get rounded() {
170
- return this._rounded;
171
- }
172
- /**
173
- * Sets the background and border styles of the OTP Input.
174
- *
175
- * @default 'solid'
176
- */
177
- set fillMode(fillMode) {
178
- const newFillMode = fillMode || DEFAULT_FILL_MODE;
179
- this.setGroupFillMode(newFillMode, this._fillMode);
180
- this._fillMode = newFillMode;
181
- }
182
- get fillMode() {
183
- return this._fillMode;
184
- }
185
- /**
186
- * Sets the HTML attributes of the inner input element. You cannot change attributes that are required for the component to work.
187
- */
188
- set inputAttributes(attributes) {
189
- this._inputAttributes = attributes;
190
- this.parsedAttributes = this.inputAttributes ?
191
- { ...this.defaultAttributes, ...this.inputAttributes } :
192
- this.inputAttributes;
193
- this.setInputAttributes();
194
- }
195
- get inputAttributes() {
196
- return this._inputAttributes;
197
- }
198
- /**
199
- * Fires when the user changes the value.
200
- *
201
- * This event does not fire when you change the value programmatically or through form bindings.
202
- */
203
- valueChange = new EventEmitter();
204
- /**
205
- * Fires when the user focuses the OTP Input.
206
- */
207
- onFocus = new EventEmitter();
208
- /**
209
- * Fires when the user blurs the OTP Input.
210
- */
211
- onBlur = new EventEmitter();
212
- wrapperClass = true;
213
- get invalidClass() {
214
- return this.isControlInvalid;
215
- }
216
- direction;
217
- role = 'group';
218
- /**
219
- * @hidden
220
- */
221
- inputFields;
222
- /**
223
- * @hidden
224
- */
225
- set inputGroups(elements) {
226
- this._inputGroups = elements;
227
- this.setGroupFillMode(this.fillMode);
228
- }
229
- get inputGroups() {
230
- return this._inputGroups;
231
- }
232
- /**
233
- * @hidden
234
- */
235
- groupLengthArray;
236
- /**
237
- * @hidden
238
- */
239
- inputsArray;
240
- /**
241
- * @hidden
242
- */
243
- inputsValues = [].constructor(DEFAULT_OTPINPUT_LENGTH);
244
- /**
245
- * @hidden
246
- */
247
- adjacentGroups;
248
- _length = DEFAULT_OTPINPUT_LENGTH;
249
- _groupLength;
250
- _inputGroups;
251
- separatorPositions = new Set();
252
- _value = null;
253
- _size = DEFAULT_SIZE;
254
- _rounded = DEFAULT_ROUNDED;
255
- _fillMode = DEFAULT_FILL_MODE;
256
- _isFocused = false;
257
- focusChangedProgrammatically = false;
258
- inputFieldValueChanged = false;
259
- focusedInput;
260
- _inputAttributes;
261
- parsedAttributes = {};
262
- get defaultAttributes() {
263
- return {
264
- autocomplete: 'off'
265
- };
266
- }
267
- subscriptions;
268
- ngChange = (_) => { };
269
- ngTouched = () => { };
270
- constructor(hostElement, cdr, injector, renderer, localizationService, zone) {
271
- this.hostElement = hostElement;
272
- this.cdr = cdr;
273
- this.injector = injector;
274
- this.renderer = renderer;
275
- this.localizationService = localizationService;
276
- this.zone = zone;
277
- this.direction = localizationService.rtl ? 'rtl' : 'ltr';
278
- }
279
- ngOnInit() {
280
- this.inputsArray = Array.from({ length: this._length });
281
- this.subscriptions = this.localizationService.changes.subscribe(({ rtl }) => {
282
- this.direction = rtl ? 'rtl' : 'ltr';
283
- });
284
- this.zone.runOutsideAngular(() => {
285
- this.subscriptions.add(this.renderer.listen(this.hostElement.nativeElement, 'paste', this.handlePaste.bind(this)));
286
- this.subscriptions.add(this.renderer.listen(this.hostElement.nativeElement, 'keydown', this.handleKeydown.bind(this)));
287
- });
288
- }
289
- ngAfterViewInit() {
290
- this.subscriptions.add(this.inputFields.changes.subscribe(this.handleInputChanges.bind(this)));
291
- this.handleInputChanges();
292
- this.renderer.addClass(this.hostElement.nativeElement, `k-otp-${SIZE_MAP[this._size]}`);
293
- this.setGroupFillMode(this.fillMode);
294
- this.zone.onStable.pipe(take(1)).subscribe(() => {
295
- this.fillInputs(this.value);
296
- });
297
- }
298
- ngOnChanges(changes) {
299
- if (changes.length) {
300
- if (typeof this.groupLength === 'number') {
301
- this.populateGroupArray(this.groupLength);
302
- }
303
- this.populateSeparatorPositions();
304
- }
305
- if (changes.spacing) {
306
- if (this.spacing === true) {
307
- this.adjacentGroups = null;
308
- }
309
- else {
310
- this.adjacentGroups = this.groupLengthArray ?? [this.length];
311
- }
312
- }
313
- if (changes.type && this.type === 'number') {
314
- if (isPresent(this.value) && !this.containsDigitsOrSpaces(this.value)) {
315
- this.value = null;
316
- this.zone.runOutsideAngular(() => setTimeout(() => this.zone.run(() => {
317
- this.ngChange(null);
318
- this.cdr.markForCheck();
319
- })));
320
- }
321
- }
322
- }
323
- ngOnDestroy() {
324
- this.subscriptions.unsubscribe();
325
- }
326
- /**
327
- * @hidden
328
- */
329
- get formControl() {
330
- const ngControl = this.injector.get(NgControl, null);
331
- return ngControl?.control || null;
332
- }
333
- /**
334
- * @hidden
335
- */
336
- writeValue(value) {
337
- this.value = value;
338
- this.cdr.markForCheck();
339
- }
340
- /**
341
- * @hidden
342
- */
343
- registerOnChange(fn) {
344
- this.ngChange = fn;
345
- }
346
- /**
347
- * @hidden
348
- */
349
- registerOnTouched(fn) {
350
- this.ngTouched = fn;
351
- }
352
- /**
353
- * @hidden
354
- */
355
- setDisabledState(isDisabled) {
356
- this.cdr.markForCheck();
357
- this.disabled = isDisabled;
358
- }
359
- /**
360
- * @hidden
361
- */
362
- get isControlInvalid() {
363
- return this.formControl?.touched && this.formControl.invalid;
364
- }
365
- /**
366
- * @hidden
367
- */
368
- get isFocused() {
369
- return this._isFocused;
370
- }
371
- /**
372
- * @hidden
373
- */
374
- set isFocused(value) {
375
- if (this._isFocused !== value && this.hostElement) {
376
- this._isFocused = value;
377
- }
378
- }
379
- /**
380
- * Returns `true` if the component has groups.
381
- *
382
- * @hidden
383
- */
384
- get hasGroups() {
385
- if (!this.spacing && isPresent(this.groupLength)) {
386
- return true;
387
- }
388
- }
389
- /**
390
- * @hidden
391
- */
392
- showGroupSeparator(index) {
393
- return this.groupLengthArray && index < this.groupLengthArray.length - 1;
394
- }
395
- /**
396
- * @hidden
397
- */
398
- showSeparator(index) {
399
- return this.groupLength ? this.separatorPositions.has(index) : false;
400
- }
401
- /**
402
- * @hidden
403
- */
404
- handleValueChange(index, groupIndex) {
405
- this.inputFieldValueChanged = true;
406
- if (groupIndex) {
407
- index = this.getIndexByGroup(groupIndex, index);
408
- }
409
- let newValue = '';
410
- this.inputFields.forEach((input) => newValue = newValue.concat(input.value?.toString() || ' '));
411
- if (!areSame(this.value, newValue)) {
412
- this.zone.run(() => {
413
- this.value = newValue;
414
- this.ngChange(newValue);
415
- this.valueChange.emit(newValue);
416
- this.cdr.markForCheck();
417
- });
418
- }
419
- this.inputFieldValueChanged = false;
420
- if (isPresent(index) && isPresent(this.inputFields?.get(index).value)) {
421
- this.focusNext();
422
- }
423
- }
424
- /**
425
- * @hidden
426
- */
427
- handleInputFocus(index, groupIndex) {
428
- if (this.focusChangedProgrammatically) {
429
- return;
430
- }
431
- if (groupIndex) {
432
- index = this.getIndexByGroup(groupIndex, index);
433
- }
434
- this.focusedInput = index;
435
- }
436
- /**
437
- * @hidden
438
- */
439
- handleInput(event, index, groupIndex) {
440
- if (this.type === 'number' && !this.isValidNumber(event?.data)) {
441
- const inputIndex = groupIndex ? this.getIndexByGroup(groupIndex, index) : index;
442
- const textbox = this.inputFields.get(inputIndex);
443
- if (this.value && this.isValidNumber(this.value[inputIndex])) {
444
- textbox.value = this.value[inputIndex];
445
- }
446
- else {
447
- textbox.value = null;
448
- }
449
- this.showInvalidInput(inputIndex);
450
- return;
451
- }
452
- this.handleValueChange(index, groupIndex);
453
- }
454
- /**
455
- * @hidden
456
- */
457
- fillInputs(text, start = 0, replaceLast = false) {
458
- if (!isPresent(text)) {
459
- return;
460
- }
461
- let charCounter = 0;
462
- this.inputFields?.forEach((otpInput, i) => {
463
- if (i < start) {
464
- return;
465
- }
466
- if (charCounter < text.length) {
467
- if (text[charCounter] === ' ') {
468
- otpInput.value = null;
469
- }
470
- else {
471
- otpInput.value = text[charCounter];
472
- }
473
- charCounter++;
474
- }
475
- else if (replaceLast) {
476
- otpInput.value = null;
477
- }
478
- });
479
- }
480
- /**
481
- * Focuses the OTP Input at the specified index provided as an argument.
482
- *
483
- * @param index The index of the input to focus.
484
- */
485
- focus(index) {
486
- if (!this.inputFields || index < 0 || index >= this.length) {
487
- return;
488
- }
489
- this.focusChangedProgrammatically = true;
490
- this.isFocused = true;
491
- this.inputFields.get(index || 0).focus();
492
- this.focusedInput = index || 0;
493
- this.focusChangedProgrammatically = false;
494
- }
495
- /**
496
- * Blurs the OTP Input.
497
- */
498
- blur() {
499
- this.focusChangedProgrammatically = true;
500
- const isFocusedElement = this.hostElement.nativeElement.querySelector(':focus');
501
- if (isFocusedElement) {
502
- isFocusedElement.blur();
503
- }
504
- this.isFocused = false;
505
- this.focusChangedProgrammatically = false;
506
- }
507
- /**
508
- * @hidden
509
- */
510
- handleFocus() {
511
- this.zone.run(() => {
512
- if (!this.focusChangedProgrammatically && hasObservers(this.onFocus)) {
513
- this.onFocus.emit();
514
- }
515
- this.isFocused = true;
516
- });
517
- }
518
- /**
519
- * @hidden
520
- */
521
- handleBlur() {
522
- this.zone.run(() => {
523
- if (!this.focusChangedProgrammatically) {
524
- this.ngTouched();
525
- this.onBlur.emit();
526
- }
527
- this.isFocused = false;
528
- });
529
- }
530
- getIndexByGroup(groupIndex, itemIndex) {
531
- return this.groupLengthArray.slice(0, groupIndex).reduce((sum, current) => sum + current, 0) + itemIndex;
532
- }
533
- focusNext() {
534
- if (!this.inputFields || this.focusedInput === this.length - 1) {
535
- return;
536
- }
537
- this.focusChangedProgrammatically = true;
538
- this.isFocused = true;
539
- this.inputFields.get(this.focusedInput).blur();
540
- this.inputFields.get(this.focusedInput + 1).focus();
541
- this.focusedInput++;
542
- this.focusChangedProgrammatically = false;
543
- }
544
- focusPrevious() {
545
- if (!this.inputFields || this.focusedInput === 0) {
546
- return;
547
- }
548
- this.focusChangedProgrammatically = true;
549
- this.isFocused = true;
550
- this.inputFields.get(this.focusedInput).blur();
551
- this.inputFields.get(this.focusedInput - 1).focus();
552
- this.focusedInput--;
553
- this.focusChangedProgrammatically = false;
554
- }
555
- handlePaste(event) {
556
- event.preventDefault();
557
- const text = event.clipboardData.getData('text').trim();
558
- if (text === '') {
559
- return;
560
- }
561
- if (this.type === 'number' && !this.isValidNumber(text)) {
562
- this.showInvalidInput(this.focusedInput);
563
- return;
564
- }
565
- this.inputFieldValueChanged = true;
566
- this.fillInputs(text, this.focusedInput);
567
- this.handleValueChange();
568
- this.inputFieldValueChanged = false;
569
- const focusedInput = this.focusedInput + text.length < this.inputFields?.length ?
570
- this.focusedInput + text.length :
571
- this.inputFields.length - 1;
572
- this.inputFields.get(this.focusedInput).blur();
573
- this.focusedInput = focusedInput;
574
- this.inputFields.get(this.focusedInput).focus();
575
- }
576
- handleKeydown(event) {
577
- const code = normalizeKeys(event);
578
- if (this.readonly) {
579
- const isCopyCommand = (event.ctrlKey || event.metaKey) && code === Keys.KeyC;
580
- if (!(code === Keys.Tab || isCopyCommand)) {
581
- event.preventDefault();
582
- return;
583
- }
584
- }
585
- switch (code) {
586
- case Keys.ArrowRight:
587
- event.preventDefault();
588
- this.direction === 'ltr' ? this.focusNext() : this.focusPrevious();
589
- break;
590
- case Keys.ArrowLeft:
591
- event.preventDefault();
592
- this.direction === 'ltr' ? this.focusPrevious() : this.focusNext();
593
- break;
594
- case Keys.Backspace:
595
- event.preventDefault();
596
- this.inputFields.get(this.focusedInput).value = null;
597
- this.handleValueChange();
598
- this.focusPrevious();
599
- break;
600
- case Keys.Delete:
601
- event.preventDefault();
602
- this.inputFields.get(this.focusedInput).value = null;
603
- this.handleValueChange();
604
- break;
605
- default:
606
- break;
607
- }
608
- }
609
- isValidGroupArray(groups) {
610
- if (!isPresent(groups)) {
611
- return;
612
- }
613
- const sum = groups.reduce((sum, current) => sum + current, 0);
614
- return sum === this.length;
615
- }
616
- populateGroupArray(length) {
617
- const groupsCount = Math.floor(this.length / length);
618
- const remainder = this.length % length;
619
- const result = Array(groupsCount).fill(length);
620
- if (remainder > 0) {
621
- result.push(remainder);
622
- }
623
- this.groupLengthArray = [...result];
624
- // groups with spacing shouldn't be wrapped in `k-input-group`
625
- if (!this.spacing) {
626
- this.adjacentGroups = [...this.groupLengthArray];
627
- }
628
- }
629
- populateSeparatorPositions() {
630
- let itemIndex = 0;
631
- this.separatorPositions.clear();
632
- if (!isPresent(this.groupLengthArray)) {
633
- return;
634
- }
635
- for (let i = 0; i < this.groupLengthArray.length - 1; i++) {
636
- itemIndex += this.groupLengthArray[i];
637
- this.separatorPositions.add(itemIndex - 1);
638
- }
639
- }
640
- clearGroups() {
641
- this.groupLengthArray = null;
642
- if (!this.spacing) {
643
- this.adjacentGroups = [this.length];
644
- }
645
- else {
646
- this.adjacentGroups = null;
647
- }
648
- this.separatorPositions.clear();
649
- }
650
- clearInputValues() {
651
- this.inputFields?.forEach((input) => input.value = null);
652
- }
653
- handleInputChanges() {
654
- this.zone.onStable.pipe(take(1)).subscribe(() => {
655
- this.fillInputs(this.value?.trim());
656
- if (this.inputAttributes) {
657
- this.setInputAttributes();
658
- }
659
- else {
660
- this.setDefaultAttributes();
661
- }
662
- this.cdr.detectChanges();
663
- });
664
- }
665
- setGroupFillMode(fillMode, previousFillMode) {
666
- this.inputGroups?.forEach(element => {
667
- if (previousFillMode !== 'none') {
668
- this.renderer.removeClass(element.nativeElement, `k-input-group-${previousFillMode}`);
669
- }
670
- if (fillMode !== 'none') {
671
- this.renderer.addClass(element.nativeElement, `k-input-group-${fillMode}`);
672
- }
673
- });
674
- }
675
- setInputAttributes() {
676
- this.inputFields?.forEach((input, index) => {
677
- if (!this.parsedAttributes || !this.parsedAttributes?.['aria-label']) {
678
- input.inputAttributes = { ...this.parsedAttributes, 'aria-label': this.ariaLabel(index) };
679
- }
680
- else {
681
- input.inputAttributes = this.parsedAttributes;
682
- }
683
- });
684
- }
685
- setDefaultAttributes() {
686
- this.inputFields?.forEach((input, index) => {
687
- input.inputAttributes = {
688
- autocomplete: 'off',
689
- 'aria-label': this.ariaLabel(index)
690
- };
691
- });
692
- }
693
- ariaLabel(index) {
694
- const localizationMsg = this.localizationService.get('ariaLabel') || '';
695
- return replaceMessagePlaceholder(replaceMessagePlaceholder(replaceMessagePlaceholder(localizationMsg, 'currentInput', (index + 1).toString()), 'totalInputs', this.length.toString()), 'value', this.value);
696
- }
697
- isValidNumber(value) {
698
- if (!isPresent(value)) {
699
- return;
700
- }
701
- const trimmedValue = value.trim();
702
- return trimmedValue !== '' &&
703
- trimmedValue !== 'Infinity' &&
704
- trimmedValue !== '-Infinity' &&
705
- !isNaN(Number(trimmedValue));
706
- }
707
- showInvalidInput(index) {
708
- const textbox = this.inputFields.get(index);
709
- const textboxElement = this.inputFields.get(index).hostElement.nativeElement;
710
- const inputElement = textbox.input.nativeElement;
711
- this.renderer.addClass(textboxElement, 'k-invalid');
712
- if (textbox.value && this.isValidNumber(textbox.value)) {
713
- this.zone.onStable.pipe(take(1)).subscribe(() => inputElement.select());
714
- }
715
- this.zone.runOutsideAngular(() => {
716
- setTimeout(() => {
717
- if (!this.isControlInvalid && textboxElement) {
718
- this.renderer.removeClass(textboxElement, 'k-invalid');
719
- }
720
- }, 300);
721
- });
722
- }
723
- containsDigitsOrSpaces(value) {
724
- // @ts-expect-error TS does not allow comparing string with number
725
- const isDigitOrSpace = (char) => (char == +char) || char === ' ';
726
- for (let i = 0; i < value.length; i++) {
727
- if (!isDigitOrSpace(value[i])) {
728
- return false;
729
- }
730
- }
731
- return true;
732
- }
733
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OTPInputComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }, { token: i0.Renderer2 }, { token: i1.LocalizationService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
734
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: OTPInputComponent, isStandalone: true, selector: "kendo-otpinput", inputs: { length: "length", type: "type", spacing: "spacing", separator: "separator", disabled: "disabled", readonly: "readonly", placeholder: "placeholder", groupLength: "groupLength", value: "value", size: "size", rounded: "rounded", fillMode: "fillMode", inputAttributes: "inputAttributes" }, outputs: { valueChange: "valueChange", onFocus: "focus", onBlur: "blur" }, host: { properties: { "class.k-otp": "this.wrapperClass", "class.k-invalid": "this.invalidClass", "attr.dir": "this.direction", "attr.role": "this.role" } }, providers: [
735
- LocalizationService,
736
- { provide: L10N_PREFIX, useValue: 'kendo.otpinput' },
737
- {
738
- provide: NG_VALUE_ACCESSOR,
739
- useExisting: forwardRef(() => OTPInputComponent),
740
- multi: true
741
- },
742
- { provide: KendoInput, useExisting: forwardRef(() => OTPInputComponent) }
743
- ], viewQueries: [{ propertyName: "inputFields", predicate: TextBoxComponent, descendants: true }, { propertyName: "inputGroups", predicate: ["inputGroup"], descendants: true }], exportAs: ["kendoOTPInput"], usesOnChanges: true, ngImport: i0, template: `
744
- <ng-container kendoOTPInputLocalizedMessages
745
- i18n-ariaLabel="kendo.otpinput.ariaLabel|The value of the aria-label attribute of the input fields."
746
- ariaLabel="{{ 'Input {currentInput} of {totalInputs}, current value {value}' }}"
747
- ></ng-container>
748
- <ng-container
749
- kendoInputSharedEvents
750
- [hostElement]="hostElement"
751
- [(isFocused)]="isFocused"
752
- (handleBlur)="handleBlur()"
753
- (onFocus)="handleFocus()"
754
- >
755
- @if (spacing) {
756
- @for (input of inputsArray; track input; let i = $index) {
757
- <kendo-textbox
758
- class="k-otp-input"
759
- [class.k-invalid]="isControlInvalid"
760
- [selectOnFocus]="true"
761
- [maxlength]="1"
762
- [type]="type !== 'number' ? type : null"
763
- [placeholder]="placeholder"
764
- [size]="size"
765
- [rounded]="rounded"
766
- [fillMode]="fillMode"
767
- [disabled]="disabled"
768
- [readonly]="readonly"
769
- (focus)="handleInputFocus(i)"
770
- (input)="handleInput($event, i)"
771
- ></kendo-textbox>
772
- @if (showSeparator(i)) {
773
- <kendo-otpinput-separator [separator]="separator"></kendo-otpinput-separator>
774
- }
775
- }
776
- } @else {
777
- @for (group of adjacentGroups; track group; let i = $index) {
778
- <div #inputGroup class="k-input-group">
779
- @for (input of [].constructor(group); track input; let j = $index) {
780
- <kendo-textbox
781
- class="k-otp-input"
782
- [class.k-invalid]="isControlInvalid"
783
- [selectOnFocus]="true"
784
- [maxlength]="1"
785
- [type]="type !== 'number' ? type : null"
786
- [placeholder]="placeholder"
787
- [size]="size"
788
- [rounded]="rounded"
789
- [fillMode]="fillMode"
790
- [disabled]="disabled"
791
- [readonly]="readonly"
792
- (focus)="handleInputFocus(j, i)"
793
- (input)="handleInput($event, j, i)"
794
- ></kendo-textbox>
795
- }
796
- </div>
797
- @if (showGroupSeparator(i)) {
798
- <kendo-otpinput-separator [separator]="separator"></kendo-otpinput-separator>
799
- }
800
- }
801
- }
802
- <ng-container>
803
- `, isInline: true, dependencies: [{ kind: "directive", type: SharedInputEventsDirective, selector: "[kendoInputSharedEvents]", inputs: ["hostElement", "clearButtonClicked", "isFocused"], outputs: ["isFocusedChange", "onFocus", "handleBlur"] }, { kind: "component", type: TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "component", type: OTPInputSeparatorComponent, selector: "kendo-otpinput-separator", inputs: ["separator"], exportAs: ["kendoOTPInputSeparator"] }, { kind: "directive", type: LocalizedOTPInputMessagesDirective, selector: "[kendoOTPInputLocalizedMessages]" }] });
804
- }
805
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OTPInputComponent, decorators: [{
806
- type: Component,
807
- args: [{
808
- exportAs: 'kendoOTPInput',
809
- providers: [
810
- LocalizationService,
811
- { provide: L10N_PREFIX, useValue: 'kendo.otpinput' },
812
- {
813
- provide: NG_VALUE_ACCESSOR,
814
- useExisting: forwardRef(() => OTPInputComponent),
815
- multi: true
816
- },
817
- { provide: KendoInput, useExisting: forwardRef(() => OTPInputComponent) }
818
- ],
819
- selector: 'kendo-otpinput',
820
- template: `
821
- <ng-container kendoOTPInputLocalizedMessages
822
- i18n-ariaLabel="kendo.otpinput.ariaLabel|The value of the aria-label attribute of the input fields."
823
- ariaLabel="{{ 'Input {currentInput} of {totalInputs}, current value {value}' }}"
824
- ></ng-container>
825
- <ng-container
826
- kendoInputSharedEvents
827
- [hostElement]="hostElement"
828
- [(isFocused)]="isFocused"
829
- (handleBlur)="handleBlur()"
830
- (onFocus)="handleFocus()"
831
- >
832
- @if (spacing) {
833
- @for (input of inputsArray; track input; let i = $index) {
834
- <kendo-textbox
835
- class="k-otp-input"
836
- [class.k-invalid]="isControlInvalid"
837
- [selectOnFocus]="true"
838
- [maxlength]="1"
839
- [type]="type !== 'number' ? type : null"
840
- [placeholder]="placeholder"
841
- [size]="size"
842
- [rounded]="rounded"
843
- [fillMode]="fillMode"
844
- [disabled]="disabled"
845
- [readonly]="readonly"
846
- (focus)="handleInputFocus(i)"
847
- (input)="handleInput($event, i)"
848
- ></kendo-textbox>
849
- @if (showSeparator(i)) {
850
- <kendo-otpinput-separator [separator]="separator"></kendo-otpinput-separator>
851
- }
852
- }
853
- } @else {
854
- @for (group of adjacentGroups; track group; let i = $index) {
855
- <div #inputGroup class="k-input-group">
856
- @for (input of [].constructor(group); track input; let j = $index) {
857
- <kendo-textbox
858
- class="k-otp-input"
859
- [class.k-invalid]="isControlInvalid"
860
- [selectOnFocus]="true"
861
- [maxlength]="1"
862
- [type]="type !== 'number' ? type : null"
863
- [placeholder]="placeholder"
864
- [size]="size"
865
- [rounded]="rounded"
866
- [fillMode]="fillMode"
867
- [disabled]="disabled"
868
- [readonly]="readonly"
869
- (focus)="handleInputFocus(j, i)"
870
- (input)="handleInput($event, j, i)"
871
- ></kendo-textbox>
872
- }
873
- </div>
874
- @if (showGroupSeparator(i)) {
875
- <kendo-otpinput-separator [separator]="separator"></kendo-otpinput-separator>
876
- }
877
- }
878
- }
879
- <ng-container>
880
- `,
881
- standalone: true,
882
- imports: [SharedInputEventsDirective, TextBoxComponent, OTPInputSeparatorComponent, LocalizedOTPInputMessagesDirective]
883
- }]
884
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }, { type: i0.Renderer2 }, { type: i1.LocalizationService }, { type: i0.NgZone }], propDecorators: { length: [{
885
- type: Input
886
- }], type: [{
887
- type: Input
888
- }], spacing: [{
889
- type: Input
890
- }], separator: [{
891
- type: Input
892
- }], disabled: [{
893
- type: Input
894
- }], readonly: [{
895
- type: Input
896
- }], placeholder: [{
897
- type: Input
898
- }], groupLength: [{
899
- type: Input
900
- }], value: [{
901
- type: Input
902
- }], size: [{
903
- type: Input
904
- }], rounded: [{
905
- type: Input
906
- }], fillMode: [{
907
- type: Input
908
- }], inputAttributes: [{
909
- type: Input
910
- }], valueChange: [{
911
- type: Output
912
- }], onFocus: [{
913
- type: Output,
914
- args: ['focus']
915
- }], onBlur: [{
916
- type: Output,
917
- args: ['blur']
918
- }], wrapperClass: [{
919
- type: HostBinding,
920
- args: ['class.k-otp']
921
- }], invalidClass: [{
922
- type: HostBinding,
923
- args: ['class.k-invalid']
924
- }], direction: [{
925
- type: HostBinding,
926
- args: ['attr.dir']
927
- }], role: [{
928
- type: HostBinding,
929
- args: ['attr.role']
930
- }], inputFields: [{
931
- type: ViewChildren,
932
- args: [TextBoxComponent]
933
- }], inputGroups: [{
934
- type: ViewChildren,
935
- args: ['inputGroup']
936
- }] } });