@koobiq/components 16.0.0-beta.5 → 16.0.0-beta.7

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 (294) hide show
  1. package/autocomplete/autocomplete-trigger.directive.d.ts +5 -15
  2. package/button/_button-theme.scss +20 -9
  3. package/button-toggle/button-toggle.component.d.ts +2 -2
  4. package/checkbox/_checkbox-theme.scss +10 -2
  5. package/checkbox/checkbox.d.ts +1 -1
  6. package/code-block/README.md +14 -14
  7. package/code-block/_code-block-theme.scss +8 -0
  8. package/code-block/code-block.component.d.ts +1 -1
  9. package/core/animation/index.d.ts +1 -1
  10. package/core/animation/select-animations.d.ts +1 -1
  11. package/core/formatters/index.d.ts +1 -1
  12. package/core/formatters/number/formatter.d.ts +56 -1
  13. package/core/forms/forms.directive.d.ts +2 -2
  14. package/core/locales/en-US.d.ts +19 -1
  15. package/core/locales/es-LA.d.ts +27 -0
  16. package/core/locales/fa-IR.d.ts +28 -0
  17. package/core/locales/locale-service.d.ts +148 -3
  18. package/core/locales/pt-BR.d.ts +27 -0
  19. package/core/locales/ru-RU.d.ts +20 -1
  20. package/core/locales/zh-CN.d.ts +26 -0
  21. package/core/option/action.d.ts +1 -1
  22. package/core/option/optgroup.d.ts +1 -1
  23. package/core/option/option.d.ts +37 -8
  24. package/core/overlay/overlay-position-map.d.ts +7 -1
  25. package/core/pop-up/constants.d.ts +2 -1
  26. package/core/public-api.d.ts +1 -0
  27. package/core/select/constants.d.ts +2 -2
  28. package/core/services/theme.service.d.ts +23 -0
  29. package/core/styles/_variables.scss +1 -0
  30. package/core/styles/common/_select.scss +24 -24
  31. package/core/styles/theming/_components-theming.scss +31 -5
  32. package/datepicker/calendar-body.component.d.ts +1 -1
  33. package/datepicker/calendar-header.component.d.ts +9 -3
  34. package/datepicker/calendar.component.d.ts +4 -5
  35. package/datepicker/datepicker-animations.d.ts +1 -1
  36. package/datepicker/datepicker-input.directive.d.ts +4 -4
  37. package/datepicker/datepicker-toggle.component.d.ts +3 -3
  38. package/datepicker/datepicker.component.d.ts +2 -2
  39. package/datepicker/month-view.component.d.ts +5 -6
  40. package/dl/_dl-theme.scss +2 -56
  41. package/dl/dl.component.d.ts +1 -2
  42. package/dl/dl.scss +10 -47
  43. package/dropdown/dropdown-animations.d.ts +1 -1
  44. package/dropdown/dropdown-content.directive.d.ts +1 -1
  45. package/dropdown/dropdown-item.component.d.ts +1 -1
  46. package/dropdown/dropdown-trigger.directive.d.ts +2 -2
  47. package/dropdown/dropdown.component.d.ts +1 -1
  48. package/dropdown/dropdown.types.d.ts +1 -1
  49. package/esm2022/alert/alert.component.mjs +2 -2
  50. package/esm2022/autocomplete/autocomplete-trigger.directive.mjs +24 -21
  51. package/esm2022/button-toggle/button-toggle.component.mjs +8 -8
  52. package/esm2022/checkbox/checkbox.mjs +3 -3
  53. package/esm2022/code-block/actionbar.component.mjs +1 -1
  54. package/esm2022/code-block/code-block.component.mjs +3 -3
  55. package/esm2022/core/animation/index.mjs +2 -2
  56. package/esm2022/core/animation/select-animations.mjs +4 -4
  57. package/esm2022/core/formatters/index.mjs +10 -2
  58. package/esm2022/core/formatters/number/formatter.mjs +224 -3
  59. package/esm2022/core/forms/forms.directive.mjs +5 -5
  60. package/esm2022/core/locales/en-US.mjs +22 -4
  61. package/esm2022/core/locales/es-LA.mjs +31 -2
  62. package/esm2022/core/locales/fa-IR.mjs +30 -2
  63. package/esm2022/core/locales/locale-service.mjs +4 -4
  64. package/esm2022/core/locales/pt-BR.mjs +29 -2
  65. package/esm2022/core/locales/ru-RU.mjs +23 -2
  66. package/esm2022/core/locales/zh-CN.mjs +28 -2
  67. package/esm2022/core/option/action.mjs +3 -3
  68. package/esm2022/core/option/optgroup.mjs +3 -3
  69. package/esm2022/core/option/option.mjs +47 -10
  70. package/esm2022/core/overlay/overlay-position-map.mjs +7 -1
  71. package/esm2022/core/pop-up/constants.mjs +2 -1
  72. package/esm2022/core/pop-up/pop-up-trigger.mjs +12 -3
  73. package/esm2022/core/public-api.mjs +2 -1
  74. package/esm2022/core/select/constants.mjs +3 -3
  75. package/esm2022/core/services/theme.service.mjs +60 -0
  76. package/esm2022/core/version.mjs +2 -2
  77. package/esm2022/datepicker/calendar-body.component.mjs +3 -3
  78. package/esm2022/datepicker/calendar-header.component.mjs +9 -8
  79. package/esm2022/datepicker/calendar.component.mjs +7 -16
  80. package/esm2022/datepicker/datepicker-animations.mjs +2 -2
  81. package/esm2022/datepicker/datepicker-input.directive.mjs +29 -20
  82. package/esm2022/datepicker/datepicker-toggle.component.mjs +6 -6
  83. package/esm2022/datepicker/datepicker.component.mjs +11 -11
  84. package/esm2022/datepicker/month-view.component.mjs +9 -18
  85. package/esm2022/dl/dl.component.mjs +3 -7
  86. package/esm2022/dropdown/dropdown-animations.mjs +4 -4
  87. package/esm2022/dropdown/dropdown-content.directive.mjs +3 -3
  88. package/esm2022/dropdown/dropdown-errors.mjs +6 -6
  89. package/esm2022/dropdown/dropdown-item.component.mjs +5 -5
  90. package/esm2022/dropdown/dropdown-trigger.directive.mjs +8 -8
  91. package/esm2022/dropdown/dropdown.component.mjs +8 -8
  92. package/esm2022/dropdown/dropdown.types.mjs +1 -1
  93. package/esm2022/file-upload/file-drop.mjs +4 -4
  94. package/esm2022/file-upload/multiple-file-upload.component.mjs +12 -8
  95. package/esm2022/file-upload/single-file-upload.component.mjs +12 -8
  96. package/esm2022/form-field/cleaner.mjs +3 -3
  97. package/esm2022/form-field/form-field.mjs +9 -12
  98. package/esm2022/form-field/hint.mjs +4 -4
  99. package/esm2022/form-field/password-hint.mjs +22 -13
  100. package/esm2022/form-field/password-toggle.mjs +25 -8
  101. package/esm2022/form-field/suffix.mjs +3 -3
  102. package/esm2022/form-field/validate.directive.mjs +4 -4
  103. package/esm2022/input/input-number.mjs +259 -43
  104. package/esm2022/link/link.component.mjs +3 -3
  105. package/esm2022/list/list-selection.component.mjs +6 -6
  106. package/esm2022/loader-overlay/loader-overlay.component.mjs +2 -2
  107. package/esm2022/modal/modal-control.service.mjs +5 -5
  108. package/esm2022/modal/modal-ref.class.mjs +1 -1
  109. package/esm2022/modal/modal.component.mjs +126 -112
  110. package/esm2022/modal/modal.module.mjs +13 -7
  111. package/esm2022/modal/modal.service.mjs +23 -23
  112. package/esm2022/modal/modal.type.mjs +1 -3
  113. package/esm2022/navbar/navbar-item.component.mjs +17 -17
  114. package/esm2022/navbar/navbar.component.mjs +18 -9
  115. package/esm2022/navbar/vertical-navbar.component.mjs +9 -6
  116. package/esm2022/popover/popover-animations.mjs +2 -2
  117. package/esm2022/popover/popover-confirm.component.mjs +9 -9
  118. package/esm2022/popover/popover.component.mjs +23 -23
  119. package/esm2022/radio/radio.component.mjs +11 -8
  120. package/esm2022/select/select.component.mjs +35 -21
  121. package/esm2022/sidebar/sidebar-animations.mjs +2 -2
  122. package/esm2022/sidebar/sidebar.component.mjs +9 -9
  123. package/esm2022/sidepanel/sidepanel-directives.mjs +2 -2
  124. package/esm2022/sidepanel/sidepanel.module.mjs +10 -4
  125. package/esm2022/splitter/splitter.component.mjs +3 -3
  126. package/esm2022/table/table.component.mjs +3 -3
  127. package/esm2022/tabs/paginated-tab-header.mjs +11 -2
  128. package/esm2022/tabs/tab-body.component.mjs +7 -7
  129. package/esm2022/tabs/tab-content.directive.mjs +3 -3
  130. package/esm2022/tabs/tab-group.component.mjs +3 -3
  131. package/esm2022/tabs/tab-nav-bar/tab-nav-bar.mjs +6 -6
  132. package/esm2022/tabs/tab.component.mjs +14 -5
  133. package/esm2022/tabs/tabs-animations.mjs +2 -2
  134. package/esm2022/tags/tag-default-options.mjs +1 -1
  135. package/esm2022/tags/tag-input.mjs +12 -10
  136. package/esm2022/tags/tag-list.component.mjs +12 -8
  137. package/esm2022/tags/tag.component.mjs +13 -13
  138. package/esm2022/timepicker/timepicker.directive.mjs +10 -10
  139. package/esm2022/timezone/timezone-option.component.mjs +3 -3
  140. package/esm2022/timezone/timezone-select.component.mjs +5 -5
  141. package/esm2022/title/title.directive.mjs +6 -6
  142. package/esm2022/toast/toast.module.mjs +10 -4
  143. package/esm2022/toggle/toggle.component.mjs +3 -3
  144. package/esm2022/tooltip/tooltip.component.mjs +16 -16
  145. package/esm2022/tree/node.mjs +5 -5
  146. package/esm2022/tree/outlet.mjs +3 -3
  147. package/esm2022/tree/padding.directive.mjs +6 -6
  148. package/esm2022/tree/toggle.mjs +8 -8
  149. package/esm2022/tree/tree-base.mjs +3 -3
  150. package/esm2022/tree/tree-option.component.mjs +9 -5
  151. package/esm2022/tree/tree-selection.component.mjs +8 -6
  152. package/esm2022/tree/tree.mjs +3 -3
  153. package/esm2022/tree-select/tree-select.component.mjs +13 -13
  154. package/fesm2022/koobiq-components-alert.mjs +2 -2
  155. package/fesm2022/koobiq-components-alert.mjs.map +1 -1
  156. package/fesm2022/koobiq-components-autocomplete.mjs +24 -21
  157. package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
  158. package/fesm2022/koobiq-components-button-toggle.mjs +7 -7
  159. package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
  160. package/fesm2022/koobiq-components-checkbox.mjs +2 -2
  161. package/fesm2022/koobiq-components-checkbox.mjs.map +1 -1
  162. package/fesm2022/koobiq-components-code-block.mjs +3 -3
  163. package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
  164. package/fesm2022/koobiq-components-core.mjs +526 -39
  165. package/fesm2022/koobiq-components-core.mjs.map +1 -1
  166. package/fesm2022/koobiq-components-datepicker.mjs +66 -74
  167. package/fesm2022/koobiq-components-datepicker.mjs.map +1 -1
  168. package/fesm2022/koobiq-components-dl.mjs +2 -6
  169. package/fesm2022/koobiq-components-dl.mjs.map +1 -1
  170. package/fesm2022/koobiq-components-dropdown.mjs +28 -28
  171. package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
  172. package/fesm2022/koobiq-components-file-upload.mjs +23 -15
  173. package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
  174. package/fesm2022/koobiq-components-form-field.mjs +61 -40
  175. package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
  176. package/fesm2022/koobiq-components-input.mjs +257 -43
  177. package/fesm2022/koobiq-components-input.mjs.map +1 -1
  178. package/fesm2022/koobiq-components-link.mjs +2 -2
  179. package/fesm2022/koobiq-components-link.mjs.map +1 -1
  180. package/fesm2022/koobiq-components-list.mjs +5 -5
  181. package/fesm2022/koobiq-components-list.mjs.map +1 -1
  182. package/fesm2022/koobiq-components-loader-overlay.mjs +2 -2
  183. package/fesm2022/koobiq-components-loader-overlay.mjs.map +1 -1
  184. package/fesm2022/koobiq-components-modal.mjs +161 -145
  185. package/fesm2022/koobiq-components-modal.mjs.map +1 -1
  186. package/fesm2022/koobiq-components-navbar.mjs +39 -31
  187. package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
  188. package/fesm2022/koobiq-components-popover.mjs +30 -30
  189. package/fesm2022/koobiq-components-popover.mjs.map +1 -1
  190. package/fesm2022/koobiq-components-radio.mjs +10 -7
  191. package/fesm2022/koobiq-components-radio.mjs.map +1 -1
  192. package/fesm2022/koobiq-components-select.mjs +34 -20
  193. package/fesm2022/koobiq-components-select.mjs.map +1 -1
  194. package/fesm2022/koobiq-components-sidebar.mjs +8 -8
  195. package/fesm2022/koobiq-components-sidebar.mjs.map +1 -1
  196. package/fesm2022/koobiq-components-sidepanel.mjs +10 -4
  197. package/fesm2022/koobiq-components-sidepanel.mjs.map +1 -1
  198. package/fesm2022/koobiq-components-splitter.mjs +2 -2
  199. package/fesm2022/koobiq-components-splitter.mjs.map +1 -1
  200. package/fesm2022/koobiq-components-table.mjs +2 -2
  201. package/fesm2022/koobiq-components-table.mjs.map +1 -1
  202. package/fesm2022/koobiq-components-tabs.mjs +39 -21
  203. package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
  204. package/fesm2022/koobiq-components-tags.mjs +34 -28
  205. package/fesm2022/koobiq-components-tags.mjs.map +1 -1
  206. package/fesm2022/koobiq-components-timepicker.mjs +9 -9
  207. package/fesm2022/koobiq-components-timepicker.mjs.map +1 -1
  208. package/fesm2022/koobiq-components-timezone.mjs +6 -6
  209. package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
  210. package/fesm2022/koobiq-components-title.mjs +5 -5
  211. package/fesm2022/koobiq-components-title.mjs.map +1 -1
  212. package/fesm2022/koobiq-components-toast.mjs +8 -2
  213. package/fesm2022/koobiq-components-toast.mjs.map +1 -1
  214. package/fesm2022/koobiq-components-toggle.mjs +2 -2
  215. package/fesm2022/koobiq-components-toggle.mjs.map +1 -1
  216. package/fesm2022/koobiq-components-tooltip.mjs +15 -15
  217. package/fesm2022/koobiq-components-tooltip.mjs.map +1 -1
  218. package/fesm2022/koobiq-components-tree-select.mjs +12 -12
  219. package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
  220. package/fesm2022/koobiq-components-tree.mjs +37 -31
  221. package/fesm2022/koobiq-components-tree.mjs.map +1 -1
  222. package/file-upload/file-drop.d.ts +1 -1
  223. package/file-upload/multiple-file-upload.component.d.ts +4 -3
  224. package/file-upload/single-file-upload.component.d.ts +4 -3
  225. package/form-field/_hint-theme.scss +1 -1
  226. package/form-field/cleaner.d.ts +1 -1
  227. package/form-field/form-field.d.ts +2 -3
  228. package/form-field/form-field.scss +2 -2
  229. package/form-field/hint.d.ts +1 -1
  230. package/form-field/password-hint.d.ts +7 -3
  231. package/form-field/password-toggle.d.ts +12 -6
  232. package/form-field/suffix.d.ts +1 -1
  233. package/form-field/validate.directive.d.ts +1 -1
  234. package/icon/_icon-theme.scss +2 -1
  235. package/input/_input-theme.scss +2 -1
  236. package/input/input-number.d.ts +61 -10
  237. package/link/_link-theme.scss +4 -0
  238. package/link/link.component.d.ts +1 -1
  239. package/list/list-selection.component.d.ts +1 -1
  240. package/loader-overlay/loader-overlay.scss +3 -0
  241. package/modal/README.md +5 -5
  242. package/modal/modal-ref.class.d.ts +2 -2
  243. package/modal/modal.component.d.ts +51 -47
  244. package/modal/modal.module.d.ts +2 -1
  245. package/modal/modal.scss +7 -0
  246. package/modal/modal.type.d.ts +35 -36
  247. package/navbar/navbar-item.component.d.ts +4 -3
  248. package/navbar/navbar.component.d.ts +5 -2
  249. package/navbar/vertical-navbar.component.d.ts +4 -2
  250. package/package.json +9 -11
  251. package/popover/README.md +14 -14
  252. package/popover/_popover-theme.scss +11 -11
  253. package/popover/popover-animations.d.ts +1 -1
  254. package/popover/popover-confirm.component.d.ts +1 -1
  255. package/popover/popover.component.d.ts +3 -3
  256. package/prebuilt-themes/dark-theme.css +1 -1
  257. package/prebuilt-themes/light-theme.css +1 -1
  258. package/radio/_radio-theme.scss +15 -2
  259. package/radio/radio.component.d.ts +2 -2
  260. package/radio/radio.scss +13 -0
  261. package/select/select.component.d.ts +14 -11
  262. package/select/select.scss +1 -1
  263. package/sidebar/sidebar-animations.d.ts +1 -1
  264. package/sidebar/sidebar.component.d.ts +3 -3
  265. package/splitter/splitter.component.d.ts +1 -1
  266. package/table/table.component.d.ts +1 -1
  267. package/tabs/paginated-tab-header.d.ts +1 -0
  268. package/tabs/tab-body.component.d.ts +1 -1
  269. package/tabs/tab-content.directive.d.ts +1 -1
  270. package/tabs/tab-nav-bar/tab-nav-bar.d.ts +2 -2
  271. package/tabs/tab.component.d.ts +1 -1
  272. package/tabs/tabs-animations.d.ts +1 -1
  273. package/tags/_tag-theme.scss +1 -1
  274. package/tags/tag-default-options.d.ts +4 -0
  275. package/tags/tag-input.d.ts +2 -2
  276. package/tags/tag-list.component.d.ts +3 -2
  277. package/tags/tag-list.scss +2 -0
  278. package/tags/tag.component.d.ts +4 -4
  279. package/timepicker/timepicker.directive.d.ts +2 -2
  280. package/timezone/timezone-option.component.d.ts +1 -1
  281. package/timezone/timezone-select.component.d.ts +1 -1
  282. package/title/title.directive.d.ts +1 -1
  283. package/toggle/toggle.component.d.ts +1 -1
  284. package/tooltip/tooltip.component.d.ts +3 -3
  285. package/tree/node.d.ts +1 -1
  286. package/tree/outlet.d.ts +1 -1
  287. package/tree/padding.directive.d.ts +1 -1
  288. package/tree/toggle.d.ts +3 -3
  289. package/tree/tree-base.d.ts +1 -1
  290. package/tree/tree-option.component.d.ts +1 -1
  291. package/tree/tree-option.scss +2 -0
  292. package/tree/tree-selection.component.d.ts +1 -1
  293. package/tree/tree.d.ts +1 -1
  294. package/tree-select/tree-select.component.d.ts +1 -1
@@ -1,17 +1,17 @@
1
1
  import { A11yModule } from '@angular/cdk/a11y';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { Directive, Optional, Self, Attribute, Input, InjectionToken, Inject, forwardRef, NgModule } from '@angular/core';
4
+ import { forwardRef, EventEmitter, Directive, Attribute, Optional, Inject, Input, InjectionToken, Self, NgModule } from '@angular/core';
5
5
  import * as i1 from '@angular/forms';
6
- import { NG_VALIDATORS, Validators, FormsModule } from '@angular/forms';
6
+ import { NG_VALUE_ACCESSOR, NG_VALIDATORS, Validators, FormsModule } from '@angular/forms';
7
7
  import * as i3 from '@koobiq/components/core';
8
- import { mixinErrorState, KbqCommonModule } from '@koobiq/components/core';
8
+ import { KBQ_LOCALE_SERVICE, mixinErrorState, KbqCommonModule } from '@koobiq/components/core';
9
9
  import { KbqIconModule } from '@koobiq/components/icon';
10
10
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
11
11
  import { getSupportedInputTypes } from '@angular/cdk/platform';
12
12
  import { KbqFormFieldControl } from '@koobiq/components/form-field';
13
- import { Subject } from 'rxjs';
14
- import { A, C, V, X, Z, F1, F12, ZERO, NINE, NUMPAD_ZERO, NUMPAD_NINE, NUMPAD_MINUS, DASH, FF_MINUS, DELETE, BACKSPACE, TAB, ESCAPE, ENTER, LEFT_ARROW, RIGHT_ARROW, HOME, END, UP_ARROW, DOWN_ARROW } from '@koobiq/cdk/keycodes';
13
+ import { Subject, Subscription } from 'rxjs';
14
+ 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 '@koobiq/cdk/keycodes';
15
15
 
16
16
  function getKbqInputUnsupportedTypeError(inputType) {
17
17
  return Error(`Input type "${inputType}" isn't supported by kbqInput.`);
@@ -42,19 +42,76 @@ function add(value1, value2) {
42
42
  const precision = Math.max(getPrecision(value1), getPrecision(value2));
43
43
  return (value1 * precision + value2 * precision) / precision;
44
44
  }
45
+ const KBQ_NUMBER_INPUT_VALUE_ACCESSOR = {
46
+ provide: NG_VALUE_ACCESSOR,
47
+ useExisting: forwardRef(() => KbqNumberInput),
48
+ multi: true
49
+ };
45
50
  class KbqNumberInput {
51
+ get value() {
52
+ return this._value;
53
+ }
54
+ set value(value) {
55
+ const oldValue = this.value;
56
+ this._value = value;
57
+ if (oldValue !== value) {
58
+ this.setViewValue(this.formatNumber(value));
59
+ this.valueChange.emit(value);
60
+ }
61
+ }
62
+ get disabled() {
63
+ return this._disabled;
64
+ }
65
+ set disabled(value) {
66
+ const newValue = coerceBooleanProperty(value);
67
+ const element = this.nativeElement;
68
+ if (this._disabled !== newValue) {
69
+ this._disabled = newValue;
70
+ this.disabledChange.emit(newValue);
71
+ }
72
+ // We need to null check the `blur` method, because it's undefined during SSR.
73
+ if (newValue && element.blur) {
74
+ // Normally, native input elements automatically blur if they turn disabled. This behavior
75
+ // is problematic, because it would mean that it triggers another change detection cycle,
76
+ // which then causes a changed after checked error if the input element was focused before.
77
+ element.blur();
78
+ }
79
+ }
46
80
  get nativeElement() {
47
81
  return this.elementRef.nativeElement;
48
82
  }
49
- constructor(elementRef, ngControl, step, bigStep, min, max) {
83
+ get viewValue() {
84
+ return this.nativeElement.value;
85
+ }
86
+ get ngControl() {
87
+ return this.control;
88
+ }
89
+ constructor(elementRef, renderer, step, bigStep, min, max, localeService) {
50
90
  this.elementRef = elementRef;
51
- this.ngControl = ngControl;
52
- this.focused = false;
91
+ this.renderer = renderer;
92
+ this.localeService = localeService;
93
+ /** Emits when the value changes (either due to user input or programmatic change). */
94
+ this.valueChange = new EventEmitter();
95
+ /** Emits when the disabled state has changed */
96
+ this.disabledChange = new EventEmitter();
53
97
  this.stateChanges = new Subject();
98
+ this.withThousandSeparator = true;
99
+ this._disabled = false;
100
+ this.focused = false;
101
+ this.localeSubscription = Subscription.EMPTY;
102
+ // tslint:disable-next-line:no-empty
103
+ this.onTouched = () => { };
104
+ // tslint:disable-next-line:no-empty
105
+ this.cvaOnChange = () => { };
106
+ this.updateLocaleParams = (id) => {
107
+ this.numberLocaleConfig = this.localeService.locales[id].input.number;
108
+ this.setViewValue(this.formatNumber(this.value));
109
+ };
54
110
  this.step = isDigit(step) ? parseFloat(step) : SMALL_STEP;
55
111
  this.bigStep = isDigit(bigStep) ? parseFloat(bigStep) : BIG_STEP;
56
112
  this.min = isDigit(min) ? parseFloat(min) : -Infinity;
57
113
  this.max = isDigit(max) ? parseFloat(max) : Infinity;
114
+ setTimeout(() => this.nativeElement.type = 'text', 0);
58
115
  if ('valueAsNumber' in this.nativeElement) {
59
116
  Object.defineProperty(Object.getPrototypeOf(this.nativeElement), 'valueAsNumber', {
60
117
  // tslint:disable-next-line:no-reserved-keywords
@@ -64,6 +121,38 @@ class KbqNumberInput {
64
121
  }
65
122
  });
66
123
  }
124
+ this.allNumberLocaleConfigs = this.localeService.locales.items
125
+ .map((localeItem) => {
126
+ return { id: localeItem.id, config: this.localeService.locales[localeItem.id].input.number };
127
+ });
128
+ this.localeSubscription = this.localeService.changes.subscribe(this.updateLocaleParams);
129
+ }
130
+ ngOnDestroy() {
131
+ this.localeSubscription.unsubscribe();
132
+ this.valueChange.complete();
133
+ this.disabledChange.complete();
134
+ }
135
+ onContainerClick() {
136
+ this.focus();
137
+ }
138
+ focus() {
139
+ this.nativeElement.focus();
140
+ }
141
+ // Implemented as part of ControlValueAccessor.
142
+ writeValue(value) {
143
+ this.value = value;
144
+ }
145
+ // Implemented as part of ControlValueAccessor.
146
+ registerOnChange(fn) {
147
+ this.cvaOnChange = fn;
148
+ }
149
+ // Implemented as part of ControlValueAccessor.
150
+ registerOnTouched(fn) {
151
+ this.onTouched = fn;
152
+ }
153
+ // Implemented as part of ControlValueAccessor.
154
+ setDisabledState(isDisabled) {
155
+ this.disabled = isDisabled;
67
156
  }
68
157
  focusChanged(isFocused) {
69
158
  if (isFocused !== this.focused) {
@@ -79,32 +168,39 @@ class KbqNumberInput {
79
168
  const isCtrlV = (e) => e.keyCode === V && (e.ctrlKey || e.metaKey);
80
169
  const isCtrlX = (e) => e.keyCode === X && (e.ctrlKey || e.metaKey);
81
170
  const isCtrlZ = (e) => e.keyCode === Z && (e.ctrlKey || e.metaKey);
82
- const isFKey = (e) => e.keyCode >= F1 && e.keyCode <= F12;
83
- const isNumber = (e) => (e.keyCode >= ZERO && e.keyCode <= NINE) ||
84
- (e.keyCode >= NUMPAD_ZERO && e.keyCode <= NUMPAD_NINE);
85
- const isPeriod = (e) => e.key === '.' || e.key === ',';
171
+ const isPeriod = (e) => this.numberLocaleConfig.groupSeparator.includes(e.key)
172
+ || [this.numberLocaleConfig.fractionSeparator, '.'].includes(e.key);
86
173
  const minuses = [NUMPAD_MINUS, DASH, FF_MINUS];
87
174
  const serviceKeys = [DELETE, BACKSPACE, TAB, ESCAPE, ENTER];
88
175
  const arrows = [LEFT_ARROW, RIGHT_ARROW];
89
176
  const allowedKeys = [HOME, END].concat(arrows).concat(serviceKeys).concat(minuses);
90
177
  if (minuses.includes(keyCode) &&
91
- (this.nativeElement.valueAsNumber || this.min >= 0 || this.nativeElement.validity?.badInput)) {
178
+ (this.viewValue.includes(event.key) || this.min >= 0)) {
92
179
  event.preventDefault();
93
180
  return;
94
181
  }
182
+ if (isPeriod(event)) {
183
+ if (event.key === this.numberLocaleConfig.fractionSeparator &&
184
+ this.viewValue.indexOf(this.numberLocaleConfig.fractionSeparator) !== -1) {
185
+ event.preventDefault();
186
+ return;
187
+ }
188
+ }
95
189
  if (allowedKeys.indexOf(keyCode) !== -1 ||
96
- isCtrlA(event) ||
97
- isCtrlC(event) ||
98
- isCtrlV(event) ||
99
- isCtrlX(event) ||
100
- isCtrlZ(event) ||
101
- isFKey(event) ||
102
- isPeriod(event)) {
190
+ [
191
+ isCtrlA,
192
+ isCtrlC,
193
+ isCtrlV,
194
+ isCtrlX,
195
+ isCtrlZ,
196
+ isFunctionKey,
197
+ isPeriod
198
+ ].some((fn) => fn(event))) {
103
199
  // let it happen, don't do anything
104
200
  return;
105
201
  }
106
202
  // Ensure that it is not a number and stop the keypress
107
- if (event.shiftKey || !isNumber(event)) {
203
+ if (event.shiftKey || !isNumberKey(event) && !isNumpadKey(event)) {
108
204
  event.preventDefault();
109
205
  // process steps
110
206
  const step = event.shiftKey ? this.bigStep : this.step;
@@ -116,48 +212,153 @@ class KbqNumberInput {
116
212
  }
117
213
  }
118
214
  }
215
+ onInput(event) {
216
+ const currentValueLength = this.formatNumber(this.value)?.length || 0;
217
+ setTimeout(() => {
218
+ const fromPaste = event.inputType === 'insertFromPaste';
219
+ let formattedValue;
220
+ if (fromPaste) {
221
+ formattedValue = this.formatNumber(this.valueFromPaste);
222
+ }
223
+ else {
224
+ /*this.viewValue is raw and should be reformatted to localized number */
225
+ formattedValue = this.formatViewValue();
226
+ const offsetWhenSeparatorAdded = 2;
227
+ Promise.resolve().then(() => {
228
+ if (Math.abs(this.viewValue.length - currentValueLength) === offsetWhenSeparatorAdded) {
229
+ const cursorPosition = Math.max(0, (this.nativeElement.selectionStart || 0) + Math.sign(this.viewValue.length - currentValueLength));
230
+ this.renderer.setProperty(this.nativeElement, 'selectionStart', cursorPosition);
231
+ this.renderer.setProperty(this.nativeElement, 'selectionEnd', cursorPosition);
232
+ }
233
+ });
234
+ }
235
+ this.setViewValue(formattedValue, !fromPaste);
236
+ this.viewToModelUpdate(formattedValue);
237
+ });
238
+ }
119
239
  onPaste(event) {
120
- if (!isDigit(normalizeSplitter(event.clipboardData.getData('text')))) {
240
+ this.valueFromPaste = this.checkAndNormalizeLocalizedNumber(event.clipboardData?.getData('text'));
241
+ if (this.valueFromPaste === null) {
121
242
  event.preventDefault();
122
243
  }
123
244
  }
124
245
  stepUp(step) {
125
- this.elementRef.nativeElement.focus();
126
- const res = Math.max(Math.min(add(this.nativeElement.valueAsNumber || 0, step), this.max), this.min);
127
- this.nativeElement.value = res.toString();
128
- this.viewToModelUpdate(this.nativeElement.valueAsNumber);
246
+ this.nativeElement.focus();
247
+ const res = Math.max(Math.min(add(this.value || 0, step), this.max), this.min);
248
+ this.setViewValue(this.formatNumber(res));
249
+ this._value = res;
250
+ this.cvaOnChange(res);
251
+ this.valueChange.emit(res);
129
252
  }
130
253
  stepDown(step) {
131
- this.elementRef.nativeElement.focus();
132
- const res = Math.min(Math.max(add(this.nativeElement.valueAsNumber || 0, -step), this.min), this.max);
133
- this.nativeElement.value = res.toString();
134
- this.viewToModelUpdate(this.nativeElement.valueAsNumber);
254
+ this.nativeElement.focus();
255
+ const res = Math.min(Math.max(add(this.value || 0, -step), this.min), this.max);
256
+ this.setViewValue(this.formatNumber(res));
257
+ this._value = res;
258
+ this.cvaOnChange(res);
259
+ this.valueChange.emit(res);
135
260
  }
136
- viewToModelUpdate(value) {
137
- if (this.ngControl) {
138
- this.ngControl.control.setValue(value);
261
+ setViewValue(value, savePosition = false) {
262
+ const cursorPosition = this.nativeElement.selectionStart;
263
+ this.renderer.setProperty(this.nativeElement, 'value', value);
264
+ if (savePosition) {
265
+ this.renderer.setProperty(this.nativeElement, 'selectionStart', cursorPosition);
266
+ this.renderer.setProperty(this.nativeElement, 'selectionEnd', cursorPosition);
267
+ }
268
+ }
269
+ viewToModelUpdate(newValue) {
270
+ const normalizedValue = newValue === null ? null : +this.normalizeNumber(newValue);
271
+ if (normalizedValue !== this.value) {
272
+ this._value = normalizedValue;
273
+ this.cvaOnChange(normalizedValue);
274
+ this.valueChange.emit(normalizedValue);
275
+ }
276
+ this.ngControl?.updateValueAndValidity({ emitEvent: false });
277
+ }
278
+ formatViewValue() {
279
+ if (this.viewValue === null || this.viewValue === '' || Number.isNaN(+this.normalizeNumber(this.viewValue))) {
280
+ return null;
139
281
  }
282
+ const separator = this.numberLocaleConfig.groupSeparator.includes(' ')
283
+ && this.numberLocaleConfig.fractionSeparator === ','
284
+ ? /[,.]/
285
+ : this.numberLocaleConfig.fractionSeparator;
286
+ const [intPart, fractionPart] = this.viewValue.split(separator)
287
+ .map((valuePart) => this.normalizeNumber(valuePart));
288
+ return this.createLocalizedNumberFromParts(+intPart, fractionPart);
140
289
  }
141
- /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: KbqNumberInput, deps: [{ token: i0.ElementRef }, { token: i1.NgControl, optional: true, self: true }, { token: 'step', attribute: true }, { token: 'big-step', attribute: true }, { token: 'min', attribute: true }, { token: 'max', attribute: true }], target: i0.ɵɵFactoryTarget.Directive }); }
142
- /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: KbqNumberInput, selector: "input[kbqInput][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 }); }
290
+ formatNumber(value) {
291
+ if (value === null || value === undefined) {
292
+ return null;
293
+ }
294
+ const [intPart, fractionPart] = value.toString().split('.');
295
+ return this.createLocalizedNumberFromParts(+intPart, fractionPart);
296
+ }
297
+ createLocalizedNumberFromParts(intPart, fractionPart) {
298
+ const formatOptions = {
299
+ useGrouping: this.withThousandSeparator,
300
+ maximumFractionDigits: 20
301
+ };
302
+ if (this.withThousandSeparator && this.numberLocaleConfig.startFormattingFrom) {
303
+ formatOptions.useGrouping = intPart >= Math.pow(
304
+ // tslint:disable-next-line:no-magic-numbers
305
+ 10, this.numberLocaleConfig.startFormattingFrom);
306
+ }
307
+ const localeId = this.localeService.id === 'es-LA' ? 'ru-RU' : this.localeService.id;
308
+ const formatter = new Intl.NumberFormat(localeId, formatOptions);
309
+ const formattedFractionPart = fractionPart?.split('')
310
+ .map((numChar) => formatter.format(+numChar)).join('');
311
+ return formattedFractionPart === undefined
312
+ ? formatter.format(intPart)
313
+ : `${formatter.format(intPart)}${this.numberLocaleConfig.fractionSeparator}${formattedFractionPart}`;
314
+ }
315
+ /**
316
+ * Method that returns a string representation of a number without localized separators
317
+ */
318
+ normalizeNumber(value, customConfig) {
319
+ if (value === null || value === undefined) {
320
+ return '';
321
+ }
322
+ const { groupSeparator, fractionSeparator } = customConfig || this.numberLocaleConfig;
323
+ const groupSeparatorRegexp = new RegExp(`[${groupSeparator.join('')}]`, 'g');
324
+ const fractionSeparatorRegexp = new RegExp(`\\${fractionSeparator}`, 'g');
325
+ return value.toString()
326
+ .replace(groupSeparatorRegexp, '')
327
+ .replace(fractionSeparatorRegexp, '.');
328
+ }
329
+ checkAndNormalizeLocalizedNumber(num) {
330
+ if (num === null || num === undefined) {
331
+ return null;
332
+ }
333
+ /* if some locale input config satisfies pasted number, try to normalise with selected locale config */
334
+ let numberOutput = null;
335
+ for (const { config } of this.allNumberLocaleConfigs) {
336
+ const normalized = +this.normalizeNumber(num, config);
337
+ if (!Number.isNaN(normalized)) {
338
+ numberOutput = normalized;
339
+ break;
340
+ }
341
+ }
342
+ return numberOutput;
343
+ }
344
+ /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: KbqNumberInput, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: 'step', attribute: true }, { token: 'big-step', attribute: true }, { token: 'min', attribute: true }, { token: 'max', attribute: true }, { token: KBQ_LOCALE_SERVICE, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
345
+ /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.5", type: KbqNumberInput, selector: "input[kbqInput][type=\"number\"]", inputs: { bigStep: "bigStep", step: "step", min: "min", max: "max", withThousandSeparator: "withThousandSeparator", startFormattingFrom: "startFormattingFrom", value: "value", disabled: "disabled" }, host: { listeners: { "blur": "focusChanged(false)", "focus": "focusChanged(true)", "paste": "onPaste($event)", "keydown": "onKeyDown($event)", "input": "onInput($event)" } }, providers: [KBQ_NUMBER_INPUT_VALUE_ACCESSOR], exportAs: ["kbqNumericalInput"], ngImport: i0 }); }
143
346
  }
144
347
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImport: i0, type: KbqNumberInput, decorators: [{
145
348
  type: Directive,
146
349
  args: [{
147
350
  selector: `input[kbqInput][type="number"]`,
148
- exportAs: 'mcNumericalInput',
351
+ exportAs: 'kbqNumericalInput',
352
+ providers: [KBQ_NUMBER_INPUT_VALUE_ACCESSOR],
149
353
  host: {
150
354
  '(blur)': 'focusChanged(false)',
151
355
  '(focus)': 'focusChanged(true)',
152
356
  '(paste)': 'onPaste($event)',
153
- '(keydown)': 'onKeyDown($event)'
357
+ '(keydown)': 'onKeyDown($event)',
358
+ '(input)': 'onInput($event)'
154
359
  }
155
360
  }]
156
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.NgControl, decorators: [{
157
- type: Optional
158
- }, {
159
- type: Self
160
- }] }, { type: undefined, decorators: [{
361
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: undefined, decorators: [{
161
362
  type: Attribute,
162
363
  args: ['step']
163
364
  }] }, { type: undefined, decorators: [{
@@ -169,6 +370,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImpor
169
370
  }] }, { type: undefined, decorators: [{
170
371
  type: Attribute,
171
372
  args: ['max']
373
+ }] }, { type: i3.KbqLocaleService, decorators: [{
374
+ type: Optional
375
+ }, {
376
+ type: Inject,
377
+ args: [KBQ_LOCALE_SERVICE]
172
378
  }] }]; }, propDecorators: { bigStep: [{
173
379
  type: Input
174
380
  }], step: [{
@@ -177,6 +383,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImpor
177
383
  type: Input
178
384
  }], max: [{
179
385
  type: Input
386
+ }], withThousandSeparator: [{
387
+ type: Input
388
+ }], startFormattingFrom: [{
389
+ type: Input
390
+ }], value: [{
391
+ type: Input
392
+ }], disabled: [{
393
+ type: Input
180
394
  }] } });
181
395
 
182
396
  const KBQ_INPUT_VALUE_ACCESSOR = new InjectionToken('KBQ_INPUT_VALUE_ACCESSOR');
@@ -827,5 +1041,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.5", ngImpor
827
1041
  * Generated bundle index. Do not edit.
828
1042
  */
829
1043
 
830
- export { BIG_STEP, KBQ_INPUT_VALUE_ACCESSOR, KbqInput, KbqInputBase, KbqInputMixinBase, KbqInputModule, KbqInputMono, KbqInputPassword, KbqNumberInput, MAX_VALIDATOR, MIN_VALIDATOR, MaxValidator, MinValidator, SMALL_STEP, add, getPrecision, isDigit, isFloat, isInt, normalizeSplitter };
1044
+ export { BIG_STEP, KBQ_INPUT_VALUE_ACCESSOR, KBQ_NUMBER_INPUT_VALUE_ACCESSOR, KbqInput, KbqInputBase, KbqInputMixinBase, KbqInputModule, KbqInputMono, KbqInputPassword, KbqNumberInput, MAX_VALIDATOR, MIN_VALIDATOR, MaxValidator, MinValidator, SMALL_STEP, add, getPrecision, isDigit, isFloat, isInt, normalizeSplitter };
831
1045
  //# sourceMappingURL=koobiq-components-input.mjs.map