@caribeng/ui 22.1.1 → 22.2.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 (253) hide show
  1. package/README.md +48 -8
  2. package/fesm2022/caribeng-ui-accordion.mjs +2 -2
  3. package/fesm2022/caribeng-ui-anchor.mjs +169 -0
  4. package/fesm2022/caribeng-ui-autocomplete.mjs +10 -8
  5. package/fesm2022/caribeng-ui-avatargroup.mjs +9 -3
  6. package/fesm2022/caribeng-ui-blockui.mjs +12 -4
  7. package/fesm2022/caribeng-ui-breadcrumb.mjs +5 -2
  8. package/fesm2022/caribeng-ui-button.mjs +22 -2
  9. package/fesm2022/caribeng-ui-caribe-alert.mjs +5 -2
  10. package/fesm2022/caribeng-ui-caribe-animation-lottie.mjs +6 -3
  11. package/fesm2022/caribeng-ui-caribe-button-group.mjs +6 -3
  12. package/fesm2022/caribeng-ui-caribe-calendar.mjs +11 -6
  13. package/fesm2022/caribeng-ui-caribe-card-content.mjs +6 -3
  14. package/fesm2022/caribeng-ui-caribe-card-move.mjs +29 -7
  15. package/fesm2022/caribeng-ui-caribe-card-select.mjs +56 -14
  16. package/fesm2022/caribeng-ui-caribe-circle-loading.mjs +10 -7
  17. package/fesm2022/caribeng-ui-caribe-coachmark.mjs +42 -19
  18. package/fesm2022/caribeng-ui-caribe-data-table.mjs +15 -9
  19. package/fesm2022/caribeng-ui-caribe-dots-indicator.mjs +38 -5
  20. package/fesm2022/caribeng-ui-caribe-expansion-panel.mjs +16 -5
  21. package/fesm2022/caribeng-ui-caribe-fab-menu.mjs +56 -7
  22. package/fesm2022/caribeng-ui-caribe-file-download.mjs +68 -27
  23. package/fesm2022/caribeng-ui-caribe-file-select.mjs +22 -17
  24. package/fesm2022/caribeng-ui-caribe-float-menu.mjs +6 -3
  25. package/fesm2022/caribeng-ui-caribe-footer.mjs +8 -4
  26. package/fesm2022/caribeng-ui-caribe-header.mjs +6 -3
  27. package/fesm2022/caribeng-ui-caribe-icon-button.mjs +6 -3
  28. package/fesm2022/caribeng-ui-caribe-illustration.mjs +6 -3
  29. package/fesm2022/caribeng-ui-caribe-inline-alert.mjs +5 -2
  30. package/fesm2022/caribeng-ui-caribe-input-search.mjs +14 -10
  31. package/fesm2022/caribeng-ui-caribe-input-select.mjs +12 -10
  32. package/fesm2022/caribeng-ui-caribe-input-token.mjs +61 -11
  33. package/fesm2022/caribeng-ui-caribe-link.mjs +7 -2
  34. package/fesm2022/caribeng-ui-caribe-loader.mjs +8 -5
  35. package/fesm2022/caribeng-ui-caribe-modal.mjs +32 -16
  36. package/fesm2022/caribeng-ui-caribe-off-canvas.mjs +26 -12
  37. package/fesm2022/caribeng-ui-caribe-onboarding.mjs +44 -19
  38. package/fesm2022/caribeng-ui-caribe-pictogram.mjs +6 -3
  39. package/fesm2022/caribeng-ui-caribe-pop-over.mjs +34 -10
  40. package/fesm2022/caribeng-ui-caribe-preloader.mjs +9 -6
  41. package/fesm2022/caribeng-ui-caribe-progress-bar.mjs +5 -2
  42. package/fesm2022/caribeng-ui-caribe-shortcut.mjs +8 -3
  43. package/fesm2022/caribeng-ui-caribe-step-indicator.mjs +12 -5
  44. package/fesm2022/caribeng-ui-caribe-stroke.mjs +6 -3
  45. package/fesm2022/caribeng-ui-caribe-switch.mjs +5 -3
  46. package/fesm2022/caribeng-ui-caribe-tag-button.mjs +1 -1
  47. package/fesm2022/caribeng-ui-caribe-tracker.mjs +5 -2
  48. package/fesm2022/caribeng-ui-caribe-transaction-status.mjs +1 -1
  49. package/fesm2022/caribeng-ui-caribe-voucher.mjs +11 -8
  50. package/fesm2022/caribeng-ui-carousel.mjs +49 -14
  51. package/fesm2022/caribeng-ui-cascadeselect.mjs +22 -8
  52. package/fesm2022/caribeng-ui-chart.mjs +2598 -303
  53. package/fesm2022/caribeng-ui-chip.mjs +9 -4
  54. package/fesm2022/caribeng-ui-chips.mjs +9 -5
  55. package/fesm2022/caribeng-ui-colorpicker.mjs +9 -7
  56. package/fesm2022/caribeng-ui-confirmdialog.mjs +74 -9
  57. package/fesm2022/caribeng-ui-confirmpopup.mjs +134 -9
  58. package/fesm2022/caribeng-ui-contextmenu.mjs +6 -3
  59. package/fesm2022/caribeng-ui-dataview.mjs +211 -6
  60. package/fesm2022/caribeng-ui-datepicker.mjs +1630 -393
  61. package/fesm2022/caribeng-ui-descriptions.mjs +124 -0
  62. package/fesm2022/caribeng-ui-dialog.mjs +10 -7
  63. package/fesm2022/caribeng-ui-dock.mjs +6 -3
  64. package/fesm2022/caribeng-ui-drawer.mjs +10 -7
  65. package/fesm2022/caribeng-ui-dynamicdialog.mjs +210 -6
  66. package/fesm2022/caribeng-ui-editor.mjs +4392 -243
  67. package/fesm2022/caribeng-ui-empty.mjs +80 -0
  68. package/fesm2022/caribeng-ui-file-card.mjs +2 -2
  69. package/fesm2022/caribeng-ui-fileupload.mjs +96 -19
  70. package/fesm2022/caribeng-ui-floatlabel.mjs +4 -2
  71. package/fesm2022/caribeng-ui-folder-card.mjs +10 -3
  72. package/fesm2022/caribeng-ui-galleria.mjs +76 -45
  73. package/fesm2022/caribeng-ui-image.mjs +52 -29
  74. package/fesm2022/caribeng-ui-inplace.mjs +22 -6
  75. package/fesm2022/caribeng-ui-input-number.mjs +9 -7
  76. package/fesm2022/caribeng-ui-inputgroup.mjs +2 -2
  77. package/fesm2022/caribeng-ui-inputmask.mjs +14 -11
  78. package/fesm2022/caribeng-ui-inputotp.mjs +12 -6
  79. package/fesm2022/caribeng-ui-keyfilter.mjs +72 -0
  80. package/fesm2022/caribeng-ui-listbox.mjs +13 -11
  81. package/fesm2022/caribeng-ui-megamenu.mjs +222 -30
  82. package/fesm2022/caribeng-ui-menu.mjs +11 -5
  83. package/fesm2022/caribeng-ui-menubar.mjs +10 -5
  84. package/fesm2022/caribeng-ui-message.mjs +7 -4
  85. package/fesm2022/caribeng-ui-metergroup.mjs +29 -11
  86. package/fesm2022/caribeng-ui-multiselect.mjs +399 -97
  87. package/fesm2022/caribeng-ui-orderlist.mjs +230 -11
  88. package/fesm2022/caribeng-ui-organizationchart.mjs +12 -7
  89. package/fesm2022/caribeng-ui-paginator.mjs +18 -15
  90. package/fesm2022/caribeng-ui-panel.mjs +5 -2
  91. package/fesm2022/caribeng-ui-panelmenu.mjs +6 -3
  92. package/fesm2022/caribeng-ui-password.mjs +8 -6
  93. package/fesm2022/caribeng-ui-pdfviewer.mjs +1553 -0
  94. package/fesm2022/caribeng-ui-picklist.mjs +251 -14
  95. package/fesm2022/caribeng-ui-pricing.mjs +17 -14
  96. package/fesm2022/caribeng-ui-rating.mjs +7 -3
  97. package/fesm2022/caribeng-ui-repeater.mjs +223 -0
  98. package/fesm2022/caribeng-ui-result.mjs +91 -0
  99. package/fesm2022/caribeng-ui-scrollpanel.mjs +6 -3
  100. package/fesm2022/caribeng-ui-scrolltop.mjs +6 -3
  101. package/fesm2022/caribeng-ui-select.mjs +379 -87
  102. package/fesm2022/caribeng-ui-selectbutton.mjs +2 -2
  103. package/fesm2022/caribeng-ui-slider.mjs +171 -75
  104. package/fesm2022/caribeng-ui-speeddial.mjs +7 -4
  105. package/fesm2022/caribeng-ui-spinner.mjs +5 -2
  106. package/fesm2022/caribeng-ui-splitbutton.mjs +163 -0
  107. package/fesm2022/caribeng-ui-splitter.mjs +5 -2
  108. package/fesm2022/caribeng-ui-statistic.mjs +183 -0
  109. package/fesm2022/caribeng-ui-stepper.mjs +8 -5
  110. package/fesm2022/caribeng-ui-steps.mjs +6 -3
  111. package/fesm2022/caribeng-ui-table.mjs +708 -82
  112. package/fesm2022/caribeng-ui-tabmenu.mjs +6 -3
  113. package/fesm2022/caribeng-ui-tag.mjs +2 -2
  114. package/fesm2022/caribeng-ui-terminal.mjs +45 -9
  115. package/fesm2022/caribeng-ui-themetoggle.mjs +82 -0
  116. package/fesm2022/caribeng-ui-tieredmenu.mjs +9 -6
  117. package/fesm2022/caribeng-ui-timeline.mjs +175 -6
  118. package/fesm2022/caribeng-ui-toast.mjs +7 -4
  119. package/fesm2022/caribeng-ui-togglebutton.mjs +8 -6
  120. package/fesm2022/caribeng-ui-toolbar.mjs +6 -3
  121. package/fesm2022/caribeng-ui-tree.mjs +302 -6
  122. package/fesm2022/caribeng-ui-treeselect.mjs +26 -10
  123. package/fesm2022/caribeng-ui-treetable.mjs +269 -6
  124. package/fesm2022/caribeng-ui-virtualscroller.mjs +123 -10
  125. package/fesm2022/caribeng-ui.mjs +829 -6
  126. package/package.json +53 -3
  127. package/schematics/collection.json +10 -0
  128. package/schematics/ng-add/index.js +125 -0
  129. package/schematics/ng-add/schema.js +2 -0
  130. package/schematics/ng-add/schema.json +66 -0
  131. package/styles/caribeng.css +380 -0
  132. package/styles/scss/_mixins.scss +46 -0
  133. package/styles/scss/_overlay.scss +15 -0
  134. package/styles/scss/_tokens.scss +267 -0
  135. package/styles/scss/_utilities.scss +73 -0
  136. package/styles/scss/_variables.scss +33 -0
  137. package/styles/scss/index.scss +16 -0
  138. package/types/caribeng-ui-anchor.d.ts +50 -0
  139. package/types/caribeng-ui-autocomplete.d.ts +4 -2
  140. package/types/caribeng-ui-avatargroup.d.ts +3 -1
  141. package/types/caribeng-ui-blockui.d.ts +9 -4
  142. package/types/caribeng-ui-breadcrumb.d.ts +3 -0
  143. package/types/caribeng-ui-button.d.ts +9 -1
  144. package/types/caribeng-ui-caribe-alert.d.ts +3 -0
  145. package/types/caribeng-ui-caribe-animation-lottie.d.ts +4 -1
  146. package/types/caribeng-ui-caribe-button-group.d.ts +4 -1
  147. package/types/caribeng-ui-caribe-calendar.d.ts +5 -1
  148. package/types/caribeng-ui-caribe-card-content.d.ts +4 -1
  149. package/types/caribeng-ui-caribe-card-move.d.ts +13 -13
  150. package/types/caribeng-ui-caribe-card-select.d.ts +10 -1
  151. package/types/caribeng-ui-caribe-circle-loading.d.ts +4 -1
  152. package/types/caribeng-ui-caribe-coachmark.d.ts +6 -0
  153. package/types/caribeng-ui-caribe-data-table.d.ts +7 -2
  154. package/types/caribeng-ui-caribe-dots-indicator.d.ts +9 -0
  155. package/types/caribeng-ui-caribe-expansion-panel.d.ts +7 -10
  156. package/types/caribeng-ui-caribe-fab-menu.d.ts +10 -1
  157. package/types/caribeng-ui-caribe-file-download.d.ts +8 -10
  158. package/types/caribeng-ui-caribe-file-select.d.ts +7 -1
  159. package/types/caribeng-ui-caribe-float-menu.d.ts +4 -1
  160. package/types/caribeng-ui-caribe-header.d.ts +3 -0
  161. package/types/caribeng-ui-caribe-icon-button.d.ts +4 -1
  162. package/types/caribeng-ui-caribe-illustration.d.ts +4 -1
  163. package/types/caribeng-ui-caribe-inline-alert.d.ts +3 -0
  164. package/types/caribeng-ui-caribe-input-search.d.ts +4 -2
  165. package/types/caribeng-ui-caribe-input-select.d.ts +4 -2
  166. package/types/caribeng-ui-caribe-input-token.d.ts +16 -1
  167. package/types/caribeng-ui-caribe-link.d.ts +3 -0
  168. package/types/caribeng-ui-caribe-loader.d.ts +4 -1
  169. package/types/caribeng-ui-caribe-modal.d.ts +7 -10
  170. package/types/caribeng-ui-caribe-off-canvas.d.ts +6 -1
  171. package/types/caribeng-ui-caribe-onboarding.d.ts +6 -0
  172. package/types/caribeng-ui-caribe-pictogram.d.ts +4 -1
  173. package/types/caribeng-ui-caribe-pop-over.d.ts +7 -10
  174. package/types/caribeng-ui-caribe-preloader.d.ts +4 -1
  175. package/types/caribeng-ui-caribe-progress-bar.d.ts +3 -0
  176. package/types/caribeng-ui-caribe-shortcut.d.ts +3 -1
  177. package/types/caribeng-ui-caribe-step-indicator.d.ts +6 -0
  178. package/types/caribeng-ui-caribe-stroke.d.ts +4 -1
  179. package/types/caribeng-ui-caribe-switch.d.ts +3 -1
  180. package/types/caribeng-ui-caribe-tracker.d.ts +3 -0
  181. package/types/caribeng-ui-caribe-voucher.d.ts +5 -2
  182. package/types/caribeng-ui-carousel.d.ts +10 -1
  183. package/types/caribeng-ui-cascadeselect.d.ts +7 -2
  184. package/types/caribeng-ui-chart.d.ts +469 -44
  185. package/types/caribeng-ui-chip.d.ts +6 -0
  186. package/types/caribeng-ui-chips.d.ts +6 -2
  187. package/types/caribeng-ui-colorpicker.d.ts +3 -1
  188. package/types/caribeng-ui-confirmdialog.d.ts +25 -6
  189. package/types/caribeng-ui-confirmpopup.d.ts +37 -5
  190. package/types/caribeng-ui-contextmenu.d.ts +4 -1
  191. package/types/caribeng-ui-dataview.d.ts +63 -5
  192. package/types/caribeng-ui-datepicker.d.ts +186 -21
  193. package/types/caribeng-ui-descriptions.d.ts +63 -0
  194. package/types/caribeng-ui-dialog.d.ts +4 -1
  195. package/types/caribeng-ui-dock.d.ts +4 -1
  196. package/types/caribeng-ui-drawer.d.ts +4 -1
  197. package/types/caribeng-ui-dynamicdialog.d.ts +93 -3
  198. package/types/caribeng-ui-editor.d.ts +486 -13
  199. package/types/caribeng-ui-empty.d.ts +34 -0
  200. package/types/caribeng-ui-file-card.d.ts +1 -1
  201. package/types/caribeng-ui-fileupload.d.ts +27 -4
  202. package/types/caribeng-ui-folder-card.d.ts +4 -1
  203. package/types/caribeng-ui-galleria.d.ts +9 -0
  204. package/types/caribeng-ui-image.d.ts +10 -0
  205. package/types/caribeng-ui-inplace.d.ts +8 -0
  206. package/types/caribeng-ui-input-number.d.ts +3 -1
  207. package/types/caribeng-ui-inputmask.d.ts +5 -0
  208. package/types/caribeng-ui-inputotp.d.ts +7 -2
  209. package/types/caribeng-ui-keyfilter.d.ts +30 -0
  210. package/types/caribeng-ui-listbox.d.ts +5 -3
  211. package/types/caribeng-ui-megamenu.d.ts +26 -2
  212. package/types/caribeng-ui-menu.d.ts +7 -2
  213. package/types/caribeng-ui-menubar.d.ts +5 -1
  214. package/types/caribeng-ui-message.d.ts +3 -0
  215. package/types/caribeng-ui-metergroup.d.ts +9 -1
  216. package/types/caribeng-ui-multiselect.d.ts +71 -10
  217. package/types/caribeng-ui-orderlist.d.ts +58 -6
  218. package/types/caribeng-ui-organizationchart.d.ts +7 -1
  219. package/types/caribeng-ui-paginator.d.ts +3 -0
  220. package/types/caribeng-ui-panel.d.ts +3 -0
  221. package/types/caribeng-ui-panelmenu.d.ts +4 -1
  222. package/types/caribeng-ui-password.d.ts +4 -2
  223. package/types/caribeng-ui-pdfviewer.d.ts +258 -0
  224. package/types/caribeng-ui-picklist.d.ts +67 -7
  225. package/types/caribeng-ui-pricing.d.ts +8 -5
  226. package/types/caribeng-ui-rating.d.ts +6 -2
  227. package/types/caribeng-ui-repeater.d.ts +79 -0
  228. package/types/caribeng-ui-result.d.ts +35 -0
  229. package/types/caribeng-ui-scrollpanel.d.ts +4 -1
  230. package/types/caribeng-ui-scrolltop.d.ts +4 -1
  231. package/types/caribeng-ui-select.d.ts +73 -9
  232. package/types/caribeng-ui-slider.d.ts +63 -10
  233. package/types/caribeng-ui-speeddial.d.ts +5 -2
  234. package/types/caribeng-ui-spinner.d.ts +3 -0
  235. package/types/caribeng-ui-splitbutton.d.ts +49 -0
  236. package/types/caribeng-ui-splitter.d.ts +3 -0
  237. package/types/caribeng-ui-statistic.d.ts +65 -0
  238. package/types/caribeng-ui-stepper.d.ts +3 -0
  239. package/types/caribeng-ui-steps.d.ts +4 -1
  240. package/types/caribeng-ui-table.d.ts +184 -16
  241. package/types/caribeng-ui-tabmenu.d.ts +4 -1
  242. package/types/caribeng-ui-terminal.d.ts +10 -0
  243. package/types/caribeng-ui-themetoggle.d.ts +32 -0
  244. package/types/caribeng-ui-tieredmenu.d.ts +5 -2
  245. package/types/caribeng-ui-timeline.d.ts +63 -4
  246. package/types/caribeng-ui-toast.d.ts +3 -0
  247. package/types/caribeng-ui-togglebutton.d.ts +5 -3
  248. package/types/caribeng-ui-toolbar.d.ts +7 -4
  249. package/types/caribeng-ui-tree.d.ts +76 -4
  250. package/types/caribeng-ui-treeselect.d.ts +10 -2
  251. package/types/caribeng-ui-treetable.d.ts +68 -4
  252. package/types/caribeng-ui-virtualscroller.d.ts +45 -5
  253. package/types/caribeng-ui.d.ts +501 -12
@@ -1,6 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, viewChild, signal, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { input, viewChild, inject, Injector, signal, computed, afterNextRender, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import * as i1 from '@angular/cdk/a11y';
4
+ import { A11yModule } from '@angular/cdk/a11y';
3
5
  import { CbIcon } from '@caribeng/ui/icon';
6
+ import { injectCbTranslation, cbFormat } from '@caribeng/ui';
4
7
 
5
8
  /**
6
9
  * Image de CaribeNG: imagen con previsualización lightbox accesible y controles
@@ -8,6 +11,10 @@ import { CbIcon } from '@caribeng/ui/icon';
8
11
  */
9
12
  class CbImage {
10
13
  constructor() {
14
+ /** Textos de interfaz en el idioma activo (`provideCaribeNG({ locale })`). */
15
+ this.t = injectCbTranslation();
16
+ /** Rellena `{0}`, `{1}`… de un texto traducido. */
17
+ this.fmt = cbFormat;
11
18
  this.src = input('', /* @ts-ignore */
12
19
  ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
13
20
  this.alt = input('', /* @ts-ignore */
@@ -20,6 +27,11 @@ class CbImage {
20
27
  ...(ngDevMode ? [{ debugName: "preview" }] : /* istanbul ignore next */ []));
21
28
  this.lightboxEl = viewChild('lightbox', /* @ts-ignore */
22
29
  ...(ngDevMode ? [{ debugName: "lightboxEl" }] : /* istanbul ignore next */ []));
30
+ this.overlayBtn = viewChild('overlay', /* @ts-ignore */
31
+ ...(ngDevMode ? [{ debugName: "overlayBtn" }] : /* istanbul ignore next */ []));
32
+ this.closeBtn = viewChild('closeBtn', /* @ts-ignore */
33
+ ...(ngDevMode ? [{ debugName: "closeBtn" }] : /* istanbul ignore next */ []));
34
+ this.injector = inject(Injector);
23
35
  this.lightboxOpen = signal(false, /* @ts-ignore */
24
36
  ...(ngDevMode ? [{ debugName: "lightboxOpen" }] : /* istanbul ignore next */ []));
25
37
  this.scale = signal(1, /* @ts-ignore */
@@ -43,9 +55,14 @@ class CbImage {
43
55
  return;
44
56
  this.reset();
45
57
  this.lightboxOpen.set(true);
58
+ afterNextRender(() => this.closeBtn()?.nativeElement.focus(), { injector: this.injector });
46
59
  }
60
+ /** Cierra la previsualización y devuelve el foco al botón que la abrió. */
47
61
  closePreview() {
62
+ if (!this.lightboxOpen())
63
+ return;
48
64
  this.lightboxOpen.set(false);
65
+ afterNextRender(() => this.overlayBtn()?.nativeElement.focus(), { injector: this.injector });
49
66
  }
50
67
  zoomIn() {
51
68
  this.scale.set(Math.min(3, Number((this.scale() + 0.25).toFixed(2))));
@@ -90,7 +107,7 @@ class CbImage {
90
107
  }
91
108
  }
92
109
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbImage, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
93
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CbImage, isStandalone: true, selector: "cb-image", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, preview: { classPropertyName: "preview", publicName: "preview", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.cb-image--preview": "preview()" }, classAttribute: "cb-image" }, viewQueries: [{ propertyName: "lightboxEl", first: true, predicate: ["lightbox"], descendants: true, isSignal: true }], ngImport: i0, template: `
110
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CbImage, isStandalone: true, selector: "cb-image", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, preview: { classPropertyName: "preview", publicName: "preview", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.cb-image--preview": "preview()" }, classAttribute: "cb-image" }, viewQueries: [{ propertyName: "lightboxEl", first: true, predicate: ["lightbox"], descendants: true, isSignal: true }, { propertyName: "overlayBtn", first: true, predicate: ["overlay"], descendants: true, isSignal: true }, { propertyName: "closeBtn", first: true, predicate: ["closeBtn"], descendants: true, isSignal: true }], ngImport: i0, template: `
94
111
  <div class="cb-image__wrapper">
95
112
  <img
96
113
  class="cb-image__img"
@@ -101,9 +118,10 @@ class CbImage {
101
118
  />
102
119
  @if (preview()) {
103
120
  <button
121
+ #overlay
104
122
  type="button"
105
123
  class="cb-image__overlay"
106
- [attr.aria-label]="'Ampliar ' + (alt() || 'imagen')"
124
+ [attr.aria-label]="fmt(t().enlargeImage, alt() || t().image)"
107
125
  (click)="openPreview()"
108
126
  >
109
127
  <cb-icon name="search" [size]="20" aria-hidden="true" />
@@ -117,23 +135,25 @@ class CbImage {
117
135
  class="cb-image__lightbox"
118
136
  role="dialog"
119
137
  aria-modal="true"
120
- [attr.aria-label]="alt() || 'Previsualización de imagen'"
138
+ [attr.aria-label]="alt() || t().imagePreview"
139
+ cdkTrapFocus
121
140
  (click)="closePreview()"
141
+ (keydown.escape)="closePreview()"
122
142
  >
123
143
  <div class="cb-image__toolbar" (click)="$event.stopPropagation()">
124
- <button type="button" class="cb-image__tool" (click)="rotateLeft()" aria-label="Rotar a la izquierda">
144
+ <button type="button" class="cb-image__tool" (click)="rotateLeft()" [attr.aria-label]="t().rotateLeft">
125
145
  <cb-icon name="rotate-ccw" [size]="18" aria-hidden="true" />
126
146
  </button>
127
- <button type="button" class="cb-image__tool" (click)="rotateRight()" aria-label="Rotar a la derecha">
147
+ <button type="button" class="cb-image__tool" (click)="rotateRight()" [attr.aria-label]="t().rotateRight">
128
148
  <cb-icon name="rotate-cw" [size]="18" aria-hidden="true" />
129
149
  </button>
130
- <button type="button" class="cb-image__tool" (click)="flipHorizontal()" aria-label="Voltear horizontal">
150
+ <button type="button" class="cb-image__tool" (click)="flipHorizontal()" [attr.aria-label]="t().flipHorizontal">
131
151
  <cb-icon name="flip-horizontal" [size]="18" aria-hidden="true" />
132
152
  </button>
133
- <button type="button" class="cb-image__tool" (click)="flipVertical()" aria-label="Voltear vertical">
153
+ <button type="button" class="cb-image__tool" (click)="flipVertical()" [attr.aria-label]="t().flipVertical">
134
154
  <cb-icon name="flip-vertical" [size]="18" aria-hidden="true" />
135
155
  </button>
136
- <button type="button" class="cb-image__tool" (click)="zoomIn()" aria-label="Acercar">
156
+ <button type="button" class="cb-image__tool" (click)="zoomIn()" [attr.aria-label]="t().zoomIn">
137
157
  <cb-icon name="plus" [size]="18" aria-hidden="true" />
138
158
  </button>
139
159
  <button
@@ -141,20 +161,20 @@ class CbImage {
141
161
  class="cb-image__tool"
142
162
  (click)="zoomOut()"
143
163
  [disabled]="scale() <= 0.5"
144
- aria-label="Alejar"
164
+ [attr.aria-label]="t().zoomOut"
145
165
  >
146
166
  <cb-icon name="minus" [size]="18" aria-hidden="true" />
147
167
  </button>
148
- <button type="button" class="cb-image__tool" (click)="reset()" aria-label="Restablecer">
168
+ <button type="button" class="cb-image__tool" (click)="reset()" [attr.aria-label]="t().reset">
149
169
  <cb-icon name="refresh-cw" [size]="18" aria-hidden="true" />
150
170
  </button>
151
- <button type="button" class="cb-image__tool" (click)="download()" aria-label="Descargar">
171
+ <button type="button" class="cb-image__tool" (click)="download()" [attr.aria-label]="t().download">
152
172
  <cb-icon name="download" [size]="18" aria-hidden="true" />
153
173
  </button>
154
- <button type="button" class="cb-image__tool" (click)="toggleFullscreen()" aria-label="Pantalla completa">
174
+ <button type="button" class="cb-image__tool" (click)="toggleFullscreen()" [attr.aria-label]="t().fullscreen">
155
175
  <cb-icon name="expand" [size]="18" aria-hidden="true" />
156
176
  </button>
157
- <button type="button" class="cb-image__tool" (click)="closePreview()" aria-label="Cerrar">
177
+ <button #closeBtn type="button" class="cb-image__tool" (click)="closePreview()" [attr.aria-label]="t().close">
158
178
  <cb-icon name="x" [size]="18" aria-hidden="true" />
159
179
  </button>
160
180
  </div>
@@ -167,11 +187,11 @@ class CbImage {
167
187
  />
168
188
  </div>
169
189
  }
170
- `, isInline: true, styles: [":host{display:inline-block;font-family:var(--cb-font-sans)}.cb-image__wrapper{position:relative;display:inline-block;border-radius:var(--cb-radius-md);overflow:hidden}.cb-image__img{display:block;max-width:100%;border-radius:var(--cb-radius-md)}.cb-image__overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;border:none;background:#0f172a73;color:#fff;opacity:0;cursor:pointer;transition:opacity .15s ease}.cb-image__wrapper:hover .cb-image__overlay,.cb-image__overlay:focus-visible{opacity:1}.cb-image__lightbox{position:fixed;inset:0;z-index:60;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#0f172ad1;padding:var(--cb-space-4)}.cb-image__toolbar{position:absolute;top:1rem;right:1rem;display:inline-flex;gap:.375rem}.cb-image__tool{display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border:none;border-radius:999px;background:#ffffff24;color:#fff;cursor:pointer}.cb-image__lightbox-img{max-width:85vw;max-height:80vh;border-radius:var(--cb-radius-md);transition:transform .16s ease}\n"], dependencies: [{ kind: "component", type: CbIcon, selector: "cb-icon", inputs: ["name", "size", "spin", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
190
+ `, isInline: true, styles: [":host{display:inline-block;font-family:var(--cb-font-sans)}.cb-image__wrapper{position:relative;display:inline-block;border-radius:var(--cb-radius-md);overflow:hidden}.cb-image__img{display:block;max-width:100%;border-radius:var(--cb-radius-md)}.cb-image__overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;border:none;background:#0f172a73;color:#fff;opacity:0;cursor:pointer;transition:opacity .15s ease}.cb-image__wrapper:hover .cb-image__overlay,.cb-image__overlay:focus-visible{opacity:1}.cb-image__lightbox{position:fixed;inset:0;z-index:60;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#0f172ad1;padding:var(--cb-space-4)}.cb-image__toolbar{position:absolute;top:1rem;right:1rem;display:inline-flex;gap:.375rem}.cb-image__tool{display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border:none;border-radius:999px;background:#ffffff24;color:#fff;cursor:pointer}.cb-image__lightbox-img{max-width:85vw;max-height:80vh;border-radius:var(--cb-radius-md);transition:transform .16s ease}\n"], dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: CbIcon, selector: "cb-icon", inputs: ["name", "size", "spin", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
171
191
  }
172
192
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbImage, decorators: [{
173
193
  type: Component,
174
- args: [{ selector: 'cb-image', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, imports: [CbIcon], host: {
194
+ args: [{ selector: 'cb-image', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, imports: [A11yModule, CbIcon], host: {
175
195
  class: 'cb-image',
176
196
  '[class.cb-image--preview]': 'preview()',
177
197
  }, template: `
@@ -185,9 +205,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
185
205
  />
186
206
  @if (preview()) {
187
207
  <button
208
+ #overlay
188
209
  type="button"
189
210
  class="cb-image__overlay"
190
- [attr.aria-label]="'Ampliar ' + (alt() || 'imagen')"
211
+ [attr.aria-label]="fmt(t().enlargeImage, alt() || t().image)"
191
212
  (click)="openPreview()"
192
213
  >
193
214
  <cb-icon name="search" [size]="20" aria-hidden="true" />
@@ -201,23 +222,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
201
222
  class="cb-image__lightbox"
202
223
  role="dialog"
203
224
  aria-modal="true"
204
- [attr.aria-label]="alt() || 'Previsualización de imagen'"
225
+ [attr.aria-label]="alt() || t().imagePreview"
226
+ cdkTrapFocus
205
227
  (click)="closePreview()"
228
+ (keydown.escape)="closePreview()"
206
229
  >
207
230
  <div class="cb-image__toolbar" (click)="$event.stopPropagation()">
208
- <button type="button" class="cb-image__tool" (click)="rotateLeft()" aria-label="Rotar a la izquierda">
231
+ <button type="button" class="cb-image__tool" (click)="rotateLeft()" [attr.aria-label]="t().rotateLeft">
209
232
  <cb-icon name="rotate-ccw" [size]="18" aria-hidden="true" />
210
233
  </button>
211
- <button type="button" class="cb-image__tool" (click)="rotateRight()" aria-label="Rotar a la derecha">
234
+ <button type="button" class="cb-image__tool" (click)="rotateRight()" [attr.aria-label]="t().rotateRight">
212
235
  <cb-icon name="rotate-cw" [size]="18" aria-hidden="true" />
213
236
  </button>
214
- <button type="button" class="cb-image__tool" (click)="flipHorizontal()" aria-label="Voltear horizontal">
237
+ <button type="button" class="cb-image__tool" (click)="flipHorizontal()" [attr.aria-label]="t().flipHorizontal">
215
238
  <cb-icon name="flip-horizontal" [size]="18" aria-hidden="true" />
216
239
  </button>
217
- <button type="button" class="cb-image__tool" (click)="flipVertical()" aria-label="Voltear vertical">
240
+ <button type="button" class="cb-image__tool" (click)="flipVertical()" [attr.aria-label]="t().flipVertical">
218
241
  <cb-icon name="flip-vertical" [size]="18" aria-hidden="true" />
219
242
  </button>
220
- <button type="button" class="cb-image__tool" (click)="zoomIn()" aria-label="Acercar">
243
+ <button type="button" class="cb-image__tool" (click)="zoomIn()" [attr.aria-label]="t().zoomIn">
221
244
  <cb-icon name="plus" [size]="18" aria-hidden="true" />
222
245
  </button>
223
246
  <button
@@ -225,20 +248,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
225
248
  class="cb-image__tool"
226
249
  (click)="zoomOut()"
227
250
  [disabled]="scale() <= 0.5"
228
- aria-label="Alejar"
251
+ [attr.aria-label]="t().zoomOut"
229
252
  >
230
253
  <cb-icon name="minus" [size]="18" aria-hidden="true" />
231
254
  </button>
232
- <button type="button" class="cb-image__tool" (click)="reset()" aria-label="Restablecer">
255
+ <button type="button" class="cb-image__tool" (click)="reset()" [attr.aria-label]="t().reset">
233
256
  <cb-icon name="refresh-cw" [size]="18" aria-hidden="true" />
234
257
  </button>
235
- <button type="button" class="cb-image__tool" (click)="download()" aria-label="Descargar">
258
+ <button type="button" class="cb-image__tool" (click)="download()" [attr.aria-label]="t().download">
236
259
  <cb-icon name="download" [size]="18" aria-hidden="true" />
237
260
  </button>
238
- <button type="button" class="cb-image__tool" (click)="toggleFullscreen()" aria-label="Pantalla completa">
261
+ <button type="button" class="cb-image__tool" (click)="toggleFullscreen()" [attr.aria-label]="t().fullscreen">
239
262
  <cb-icon name="expand" [size]="18" aria-hidden="true" />
240
263
  </button>
241
- <button type="button" class="cb-image__tool" (click)="closePreview()" aria-label="Cerrar">
264
+ <button #closeBtn type="button" class="cb-image__tool" (click)="closePreview()" [attr.aria-label]="t().close">
242
265
  <cb-icon name="x" [size]="18" aria-hidden="true" />
243
266
  </button>
244
267
  </div>
@@ -252,7 +275,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
252
275
  </div>
253
276
  }
254
277
  `, styles: [":host{display:inline-block;font-family:var(--cb-font-sans)}.cb-image__wrapper{position:relative;display:inline-block;border-radius:var(--cb-radius-md);overflow:hidden}.cb-image__img{display:block;max-width:100%;border-radius:var(--cb-radius-md)}.cb-image__overlay{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;border:none;background:#0f172a73;color:#fff;opacity:0;cursor:pointer;transition:opacity .15s ease}.cb-image__wrapper:hover .cb-image__overlay,.cb-image__overlay:focus-visible{opacity:1}.cb-image__lightbox{position:fixed;inset:0;z-index:60;display:flex;flex-direction:column;align-items:center;justify-content:center;background:#0f172ad1;padding:var(--cb-space-4)}.cb-image__toolbar{position:absolute;top:1rem;right:1rem;display:inline-flex;gap:.375rem}.cb-image__tool{display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border:none;border-radius:999px;background:#ffffff24;color:#fff;cursor:pointer}.cb-image__lightbox-img{max-width:85vw;max-height:80vh;border-radius:var(--cb-radius-md);transition:transform .16s ease}\n"] }]
255
- }], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], preview: [{ type: i0.Input, args: [{ isSignal: true, alias: "preview", required: false }] }], lightboxEl: [{ type: i0.ViewChild, args: ['lightbox', { isSignal: true }] }] } });
278
+ }], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], preview: [{ type: i0.Input, args: [{ isSignal: true, alias: "preview", required: false }] }], lightboxEl: [{ type: i0.ViewChild, args: ['lightbox', { isSignal: true }] }], overlayBtn: [{ type: i0.ViewChild, args: ['overlay', { isSignal: true }] }], closeBtn: [{ type: i0.ViewChild, args: ['closeBtn', { isSignal: true }] }] } });
256
279
 
257
280
  /**
258
281
  * Generated bundle index. Do not edit.
@@ -1,6 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, model, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { input, model, inject, ElementRef, Injector, afterNextRender, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { CbIcon } from '@caribeng/ui/icon';
4
+ import { injectCbTranslation } from '@caribeng/ui';
4
5
 
5
6
  /**
6
7
  * Inplace de CaribeNG: alterna entre una vista previa (`[cb-inplace-display]`)
@@ -8,22 +9,36 @@ import { CbIcon } from '@caribeng/ui/icon';
8
9
  */
9
10
  class CbInplace {
10
11
  constructor() {
12
+ /** Textos de interfaz en el idioma activo (`provideCaribeNG({ locale })`). */
13
+ this.t = injectCbTranslation();
11
14
  this.closable = input(false, /* @ts-ignore */
12
15
  ...(ngDevMode ? [{ debugName: "closable" }] : /* istanbul ignore next */ []));
13
16
  this.disabled = input(false, /* @ts-ignore */
14
17
  ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
15
18
  this.active = model(false, /* @ts-ignore */
16
19
  ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
20
+ this.host = inject(ElementRef);
21
+ this.injector = inject(Injector);
17
22
  }
23
+ /** Muestra el contenido y mueve el foco a su primer elemento enfocable. */
18
24
  open() {
19
- if (!this.disabled())
20
- this.active.set(true);
25
+ if (this.disabled())
26
+ return;
27
+ this.active.set(true);
28
+ this.focusAfterRender('.cb-inplace__content :is(input, select, textarea, button, a[href], [tabindex]:not([tabindex="-1"]))');
21
29
  }
30
+ /** Vuelve a la vista previa y devuelve el foco a ella. */
22
31
  close() {
23
32
  this.active.set(false);
33
+ this.focusAfterRender('.cb-inplace__display');
34
+ }
35
+ focusAfterRender(selector) {
36
+ afterNextRender(() => this.host.nativeElement.querySelector(selector)?.focus(), {
37
+ injector: this.injector,
38
+ });
24
39
  }
25
40
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbInplace, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
26
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CbInplace, isStandalone: true, selector: "cb-inplace", inputs: { closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { active: "activeChange" }, host: { properties: { "class.cb-is-active": "active()" }, classAttribute: "cb-inplace" }, ngImport: i0, template: `
41
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CbInplace, isStandalone: true, selector: "cb-inplace", inputs: { closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { active: "activeChange" }, host: { listeners: { "keydown.escape": "closable() && active() && close()" }, properties: { "class.cb-is-active": "active()" }, classAttribute: "cb-inplace" }, ngImport: i0, template: `
27
42
  @if (!active()) {
28
43
  <button
29
44
  type="button"
@@ -40,7 +55,7 @@ class CbInplace {
40
55
  <button
41
56
  type="button"
42
57
  class="cb-inplace__close"
43
- aria-label="Cerrar edición"
58
+ [attr.aria-label]="t().closeEditing"
44
59
  (click)="close()"
45
60
  >
46
61
  <cb-icon name="x" [size]="15" aria-hidden="true" />
@@ -55,6 +70,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
55
70
  args: [{ selector: 'cb-inplace', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, imports: [CbIcon], host: {
56
71
  class: 'cb-inplace',
57
72
  '[class.cb-is-active]': 'active()',
73
+ '(keydown.escape)': 'closable() && active() && close()',
58
74
  }, template: `
59
75
  @if (!active()) {
60
76
  <button
@@ -72,7 +88,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
72
88
  <button
73
89
  type="button"
74
90
  class="cb-inplace__close"
75
- aria-label="Cerrar edición"
91
+ [attr.aria-label]="t().closeEditing"
76
92
  (click)="close()"
77
93
  >
78
94
  <cb-icon name="x" [size]="15" aria-hidden="true" />
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { model, input, signal, computed, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
- import { cbFieldState } from '@caribeng/ui';
4
+ import { injectCbTranslation, cbFieldState } from '@caribeng/ui';
5
5
  import { CbIcon } from '@caribeng/ui/icon';
6
6
 
7
7
  let nextUid = 0;
@@ -18,6 +18,8 @@ let nextUid = 0;
18
18
  */
19
19
  class CbInputNumber {
20
20
  constructor() {
21
+ /** Textos de interfaz en el idioma activo (`provideCaribeNG({ locale })`). */
22
+ this.t = injectCbTranslation();
21
23
  /** Valor numérico (two-way opcional fuera de Angular Forms). */
22
24
  this.value = model(null, /* @ts-ignore */
23
25
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -295,7 +297,7 @@ class CbInputNumber {
295
297
  type="button"
296
298
  class="cb-input-number__btn cb-input-number__btn--up"
297
299
  tabindex="-1"
298
- aria-label="Incrementar"
300
+ [attr.aria-label]="t().increment"
299
301
  [disabled]="isDisabled() || readonly() || isAtMax()"
300
302
  (click)="increment()"
301
303
  >
@@ -305,7 +307,7 @@ class CbInputNumber {
305
307
  type="button"
306
308
  class="cb-input-number__btn cb-input-number__btn--down"
307
309
  tabindex="-1"
308
- aria-label="Decrementar"
310
+ [attr.aria-label]="t().decrement"
309
311
  [disabled]="isDisabled() || readonly() || isAtMin()"
310
312
  (click)="decrement()"
311
313
  >
@@ -324,7 +326,7 @@ class CbInputNumber {
324
326
  {{ hint() }}
325
327
  </p>
326
328
  }
327
- `, isInline: true, styles: [":host{display:block}.cb-input-number__label{display:block;margin-bottom:var(--cb-space-1);font-family:var(--cb-font-sans);font-size:var(--cb-text-sm);font-weight:var(--cb-font-weight-medium);color:var(--cb-color-text)}.cb-input-number__required{color:var(--cb-color-danger);margin-left:2px}.cb-input-number{position:relative;display:flex;align-items:stretch;box-sizing:border-box;width:100%;background-color:var(--cb-color-bg);border:var(--cb-border-width) solid var(--cb-color-border-strong);border-radius:var(--cb-radius-md);transition:border-color var(--cb-duration-fast) var(--cb-ease),box-shadow var(--cb-duration-fast) var(--cb-ease)}.cb-input-number:hover:not(.cb-is-disabled):not(:focus-within){border-color:var(--cb-color-text-muted)}.cb-input-number:focus-within{border-color:var(--cb-color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--cb-color-primary-500) 25%,transparent)}.cb-input-number.cb-is-invalid{border-color:var(--cb-color-danger)}.cb-input-number.cb-is-invalid:focus-within{box-shadow:0 0 0 3px color-mix(in srgb,var(--cb-color-danger) 25%,transparent)}.cb-input-number.cb-is-disabled{background-color:var(--cb-color-surface);opacity:.8}.cb-input-number__field{flex:1 1 auto;min-width:0;box-sizing:border-box;font-family:var(--cb-font-sans);color:var(--cb-color-text);background:transparent;border:none;border-radius:inherit;text-align:right}.cb-input-number__field::placeholder{color:var(--cb-color-text-muted)}.cb-input-number__field:focus{outline:none}.cb-input-number__field:disabled{color:var(--cb-color-text-muted);cursor:not-allowed}.cb-input-number--sm .cb-input-number__field{min-height:2rem;padding:var(--cb-space-1) var(--cb-space-2);font-size:var(--cb-text-sm)}.cb-input-number--md .cb-input-number__field{min-height:2.5rem;padding:var(--cb-space-2) var(--cb-space-3);font-size:var(--cb-text-base)}.cb-input-number--lg .cb-input-number__field{min-height:3rem;padding:var(--cb-space-3) var(--cb-space-4);font-size:var(--cb-text-lg)}.cb-input-number__buttons{display:flex;flex:none;flex-direction:column;border-left:var(--cb-border-width) solid var(--cb-color-border)}.cb-input-number__btn{display:flex;flex:1 1 50%;align-items:center;justify-content:center;width:2rem;padding:0;color:var(--cb-color-text-muted);background-color:var(--cb-color-surface-50);border:none;cursor:pointer;transition:background-color var(--cb-duration-fast) var(--cb-ease)}.cb-input-number__btn:hover:not(:disabled){background-color:var(--cb-color-surface-100);color:var(--cb-color-text)}.cb-input-number__btn:disabled{opacity:.4;cursor:not-allowed}.cb-input-number__btn--up{border-top-right-radius:var(--cb-radius-md);border-bottom:var(--cb-border-width) solid var(--cb-color-border)}.cb-input-number__btn--down{border-bottom-right-radius:var(--cb-radius-md)}.cb-input-number__btn cb-icon{color:currentColor}.cb-input-number__message{margin:var(--cb-space-1) 0 0;font-size:var(--cb-text-sm);line-height:var(--cb-line-height-normal)}.cb-input-number__message--hint{color:var(--cb-color-text-muted)}.cb-input-number__message--error{color:var(--cb-color-danger)}.cb-input-number__required--required,.cb-input-number__required--optional{margin-left:.25rem;color:var(--cb-color-text-muted);font-size:.85em;font-weight:var(--cb-font-weight-normal, 400)}\n"], dependencies: [{ kind: "component", type: CbIcon, selector: "cb-icon", inputs: ["name", "size", "spin", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
329
+ `, isInline: true, styles: [":host{display:block}.cb-input-number__label{display:block;margin-bottom:var(--cb-space-1);font-family:var(--cb-font-sans);font-size:var(--cb-text-sm);font-weight:var(--cb-font-weight-medium);color:var(--cb-color-text)}.cb-input-number__required{color:var(--cb-color-danger);margin-left:2px}.cb-input-number{position:relative;display:flex;align-items:stretch;box-sizing:border-box;width:100%;background-color:var(--cb-color-bg);border:var(--cb-border-width) solid var(--cb-color-border-strong);border-radius:var(--cb-radius-md);transition:border-color var(--cb-duration-fast) var(--cb-ease),box-shadow var(--cb-duration-fast) var(--cb-ease)}.cb-input-number:hover:not(.cb-is-disabled):not(:focus-within){border-color:var(--cb-color-text-muted)}.cb-input-number:focus-within{border-color:var(--cb-color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--cb-color-primary-500) 25%,transparent)}.cb-input-number.cb-is-invalid{border-color:var(--cb-color-danger)}.cb-input-number.cb-is-invalid:focus-within{box-shadow:0 0 0 3px color-mix(in srgb,var(--cb-color-danger) 25%,transparent)}.cb-input-number.cb-is-disabled{background-color:var(--cb-color-surface);opacity:.8}.cb-input-number__field{flex:1 1 auto;min-width:0;box-sizing:border-box;font-family:var(--cb-font-sans);color:var(--cb-color-text);background:transparent;border:none;border-radius:inherit;text-align:right}.cb-input-number__field::placeholder{color:var(--cb-color-text-muted)}.cb-input-number__field:focus{outline:none}.cb-input-number__field:disabled{color:var(--cb-color-text-muted);cursor:not-allowed}.cb-input-number--sm .cb-input-number__field{min-height:2rem;padding:var(--cb-space-1) var(--cb-space-2);font-size:var(--cb-text-sm)}.cb-input-number--md .cb-input-number__field{min-height:2.5rem;padding:var(--cb-space-2) var(--cb-space-3);font-size:var(--cb-text-base)}.cb-input-number--lg .cb-input-number__field{min-height:3rem;padding:var(--cb-space-3) var(--cb-space-4);font-size:var(--cb-text-lg)}.cb-input-number__buttons{display:flex;flex:none;flex-direction:column;border-left:var(--cb-border-width) solid var(--cb-color-border)}.cb-input-number__btn{display:flex;flex:1 1 50%;align-items:center;justify-content:center;width:2rem;padding:0;color:var(--cb-color-text-muted);background-color:var(--cb-color-surface-subtle);border:none;cursor:pointer;transition:background-color var(--cb-duration-fast) var(--cb-ease)}.cb-input-number__btn:hover:not(:disabled){background-color:var(--cb-color-surface-hover);color:var(--cb-color-text)}.cb-input-number__btn:disabled{opacity:.4;cursor:not-allowed}.cb-input-number__btn--up{border-top-right-radius:var(--cb-radius-md);border-bottom:var(--cb-border-width) solid var(--cb-color-border)}.cb-input-number__btn--down{border-bottom-right-radius:var(--cb-radius-md)}.cb-input-number__btn cb-icon{color:currentColor}.cb-input-number__message{margin:var(--cb-space-1) 0 0;font-size:var(--cb-text-sm);line-height:var(--cb-line-height-normal)}.cb-input-number__message--hint{color:var(--cb-color-text-muted)}.cb-input-number__message--error{color:var(--cb-color-danger)}.cb-input-number__required--required,.cb-input-number__required--optional{margin-left:.25rem;color:var(--cb-color-text-muted);font-size:.85em;font-weight:var(--cb-font-weight-normal, 400)}\n"], dependencies: [{ kind: "component", type: CbIcon, selector: "cb-icon", inputs: ["name", "size", "spin", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
328
330
  }
329
331
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbInputNumber, decorators: [{
330
332
  type: Component,
@@ -383,7 +385,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
383
385
  type="button"
384
386
  class="cb-input-number__btn cb-input-number__btn--up"
385
387
  tabindex="-1"
386
- aria-label="Incrementar"
388
+ [attr.aria-label]="t().increment"
387
389
  [disabled]="isDisabled() || readonly() || isAtMax()"
388
390
  (click)="increment()"
389
391
  >
@@ -393,7 +395,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
393
395
  type="button"
394
396
  class="cb-input-number__btn cb-input-number__btn--down"
395
397
  tabindex="-1"
396
- aria-label="Decrementar"
398
+ [attr.aria-label]="t().decrement"
397
399
  [disabled]="isDisabled() || readonly() || isAtMin()"
398
400
  (click)="decrement()"
399
401
  >
@@ -412,7 +414,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
412
414
  {{ hint() }}
413
415
  </p>
414
416
  }
415
- `, styles: [":host{display:block}.cb-input-number__label{display:block;margin-bottom:var(--cb-space-1);font-family:var(--cb-font-sans);font-size:var(--cb-text-sm);font-weight:var(--cb-font-weight-medium);color:var(--cb-color-text)}.cb-input-number__required{color:var(--cb-color-danger);margin-left:2px}.cb-input-number{position:relative;display:flex;align-items:stretch;box-sizing:border-box;width:100%;background-color:var(--cb-color-bg);border:var(--cb-border-width) solid var(--cb-color-border-strong);border-radius:var(--cb-radius-md);transition:border-color var(--cb-duration-fast) var(--cb-ease),box-shadow var(--cb-duration-fast) var(--cb-ease)}.cb-input-number:hover:not(.cb-is-disabled):not(:focus-within){border-color:var(--cb-color-text-muted)}.cb-input-number:focus-within{border-color:var(--cb-color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--cb-color-primary-500) 25%,transparent)}.cb-input-number.cb-is-invalid{border-color:var(--cb-color-danger)}.cb-input-number.cb-is-invalid:focus-within{box-shadow:0 0 0 3px color-mix(in srgb,var(--cb-color-danger) 25%,transparent)}.cb-input-number.cb-is-disabled{background-color:var(--cb-color-surface);opacity:.8}.cb-input-number__field{flex:1 1 auto;min-width:0;box-sizing:border-box;font-family:var(--cb-font-sans);color:var(--cb-color-text);background:transparent;border:none;border-radius:inherit;text-align:right}.cb-input-number__field::placeholder{color:var(--cb-color-text-muted)}.cb-input-number__field:focus{outline:none}.cb-input-number__field:disabled{color:var(--cb-color-text-muted);cursor:not-allowed}.cb-input-number--sm .cb-input-number__field{min-height:2rem;padding:var(--cb-space-1) var(--cb-space-2);font-size:var(--cb-text-sm)}.cb-input-number--md .cb-input-number__field{min-height:2.5rem;padding:var(--cb-space-2) var(--cb-space-3);font-size:var(--cb-text-base)}.cb-input-number--lg .cb-input-number__field{min-height:3rem;padding:var(--cb-space-3) var(--cb-space-4);font-size:var(--cb-text-lg)}.cb-input-number__buttons{display:flex;flex:none;flex-direction:column;border-left:var(--cb-border-width) solid var(--cb-color-border)}.cb-input-number__btn{display:flex;flex:1 1 50%;align-items:center;justify-content:center;width:2rem;padding:0;color:var(--cb-color-text-muted);background-color:var(--cb-color-surface-50);border:none;cursor:pointer;transition:background-color var(--cb-duration-fast) var(--cb-ease)}.cb-input-number__btn:hover:not(:disabled){background-color:var(--cb-color-surface-100);color:var(--cb-color-text)}.cb-input-number__btn:disabled{opacity:.4;cursor:not-allowed}.cb-input-number__btn--up{border-top-right-radius:var(--cb-radius-md);border-bottom:var(--cb-border-width) solid var(--cb-color-border)}.cb-input-number__btn--down{border-bottom-right-radius:var(--cb-radius-md)}.cb-input-number__btn cb-icon{color:currentColor}.cb-input-number__message{margin:var(--cb-space-1) 0 0;font-size:var(--cb-text-sm);line-height:var(--cb-line-height-normal)}.cb-input-number__message--hint{color:var(--cb-color-text-muted)}.cb-input-number__message--error{color:var(--cb-color-danger)}.cb-input-number__required--required,.cb-input-number__required--optional{margin-left:.25rem;color:var(--cb-color-text-muted);font-size:.85em;font-weight:var(--cb-font-weight-normal, 400)}\n"] }]
417
+ `, styles: [":host{display:block}.cb-input-number__label{display:block;margin-bottom:var(--cb-space-1);font-family:var(--cb-font-sans);font-size:var(--cb-text-sm);font-weight:var(--cb-font-weight-medium);color:var(--cb-color-text)}.cb-input-number__required{color:var(--cb-color-danger);margin-left:2px}.cb-input-number{position:relative;display:flex;align-items:stretch;box-sizing:border-box;width:100%;background-color:var(--cb-color-bg);border:var(--cb-border-width) solid var(--cb-color-border-strong);border-radius:var(--cb-radius-md);transition:border-color var(--cb-duration-fast) var(--cb-ease),box-shadow var(--cb-duration-fast) var(--cb-ease)}.cb-input-number:hover:not(.cb-is-disabled):not(:focus-within){border-color:var(--cb-color-text-muted)}.cb-input-number:focus-within{border-color:var(--cb-color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--cb-color-primary-500) 25%,transparent)}.cb-input-number.cb-is-invalid{border-color:var(--cb-color-danger)}.cb-input-number.cb-is-invalid:focus-within{box-shadow:0 0 0 3px color-mix(in srgb,var(--cb-color-danger) 25%,transparent)}.cb-input-number.cb-is-disabled{background-color:var(--cb-color-surface);opacity:.8}.cb-input-number__field{flex:1 1 auto;min-width:0;box-sizing:border-box;font-family:var(--cb-font-sans);color:var(--cb-color-text);background:transparent;border:none;border-radius:inherit;text-align:right}.cb-input-number__field::placeholder{color:var(--cb-color-text-muted)}.cb-input-number__field:focus{outline:none}.cb-input-number__field:disabled{color:var(--cb-color-text-muted);cursor:not-allowed}.cb-input-number--sm .cb-input-number__field{min-height:2rem;padding:var(--cb-space-1) var(--cb-space-2);font-size:var(--cb-text-sm)}.cb-input-number--md .cb-input-number__field{min-height:2.5rem;padding:var(--cb-space-2) var(--cb-space-3);font-size:var(--cb-text-base)}.cb-input-number--lg .cb-input-number__field{min-height:3rem;padding:var(--cb-space-3) var(--cb-space-4);font-size:var(--cb-text-lg)}.cb-input-number__buttons{display:flex;flex:none;flex-direction:column;border-left:var(--cb-border-width) solid var(--cb-color-border)}.cb-input-number__btn{display:flex;flex:1 1 50%;align-items:center;justify-content:center;width:2rem;padding:0;color:var(--cb-color-text-muted);background-color:var(--cb-color-surface-subtle);border:none;cursor:pointer;transition:background-color var(--cb-duration-fast) var(--cb-ease)}.cb-input-number__btn:hover:not(:disabled){background-color:var(--cb-color-surface-hover);color:var(--cb-color-text)}.cb-input-number__btn:disabled{opacity:.4;cursor:not-allowed}.cb-input-number__btn--up{border-top-right-radius:var(--cb-radius-md);border-bottom:var(--cb-border-width) solid var(--cb-color-border)}.cb-input-number__btn--down{border-bottom-right-radius:var(--cb-radius-md)}.cb-input-number__btn cb-icon{color:currentColor}.cb-input-number__message{margin:var(--cb-space-1) 0 0;font-size:var(--cb-text-sm);line-height:var(--cb-line-height-normal)}.cb-input-number__message--hint{color:var(--cb-color-text-muted)}.cb-input-number__message--error{color:var(--cb-color-danger)}.cb-input-number__required--required,.cb-input-number__required--optional{margin-left:.25rem;color:var(--cb-color-text-muted);font-size:.85em;font-weight:var(--cb-font-weight-normal, 400)}\n"] }]
416
418
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], requiredIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "requiredIndicator", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], showButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showButtons", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], useGrouping: [{ type: i0.Input, args: [{ isSignal: true, alias: "useGrouping", required: false }] }], minFractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "minFractionDigits", required: false }] }], maxFractionDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFractionDigits", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", required: false }] }] } });
417
419
  function toBoolean(value) {
418
420
  return value !== false && value != null && `${value}` !== 'false';
@@ -30,14 +30,14 @@ class CbInputGroupAddon {
30
30
  this.button = input(false, { ...(ngDevMode ? { debugName: "button" } : /* istanbul ignore next */ {}), transform: toBoolean });
31
31
  }
32
32
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbInputGroupAddon, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
33
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.5", type: CbInputGroupAddon, isStandalone: true, selector: "cb-input-group-addon", inputs: { button: { classPropertyName: "button", publicName: "button", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.cb-input-group-addon--button": "button()" }, classAttribute: "cb-input-group-addon" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;gap:var(--cb-space-2);padding:0 var(--cb-space-3);white-space:nowrap;color:var(--cb-color-text-muted);background-color:var(--cb-color-surface-100);border:var(--cb-border-width) solid var(--cb-color-border-strong);font-size:var(--cb-text-sm);font-family:var(--cb-font-sans)}:host(.cb-input-group-addon--button){padding:0;background-color:transparent;border:none}:host-context([data-theme=\"dark\"]){background-color:var(--cb-color-surface-200)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
33
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.5", type: CbInputGroupAddon, isStandalone: true, selector: "cb-input-group-addon", inputs: { button: { classPropertyName: "button", publicName: "button", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.cb-input-group-addon--button": "button()" }, classAttribute: "cb-input-group-addon" }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;gap:var(--cb-space-2);padding:0 var(--cb-space-3);white-space:nowrap;color:var(--cb-color-text-muted);background-color:var(--cb-color-surface-hover);border:var(--cb-border-width) solid var(--cb-color-border-strong);font-size:var(--cb-text-sm);font-family:var(--cb-font-sans)}:host(.cb-input-group-addon--button){padding:0;background-color:transparent;border:none}:host-context([data-theme=\"dark\"]){background-color:var(--cb-color-surface-subtle)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
34
34
  }
35
35
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbInputGroupAddon, decorators: [{
36
36
  type: Component,
37
37
  args: [{ selector: 'cb-input-group-addon', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
38
38
  class: 'cb-input-group-addon',
39
39
  '[class.cb-input-group-addon--button]': 'button()',
40
- }, template: `<ng-content />`, styles: [":host{display:inline-flex;align-items:center;justify-content:center;gap:var(--cb-space-2);padding:0 var(--cb-space-3);white-space:nowrap;color:var(--cb-color-text-muted);background-color:var(--cb-color-surface-100);border:var(--cb-border-width) solid var(--cb-color-border-strong);font-size:var(--cb-text-sm);font-family:var(--cb-font-sans)}:host(.cb-input-group-addon--button){padding:0;background-color:transparent;border:none}:host-context([data-theme=\"dark\"]){background-color:var(--cb-color-surface-200)}\n"] }]
40
+ }, template: `<ng-content />`, styles: [":host{display:inline-flex;align-items:center;justify-content:center;gap:var(--cb-space-2);padding:0 var(--cb-space-3);white-space:nowrap;color:var(--cb-color-text-muted);background-color:var(--cb-color-surface-hover);border:var(--cb-border-width) solid var(--cb-color-border-strong);font-size:var(--cb-text-sm);font-family:var(--cb-font-sans)}:host(.cb-input-group-addon--button){padding:0;background-color:transparent;border:none}:host-context([data-theme=\"dark\"]){background-color:var(--cb-color-surface-subtle)}\n"] }]
41
41
  }], propDecorators: { button: [{ type: i0.Input, args: [{ isSignal: true, alias: "button", required: false }] }] } });
42
42
  function toBoolean(value) {
43
43
  return value !== false && value != null && `${value}` !== 'false';
@@ -64,17 +64,22 @@ class CbInputMask {
64
64
  onBlur() {
65
65
  this.onTouched();
66
66
  }
67
+ /**
68
+ * Aplica la máscara. Los literales (`-`, `(`, espacios…) se escriben solo
69
+ * cuando llega el carácter siguiente: así un literal inicial aparece y
70
+ * Backspace puede borrar el último literal sin que vuelva a añadirse.
71
+ */
67
72
  applyMask(raw, mask) {
68
- const cleanChars = Array.from(raw);
73
+ const chars = Array.from(raw);
69
74
  let rawIdx = 0;
70
75
  let masked = '';
71
76
  let unmasked = '';
72
- for (let mIdx = 0; mIdx < mask.length; mIdx++) {
73
- const mChar = mask[mIdx];
77
+ let pending = '';
78
+ for (const mChar of mask) {
74
79
  if (mChar === '9' || mChar === 'a' || mChar === '*') {
75
80
  let matched = '';
76
- while (rawIdx < cleanChars.length) {
77
- const candidate = cleanChars[rawIdx++];
81
+ while (rawIdx < chars.length) {
82
+ const candidate = chars[rawIdx++];
78
83
  if (this.matchesToken(candidate, mChar)) {
79
84
  matched = candidate;
80
85
  break;
@@ -82,16 +87,14 @@ class CbInputMask {
82
87
  }
83
88
  if (!matched)
84
89
  break;
85
- masked += matched;
90
+ masked += pending + matched;
86
91
  unmasked += matched;
92
+ pending = '';
87
93
  }
88
94
  else {
89
- if (rawIdx < cleanChars.length && cleanChars[rawIdx] === mChar) {
95
+ if (chars[rawIdx] === mChar)
90
96
  rawIdx++;
91
- }
92
- if (rawIdx <= cleanChars.length && unmasked.length > 0) {
93
- masked += mChar;
94
- }
97
+ pending += mChar;
95
98
  }
96
99
  }
97
100
  return { masked, unmasked };
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, ElementRef, input, booleanAttribute, model, signal, computed, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
- import { cbFieldState } from '@caribeng/ui';
4
+ import { injectCbTranslation, cbFormat, cbFieldState } from '@caribeng/ui';
5
5
 
6
6
  /**
7
7
  * InputOTP de CaribeNG: entrada de código de verificación en casillas individuales
@@ -9,6 +9,10 @@ import { cbFieldState } from '@caribeng/ui';
9
9
  */
10
10
  class CbInputOtp {
11
11
  constructor() {
12
+ /** Textos de interfaz en el idioma activo (`provideCaribeNG({ locale })`). */
13
+ this.t = injectCbTranslation();
14
+ /** Rellena `{0}`, `{1}`… de un texto traducido. */
15
+ this.fmt = cbFormat;
12
16
  this.hostRef = inject(ElementRef);
13
17
  this.length = input(6, /* @ts-ignore */
14
18
  ...(ngDevMode ? [{ debugName: "length" }] : /* istanbul ignore next */ []));
@@ -22,7 +26,7 @@ class CbInputOtp {
22
26
  this.invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
23
27
  /** Estado de validación: inputs manuales + estado de Angular Forms. */
24
28
  this.fieldState = cbFieldState({ invalid: () => this.invalid() });
25
- this.ariaLabel = input('Código de verificación', /* @ts-ignore */
29
+ this.ariaLabel = input(undefined, /* @ts-ignore */
26
30
  ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
27
31
  this.value = model('', /* @ts-ignore */
28
32
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
@@ -87,6 +91,8 @@ class CbInputOtp {
87
91
  const next = cleaned.slice(0, this.length());
88
92
  this.value.set(next);
89
93
  this.onChange(next);
94
+ if (next)
95
+ this.focusSlot(Math.min(next.length, this.length()) - 1);
90
96
  }
91
97
  onBlur() {
92
98
  this.onTouched();
@@ -96,7 +102,7 @@ class CbInputOtp {
96
102
  slots[idx]?.focus();
97
103
  }
98
104
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbInputOtp, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
99
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CbInputOtp, isStandalone: true, selector: "cb-input-otp", inputs: { length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, integerOnly: { classPropertyName: "integerOnly", publicName: "integerOnly", isSignal: true, isRequired: false, transformFunction: null }, mask: { classPropertyName: "mask", publicName: "mask", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { attributes: { "role": "group" }, properties: { "attr.aria-label": "ariaLabel() || \"C\u00F3digo de verificaci\u00F3n\"" }, classAttribute: "cb-input-otp" }, providers: [
105
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CbInputOtp, isStandalone: true, selector: "cb-input-otp", inputs: { length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, integerOnly: { classPropertyName: "integerOnly", publicName: "integerOnly", isSignal: true, isRequired: false, transformFunction: null }, mask: { classPropertyName: "mask", publicName: "mask", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { attributes: { "role": "group" }, properties: { "attr.aria-label": "(ariaLabel() ?? t().verificationCode)" }, classAttribute: "cb-input-otp" }, providers: [
100
106
  {
101
107
  provide: NG_VALUE_ACCESSOR,
102
108
  useExisting: forwardRef(() => CbInputOtp),
@@ -113,7 +119,7 @@ class CbInputOtp {
113
119
  [attr.inputmode]="integerOnly() ? 'numeric' : 'text'"
114
120
  [value]="charAt(idx)"
115
121
  [disabled]="isDisabled()"
116
- [attr.aria-label]="'Dígito ' + (idx + 1)"
122
+ [attr.aria-label]="fmt(t().digit, idx + 1)"
117
123
  (input)="onSlotInput($event, idx)"
118
124
  (keydown)="onSlotKeydown($event, idx)"
119
125
  (paste)="onPaste($event)"
@@ -133,7 +139,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
133
139
  ], host: {
134
140
  class: 'cb-input-otp',
135
141
  role: 'group',
136
- '[attr.aria-label]': 'ariaLabel() || "Código de verificación"',
142
+ '[attr.aria-label]': '(ariaLabel() ?? t().verificationCode)',
137
143
  }, template: `
138
144
  @for (idx of indices(); track idx) {
139
145
  <input
@@ -145,7 +151,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
145
151
  [attr.inputmode]="integerOnly() ? 'numeric' : 'text'"
146
152
  [value]="charAt(idx)"
147
153
  [disabled]="isDisabled()"
148
- [attr.aria-label]="'Dígito ' + (idx + 1)"
154
+ [attr.aria-label]="fmt(t().digit, idx + 1)"
149
155
  (input)="onSlotInput($event, idx)"
150
156
  (keydown)="onSlotKeydown($event, idx)"
151
157
  (paste)="onPaste($event)"