@prolibu-suite/cobalt-core 0.9.3 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/custom-elements.json +375 -25
  2. package/dist/cjs/co-audio-player.cjs.entry.js +107 -18
  3. package/dist/cjs/co-avatar_2.cjs.entry.js +7 -31
  4. package/dist/cjs/co-button.cjs.entry.js +6 -4
  5. package/dist/cjs/co-calendar-month_2.cjs.entry.js +59 -2
  6. package/dist/cjs/co-checkbox.cjs.entry.js +10 -4
  7. package/dist/cjs/co-chip_2.cjs.entry.js +388 -18
  8. package/dist/cjs/co-color-picker.cjs.entry.js +36 -3
  9. package/dist/cjs/co-combobox.cjs.entry.js +44 -4
  10. package/dist/cjs/co-event-popover.cjs.entry.js +5 -2
  11. package/dist/cjs/co-file-field.cjs.entry.js +12 -6
  12. package/dist/cjs/co-icon-button.cjs.entry.js +5 -2
  13. package/dist/cjs/co-icon.cjs.entry.js +17 -1
  14. package/dist/cjs/co-input.cjs.entry.js +21 -1
  15. package/dist/cjs/co-loader.cjs.entry.js +1 -1
  16. package/dist/cjs/co-number-field.cjs.entry.js +22 -2
  17. package/dist/cjs/co-ref-field.cjs.entry.js +99 -13
  18. package/dist/cjs/co-select.cjs.entry.js +273 -8
  19. package/dist/cjs/co-tags-field.cjs.entry.js +1 -1
  20. package/dist/cjs/cobalt.cjs.js +1 -1
  21. package/dist/cjs/color-YhUkm10t.js +32 -0
  22. package/dist/cjs/fieldChip-BLzo9MEV.js +7 -0
  23. package/dist/cjs/index-DK-2Lzmf.js +4 -4
  24. package/dist/cjs/loader.cjs.js +1 -1
  25. package/dist/cobalt/cobalt.esm.js +1 -1
  26. package/dist/cobalt/p-0c463d9a.entry.js +1 -0
  27. package/dist/cobalt/{p-3ced4269.entry.js → p-2828ecf6.entry.js} +1 -1
  28. package/dist/cobalt/p-2f88d151.entry.js +1 -0
  29. package/dist/cobalt/p-409f28bb.entry.js +1 -0
  30. package/dist/cobalt/{p-18af9e44.entry.js → p-568cfe8d.entry.js} +1 -1
  31. package/dist/cobalt/p-6bf814f9.entry.js +1 -0
  32. package/dist/cobalt/p-76420ac1.entry.js +1 -0
  33. package/dist/cobalt/p-7ea87b75.entry.js +1 -0
  34. package/dist/cobalt/p-8b4b3589.entry.js +1 -0
  35. package/dist/cobalt/p-93c68029.entry.js +1 -0
  36. package/dist/cobalt/p-BG4WRR22.js +1 -0
  37. package/dist/cobalt/p-a2d31248.entry.js +1 -0
  38. package/dist/cobalt/p-bcedbd73.entry.js +1 -0
  39. package/dist/cobalt/p-dfd25f1d.entry.js +1 -0
  40. package/dist/cobalt/p-e364b8a5.entry.js +1 -0
  41. package/dist/cobalt/p-e84eda2e.entry.js +1 -0
  42. package/dist/cobalt/p-f25967fb.entry.js +1 -0
  43. package/dist/cobalt/p-f5f1b463.entry.js +1 -0
  44. package/dist/cobalt/p-fef5db54.entry.js +1 -0
  45. package/dist/cobalt/p-mAGnZXRn.js +1 -0
  46. package/dist/collection/components/co-audio-player/co-audio-player.js +81 -17
  47. package/dist/collection/components/co-audio-player/co-audio-player.utils.js +27 -2
  48. package/dist/collection/components/co-autocomplete/co-autocomplete.js +1 -1
  49. package/dist/collection/components/co-avatar/co-avatar.js +5 -1
  50. package/dist/collection/components/co-avatar-group/co-avatar-group.js +1 -1
  51. package/dist/collection/components/co-button/co-button.css +7 -0
  52. package/dist/collection/components/co-button/co-button.js +7 -5
  53. package/dist/collection/components/co-calendar-month/co-calendar-month.js +59 -2
  54. package/dist/collection/components/co-checkbox/co-checkbox.css +22 -0
  55. package/dist/collection/components/co-checkbox/co-checkbox.js +9 -3
  56. package/dist/collection/components/co-checkbox-group/co-checkbox-group.js +1 -1
  57. package/dist/collection/components/co-color-picker/co-color-picker.css +7 -0
  58. package/dist/collection/components/co-color-picker/co-color-picker.js +35 -2
  59. package/dist/collection/components/co-combobox/co-combobox.css +7 -0
  60. package/dist/collection/components/co-combobox/co-combobox.js +44 -4
  61. package/dist/collection/components/co-command-search/co-command-search.js +1 -1
  62. package/dist/collection/components/co-data-table/co-data-table.js +1 -1
  63. package/dist/collection/components/co-date-range-picker/co-date-range-picker.js +2 -2
  64. package/dist/collection/components/co-event-popover/co-event-popover.js +5 -2
  65. package/dist/collection/components/co-file-field/co-file-field.css +2 -0
  66. package/dist/collection/components/co-file-field/co-file-field.js +8 -5
  67. package/dist/collection/components/co-icon/iconLoader.js +17 -1
  68. package/dist/collection/components/co-icon-button/co-icon-button.css +7 -0
  69. package/dist/collection/components/co-icon-button/co-icon-button.js +6 -3
  70. package/dist/collection/components/co-input/co-input.css +13 -0
  71. package/dist/collection/components/co-input/co-input.js +21 -0
  72. package/dist/collection/components/co-loader/co-loader.css +5 -3
  73. package/dist/collection/components/co-number-field/co-number-field.js +23 -2
  74. package/dist/collection/components/co-option-list/co-option-list.css +45 -2
  75. package/dist/collection/components/co-option-list/co-option-list.js +468 -18
  76. package/dist/collection/components/co-option-list/optionListLogic.js +25 -0
  77. package/dist/collection/components/co-popover/co-popover.js +1 -1
  78. package/dist/collection/components/co-radio-group/co-radio-group.js +1 -1
  79. package/dist/collection/components/co-ref-field/co-ref-field.css +49 -0
  80. package/dist/collection/components/co-ref-field/co-ref-field.js +252 -12
  81. package/dist/collection/components/co-segmented-bar/co-segmented-bar.js +1 -1
  82. package/dist/collection/components/co-select/co-select.css +19 -0
  83. package/dist/collection/components/co-select/co-select.js +275 -9
  84. package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.js +1 -1
  85. package/dist/collection/components/co-toast/co-toast.js +2 -2
  86. package/dist/collection/components/co-transfer-list/co-transfer-list.js +1 -1
  87. package/dist/collection/utils/fieldChip.js +1 -1
  88. package/dist/collection/utils/fileI18n.js +3 -0
  89. package/dist/components/co-accordion.js +1 -1
  90. package/dist/components/co-action-bar.js +1 -1
  91. package/dist/components/co-audio-player.js +1 -1
  92. package/dist/components/co-autocomplete.js +1 -1
  93. package/dist/components/co-avatar-group.js +1 -1
  94. package/dist/components/co-avatar.js +1 -1
  95. package/dist/components/co-breadcrumb-item.js +1 -1
  96. package/dist/components/co-breadcrumb.js +1 -1
  97. package/dist/components/co-button.js +1 -1
  98. package/dist/components/co-calendar-month.js +1 -1
  99. package/dist/components/co-calendar-timegrid.js +1 -1
  100. package/dist/components/co-calendar.js +1 -1
  101. package/dist/components/co-carousel.js +1 -1
  102. package/dist/components/co-checkbox-group.js +1 -1
  103. package/dist/components/co-checkbox.js +1 -1
  104. package/dist/components/co-chip.js +1 -1
  105. package/dist/components/co-color-picker.js +1 -1
  106. package/dist/components/co-column-picker.js +1 -1
  107. package/dist/components/co-combobox.js +1 -1
  108. package/dist/components/co-command-search.js +1 -1
  109. package/dist/components/co-data-table-pagination.js +1 -1
  110. package/dist/components/co-data-table.js +1 -1
  111. package/dist/components/co-date-field.js +1 -1
  112. package/dist/components/co-date-picker.js +1 -1
  113. package/dist/components/co-date-range-picker.js +1 -1
  114. package/dist/components/co-date-range.js +1 -1
  115. package/dist/components/co-date-time-picker.js +1 -1
  116. package/dist/components/co-drawer.js +1 -1
  117. package/dist/components/co-drive-card.js +1 -1
  118. package/dist/components/co-drop-zone.js +1 -1
  119. package/dist/components/co-emoji-picker.js +1 -1
  120. package/dist/components/co-empty-state.js +1 -1
  121. package/dist/components/co-event-calendar.js +1 -1
  122. package/dist/components/co-event-popover.js +1 -1
  123. package/dist/components/co-fab.js +1 -1
  124. package/dist/components/co-file-field.js +1 -1
  125. package/dist/components/co-file-type-tile.js +1 -1
  126. package/dist/components/co-helper-text.js +1 -1
  127. package/dist/components/co-icon-button.js +1 -1
  128. package/dist/components/co-icon.js +1 -1
  129. package/dist/components/co-input.js +1 -1
  130. package/dist/components/co-json-field.js +1 -1
  131. package/dist/components/co-lightbox.js +1 -1
  132. package/dist/components/co-list-footer.js +1 -1
  133. package/dist/components/co-list-item.js +1 -1
  134. package/dist/components/co-loader.js +1 -1
  135. package/dist/components/co-menu-item.js +1 -1
  136. package/dist/components/co-modal.js +1 -1
  137. package/dist/components/co-number-field.js +1 -1
  138. package/dist/components/co-option-list.js +1 -1
  139. package/dist/components/co-page-header.js +1 -1
  140. package/dist/components/co-phone-field.js +1 -1
  141. package/dist/components/co-radio-group.js +1 -1
  142. package/dist/components/co-rating.js +1 -1
  143. package/dist/components/co-ref-field.js +1 -1
  144. package/dist/components/co-rich-text-editor.js +1 -1
  145. package/dist/components/co-rich-text-toolbar.js +1 -1
  146. package/dist/components/co-select.js +1 -1
  147. package/dist/components/co-sidebar-nav.js +1 -1
  148. package/dist/components/co-slider.js +1 -1
  149. package/dist/components/co-switch.js +1 -1
  150. package/dist/components/co-tab.js +1 -1
  151. package/dist/components/co-tags-field.js +1 -1
  152. package/dist/components/co-textarea.js +1 -1
  153. package/dist/components/co-toast.js +1 -1
  154. package/dist/components/co-toggle-button.js +1 -1
  155. package/dist/components/co-transfer-list.js +1 -1
  156. package/dist/components/co-video.js +1 -1
  157. package/dist/components/{p-CklsvHeL.js → p-B0Dc-I_C.js} +1 -1
  158. package/dist/components/{p-DzoNGEDU.js → p-BH184F0X.js} +1 -1
  159. package/dist/components/{p-BGD3oQ73.js → p-BHYtxTzM.js} +1 -1
  160. package/dist/components/{p-mom5kiBa.js → p-BTQEg3UO.js} +1 -1
  161. package/dist/components/p-BZIB4JDs.js +1 -0
  162. package/dist/components/p-Bbny3WUc.js +1 -0
  163. package/dist/components/{p-D5QJpmqf.js → p-Bxk96Zgc.js} +1 -1
  164. package/dist/components/p-C1Kv3zYZ.js +1 -0
  165. package/dist/components/p-C4U2tbRp.js +1 -0
  166. package/dist/components/{p-CyMaOb1j.js → p-CA_JAK9s.js} +1 -1
  167. package/dist/components/{p-AvSaw4Ua.js → p-CR0izsJC.js} +1 -1
  168. package/dist/components/p-CuZXTvDM.js +1 -0
  169. package/dist/components/{p-_131DL6m.js → p-D4qzGifz.js} +1 -1
  170. package/dist/components/{p-BsQQ7Mki.js → p-D5EdMieb.js} +1 -1
  171. package/dist/components/p-Dabi98BI.js +1 -0
  172. package/dist/components/p-DbipMAyT.js +1 -0
  173. package/dist/components/p-DgUBcJIS.js +1 -0
  174. package/dist/components/p-Dj1EZ5qD.js +1 -0
  175. package/dist/components/{p-DkmKOF60.js → p-P8wvwhM2.js} +1 -1
  176. package/dist/components/{p-nwy6X1QT.js → p-hfGFsvaD.js} +1 -1
  177. package/dist/esm/co-audio-player.entry.js +107 -18
  178. package/dist/esm/co-avatar_2.entry.js +6 -30
  179. package/dist/esm/co-button.entry.js +6 -4
  180. package/dist/esm/co-calendar-month_2.entry.js +59 -2
  181. package/dist/esm/co-checkbox.entry.js +10 -4
  182. package/dist/esm/co-chip_2.entry.js +388 -18
  183. package/dist/esm/co-color-picker.entry.js +36 -3
  184. package/dist/esm/co-combobox.entry.js +44 -4
  185. package/dist/esm/co-event-popover.entry.js +5 -2
  186. package/dist/esm/co-file-field.entry.js +12 -6
  187. package/dist/esm/co-icon-button.entry.js +5 -2
  188. package/dist/esm/co-icon.entry.js +17 -1
  189. package/dist/esm/co-input.entry.js +21 -1
  190. package/dist/esm/co-loader.entry.js +1 -1
  191. package/dist/esm/co-number-field.entry.js +22 -2
  192. package/dist/esm/co-ref-field.entry.js +99 -13
  193. package/dist/esm/co-select.entry.js +273 -8
  194. package/dist/esm/co-tags-field.entry.js +1 -1
  195. package/dist/esm/cobalt.js +1 -1
  196. package/dist/esm/color-BG4WRR22.js +30 -0
  197. package/dist/esm/fieldChip-DsAfq1e0.js +5 -0
  198. package/dist/esm/index-CrtiywTB.js +4 -4
  199. package/dist/esm/loader.js +1 -1
  200. package/dist/types/components/co-audio-player/co-audio-player.d.ts +13 -0
  201. package/dist/types/components/co-audio-player/co-audio-player.utils.d.ts +18 -1
  202. package/dist/types/components/co-button/co-button.d.ts +3 -1
  203. package/dist/types/components/co-calendar-month/co-calendar-month.d.ts +7 -0
  204. package/dist/types/components/co-checkbox/co-checkbox.d.ts +1 -0
  205. package/dist/types/components/co-color-picker/co-color-picker.d.ts +15 -0
  206. package/dist/types/components/co-combobox/co-combobox.d.ts +17 -0
  207. package/dist/types/components/co-icon-button/co-icon-button.d.ts +3 -0
  208. package/dist/types/components/co-input/co-input.d.ts +9 -0
  209. package/dist/types/components/co-number-field/co-number-field.d.ts +9 -0
  210. package/dist/types/components/co-option-list/co-option-list.d.ts +79 -0
  211. package/dist/types/components/co-option-list/optionListLogic.d.ts +23 -1
  212. package/dist/types/components/co-ref-field/co-ref-field.d.ts +46 -0
  213. package/dist/types/components/co-select/co-select.d.ts +67 -0
  214. package/dist/types/components.d.ts +110 -4
  215. package/dist/types/utils/fieldChip.d.ts +5 -0
  216. package/dist/types/utils/fileI18n.d.ts +1 -0
  217. package/package.json +4 -4
  218. package/dist/cjs/fieldChip-xNJPEFcS.js +0 -7
  219. package/dist/cobalt/p-02ac492f.entry.js +0 -1
  220. package/dist/cobalt/p-0ccb672b.entry.js +0 -1
  221. package/dist/cobalt/p-2d81b292.entry.js +0 -1
  222. package/dist/cobalt/p-4a503187.entry.js +0 -1
  223. package/dist/cobalt/p-55566b37.entry.js +0 -1
  224. package/dist/cobalt/p-680d3db8.entry.js +0 -1
  225. package/dist/cobalt/p-7457aa89.entry.js +0 -1
  226. package/dist/cobalt/p-77719335.entry.js +0 -1
  227. package/dist/cobalt/p-8f600512.entry.js +0 -1
  228. package/dist/cobalt/p-CQAYgqA6.js +0 -1
  229. package/dist/cobalt/p-a02db338.entry.js +0 -1
  230. package/dist/cobalt/p-a51d8775.entry.js +0 -1
  231. package/dist/cobalt/p-aafb9d11.entry.js +0 -1
  232. package/dist/cobalt/p-b28dc0fe.entry.js +0 -1
  233. package/dist/cobalt/p-c6b9b9d6.entry.js +0 -1
  234. package/dist/cobalt/p-d4debd6f.entry.js +0 -1
  235. package/dist/cobalt/p-d629fb4e.entry.js +0 -1
  236. package/dist/components/p-B3TkpLNh.js +0 -1
  237. package/dist/components/p-B7hvddnu.js +0 -1
  238. package/dist/components/p-BT5tSgZa.js +0 -1
  239. package/dist/components/p-CXLX8DpD.js +0 -1
  240. package/dist/components/p-DTvb412h.js +0 -1
  241. package/dist/components/p-DvhR3H61.js +0 -1
  242. package/dist/components/p-KWTokD0C.js +0 -1
  243. package/dist/components/p-Q6caHt79.js +0 -1
  244. package/dist/components/p-WWlZiln1.js +0 -1
  245. package/dist/esm/fieldChip-BZDUy9Z-.js +0 -5
@@ -89,6 +89,13 @@
89
89
  box-shadow: 0 0 0 2px var(--co-semantic-border-focus-ring);
90
90
  }
91
91
 
92
+ /* Anillo de foco por teclado — mismo trazo que el estado abierto. */
93
+ .co-combobox__trigger:focus-visible {
94
+ outline: none;
95
+ border-color: var(--co-semantic-border-focus);
96
+ box-shadow: 0 0 0 2px var(--co-semantic-border-focus-ring);
97
+ }
98
+
92
99
  .co-combobox--disabled .co-combobox__trigger {
93
100
  background: var(--co-semantic-surface-disabled);
94
101
  border-color: transparent;
@@ -46,6 +46,24 @@ export class CoCombobox {
46
46
  if (this.disabled)
47
47
  e.stopPropagation();
48
48
  };
49
+ this.handleTriggerKeyDown = (e) => {
50
+ if (this.disabled)
51
+ return;
52
+ // Solo las teclas del PROPIO trigger togglean el dropdown. Los botones
53
+ // internos (clear, "x" de los chips) llevan tabIndex={-1} pero quedan
54
+ // focuseados al clickearlos: su Enter/Space debe activarlos de forma
55
+ // nativa, no abrir/cerrar el panel bajo ellos.
56
+ if (e.target !== this.triggerEl)
57
+ return;
58
+ if (e.key === 'Enter' || e.key === ' ') {
59
+ e.preventDefault();
60
+ this.isOpen = !this.isOpen;
61
+ }
62
+ else if (e.key === 'ArrowDown' && !this.isOpen) {
63
+ e.preventDefault();
64
+ this.isOpen = true;
65
+ }
66
+ };
49
67
  this.handlePopoverOpen = () => {
50
68
  console.log('[co-combobox] handlePopoverOpen called');
51
69
  this.isOpen = true;
@@ -175,6 +193,7 @@ export class CoCombobox {
175
193
  }
176
194
  else {
177
195
  this.coClose.emit();
196
+ this.restoreTriggerFocus();
178
197
  }
179
198
  }
180
199
  onValueChange() {
@@ -231,16 +250,26 @@ export class CoCombobox {
231
250
  this.overflowCount = hiddenCount;
232
251
  }
233
252
  }
253
+ /** Devuelve el foco al trigger al cerrar el panel (Escape, selección),
254
+ * salvo que el cierre venga de un click-outside que ya movió el foco a
255
+ * otro elemento — en ese caso no robarlo. */
256
+ restoreTriggerFocus() {
257
+ var _a;
258
+ const active = document.activeElement;
259
+ if (active === this.el || this.el.contains(active)) {
260
+ (_a = this.triggerEl) === null || _a === void 0 ? void 0 : _a.focus();
261
+ }
262
+ }
234
263
  render() {
235
- return (h("div", { key: '115947444bbca6363647eadfa82af752c5e9c59a', class: {
264
+ return (h("div", { key: '37a1a6c5d14a61e45a522024b1aecf9ef3421cb5', class: {
236
265
  'co-combobox': true,
237
266
  'co-combobox--open': this.isOpen,
238
267
  'co-combobox--disabled': this.disabled,
239
268
  [`co-combobox--${this.size}`]: true,
240
- }, part: "wrapper" }, (this.label || this.secondaryLabel) && (h("div", { key: '775183563b76c909d4d566b0f829a3a7cf7927f2', class: "co-combobox__labels" }, this.label && h("label", { key: '38441f5d492f9c0976fb20f299d82ac6129b2ef6', class: "co-combobox__label", part: "label" }, this.label, h(RequiredMark, { key: '921136617ac8082a7f54e21fd4954e2a8a25870f', required: this.required })), this.secondaryLabel && (h("span", { key: 'f93bc3b87b8d16736f2326a54cc63799612fd7b2', class: "co-combobox__secondary-label", part: "secondary-label" }, this.secondaryLabel)))), h("co-popover", { key: '295160e48bacd17ee7ec69b8f1c77da2436acbe5', open: this.isOpen, placement: "bottom-start", matchWidth: true, offset: 4, onCoOpen: this.handlePopoverOpen, onCoClose: this.handlePopoverClose }, h("div", { key: 'e0f2595637c0e2362d6b07e36302c8080b31064a', slot: "trigger", class: "co-combobox__trigger", part: "trigger", onClick: this.handleTriggerClick }, this.iconLeft && (h("co-icon", { key: '560b912264de5ebf0e05c1e67afcd85c7e890d5f', name: this.iconLeft, size: 16, class: "co-combobox__icon" })), h("div", { key: '455830491a53919efc40396c7664576e583f19ab', class: "co-combobox__input-wrapper", ref: (el) => (this.chipContainerEl = el) }, this.multiple && this.hasValue ? (this.selectedOptions.map(opt => (h("co-chip", { size: "small", "icon-mode": "both", label: opt.label }, h("co-icon", { slot: "icon-left", name: opt.icon || 'circle', size: 10 }), h("co-icon", { slot: "icon-right", name: "x-circle", size: 10, weight: "fill", onClick: (e) => { e.stopPropagation(); this.handleListRemove(opt.value); } }))))) : (h("span", { class: {
269
+ }, part: "wrapper" }, (this.label || this.secondaryLabel) && (h("div", { key: '4db14a62bbdbd01088df7279939cce69eb30f9a3', class: "co-combobox__labels" }, this.label && h("label", { key: '294744758ea6e99f1c68c3b612269aa5fb38e838', class: "co-combobox__label", part: "label" }, this.label, h(RequiredMark, { key: '17c9fd9fe7cac0abd1f6b8bee4f31a9e536758fb', required: this.required })), this.secondaryLabel && (h("span", { key: '457e35ca2dd250a7ecd5c36980ced045fb46f319', class: "co-combobox__secondary-label", part: "secondary-label" }, this.secondaryLabel)))), h("co-popover", { key: '54fdc55762dcf268d1522c345968d39f26fc768e', open: this.isOpen, placement: "bottom-start", matchWidth: true, offset: 4, onCoOpen: this.handlePopoverOpen, onCoClose: this.handlePopoverClose }, h("div", { key: '0bb104f5e51e7ea5b36d7325e178c7c7eadde05c', slot: "trigger", class: "co-combobox__trigger", part: "trigger", role: "combobox", "aria-expanded": this.isOpen ? 'true' : 'false', "aria-haspopup": "listbox", "aria-label": this.label || undefined, "aria-disabled": this.disabled ? 'true' : undefined, "aria-controls": this.isOpen ? CoCombobox.LIST_ID : undefined, tabIndex: this.disabled ? -1 : 0, ref: (el) => (this.triggerEl = el), onClick: this.handleTriggerClick, onKeyDown: this.handleTriggerKeyDown }, this.iconLeft && (h("co-icon", { key: 'ebdfa267be7257aaa2b187fc867cb5d334d91319', name: this.iconLeft, size: 16, class: "co-combobox__icon" })), h("div", { key: '77671cfffe0d593242c776316292dec69af64ed6', class: "co-combobox__input-wrapper", ref: (el) => (this.chipContainerEl = el) }, this.multiple && this.hasValue ? (this.selectedOptions.map(opt => (h("co-chip", { size: "small", "icon-mode": "both", label: opt.label }, h("co-icon", { slot: "icon-left", name: opt.icon || 'circle', size: 10 }), h("co-icon", { slot: "icon-right", name: "x-circle", size: 10, weight: "fill", onClick: (e) => { e.stopPropagation(); this.handleListRemove(opt.value); } }))))) : (h("span", { class: {
241
270
  'co-combobox__text': true,
242
271
  'co-combobox__text--placeholder': !this.hasValue,
243
- } }, this.hasValue ? this.displayText : this.placeholder))), this.multiple && this.overflowCount > 0 && (h("span", { key: 'cd033364eb722a95343b8fd1229d1bd4e86ac6eb', class: "co-combobox__overflow-badge" }, this.overflowCount)), this.clearable && this.hasValue && !this.disabled && (h("button", { key: '9734b00f8d48310ec7643ecad7c37dc67b8d10a5', class: "co-combobox__clear", type: "button", tabIndex: -1, onClick: this.handleClear, "aria-label": "Clear selection", part: "clear" }, h("co-icon", { key: 'b5b4441482bd896ca54e651dd491ea947a72a163', name: "x-circle", size: 16, weight: "fill" }))), h("co-icon", { key: '2c1e33a3a5e13d77d7c4a646be2f723021608ce1', name: this.isOpen ? 'caret-up' : 'caret-down', size: 16, class: "co-combobox__caret" })), h("div", { key: '2860fe141048ca0e6eb3fd4d0354fec49d1a9234', class: "co-combobox__dropdown", part: "dropdown" }, this.isOpen && (h("co-option-list", { key: '04a725a827b086bcd2942ca96b1e2739a459ac57', ref: (el) => (this.optionListEl = el), items: this.listItemsJson, value: this.multiple ? JSON.stringify(this.selectedValues) : (this.selectedValues[0] || ''), multiple: this.multiple, selectedAffordance: "check", removableItems: this.multiple, virtual: true, searchable: this.searchable, searchPlaceholder: this.searchPlaceholder, searchDebounce: 0, highlightMatches: true, emptyMessage: this.emptyMessage, onCoSearch: (e) => { this.searchQuery = e.detail; }, onCoChange: (e) => this.handleListChange(e.detail), onCoRemoveItem: (e) => this.handleListRemove(e.detail) }, this.showFooter && (h("co-list-footer", { key: '40f9a6ba691c5766bd5d9c0dcf8cb9c467139ba7', slot: "footer", secondaryLabel: this.footerSecondaryLabel, primaryLabel: this.footerPrimaryLabel, onCoSecondary: this.handleFooterSecondary, onCoPrimary: this.handleFooterPrimary })))))), this.helperText && (h("div", { key: 'e518fc76d1e94f2a9cf74e3ea6f934966b24f837', class: `co-combobox__helper co-combobox__helper--${this.status}`, part: "helper" }, this.statusIcon && h("co-icon", { key: '72e7890676a61ff832894bf92530a032c6c5c85d', name: this.statusIcon, size: 14, weight: "fill", class: "co-combobox__helper-icon" }), h("span", { key: 'c5bf6bf198c8380cd787214e68eb2eacadb88f44', class: "co-combobox__helper-text" }, this.helperText)))));
272
+ } }, this.hasValue ? this.displayText : this.placeholder))), this.multiple && this.overflowCount > 0 && (h("span", { key: 'c230748247efc705f21f299254c24b717d7f5af7', class: "co-combobox__overflow-badge" }, this.overflowCount)), this.clearable && this.hasValue && !this.disabled && (h("button", { key: 'b8acd2eeeb17ec672912886e7dfa67abd1026927', class: "co-combobox__clear", type: "button", tabIndex: -1, onClick: this.handleClear, "aria-label": "Clear selection", part: "clear" }, h("co-icon", { key: 'd21e7dec49db82e5514a1562b60596d51ee69094', name: "x-circle", size: 16, weight: "fill" }))), h("co-icon", { key: '51becab683f82d56d93599e701025a640822127c', name: this.isOpen ? 'caret-up' : 'caret-down', size: 16, class: "co-combobox__caret" })), h("div", { key: '8d21ea81c9c5ca9500359f7cedadf12328e4c5eb', class: "co-combobox__dropdown", part: "dropdown" }, this.isOpen && (h("co-option-list", { key: '066a18d85a356c238ff9ced3721c1d3280bce4c8', id: CoCombobox.LIST_ID, ref: (el) => (this.optionListEl = el), items: this.listItemsJson, value: this.multiple ? JSON.stringify(this.selectedValues) : (this.selectedValues[0] || ''), multiple: this.multiple, selectedAffordance: "check", removableItems: this.multiple, virtual: true, searchable: this.searchable, searchPlaceholder: this.searchPlaceholder, searchDebounce: 0, highlightMatches: true, emptyMessage: this.emptyMessage, onCoSearch: (e) => { this.searchQuery = e.detail; }, onCoChange: (e) => this.handleListChange(e.detail), onCoRemoveItem: (e) => this.handleListRemove(e.detail) }, this.showFooter && (h("co-list-footer", { key: '11d5f3fd067ac246e2068bc33a7ef938efef8829', slot: "footer", secondaryLabel: this.footerSecondaryLabel, primaryLabel: this.footerPrimaryLabel, onCoSecondary: this.handleFooterSecondary, onCoPrimary: this.handleFooterPrimary })))))), this.helperText && (h("div", { key: 'aea733779599bf85e1060062b9664821bcd1f003', class: `co-combobox__helper co-combobox__helper--${this.status}`, part: "helper" }, this.statusIcon && h("co-icon", { key: '629698daf7e0005c8849062777daf8b329fe969c', name: this.statusIcon, size: 14, weight: "fill", class: "co-combobox__helper-icon" }), h("span", { key: 'd91bd4fdadedb2eebbe4a2a3c5d033978cb8db76', class: "co-combobox__helper-text" }, this.helperText)))));
244
273
  }
245
274
  static get is() { return "co-combobox"; }
246
275
  static get encapsulation() { return "shadow"; }
@@ -502,7 +531,7 @@ export class CoCombobox {
502
531
  "references": {
503
532
  "ComboboxOption": {
504
533
  "location": "local",
505
- "path": "/Users/agox/worktrees/cobalt-release-093/packages/core/src/components/co-combobox/co-combobox.tsx",
534
+ "path": "/Users/agox/worktrees/cobalt-rel-095/packages/core/src/components/co-combobox/co-combobox.tsx",
506
535
  "id": "src/components/co-combobox/co-combobox.tsx::ComboboxOption"
507
536
  }
508
537
  }
@@ -771,3 +800,14 @@ export class CoCombobox {
771
800
  }];
772
801
  }
773
802
  }
803
+ /**
804
+ * Id del <co-option-list> del dropdown, target de `aria-controls` del
805
+ * trigger. Constante (no aleatoria): vive en el shadow root de ESTA
806
+ * instancia, donde los ids no colisionan con los de otras. Se referencia el
807
+ * HOST de la primitiva — su listbox interno queda tras su propio shadow
808
+ * boundary y no es direccionable desde acá (limitación conocida y aceptada).
809
+ *
810
+ * El trigger solo emite `aria-controls` mientras `isOpen`: la lista se monta
811
+ * on-demand, así que cerrado el IDREF quedaría colgante.
812
+ */
813
+ CoCombobox.LIST_ID = 'co-combobox-list';
@@ -246,7 +246,7 @@ export class CoCommandSearch {
246
246
  "references": {
247
247
  "CommandItem": {
248
248
  "location": "local",
249
- "path": "/Users/agox/worktrees/cobalt-release-093/packages/core/src/components/co-command-search/co-command-search.tsx",
249
+ "path": "/Users/agox/worktrees/cobalt-rel-095/packages/core/src/components/co-command-search/co-command-search.tsx",
250
250
  "id": "src/components/co-command-search/co-command-search.tsx::CommandItem"
251
251
  }
252
252
  }
@@ -450,7 +450,7 @@ export class CoDataTable {
450
450
  "references": {
451
451
  "CoDataTableColumn": {
452
452
  "location": "local",
453
- "path": "/Users/agox/worktrees/cobalt-release-093/packages/core/src/components/co-data-table/co-data-table.tsx",
453
+ "path": "/Users/agox/worktrees/cobalt-rel-095/packages/core/src/components/co-data-table/co-data-table.tsx",
454
454
  "id": "src/components/co-data-table/co-data-table.tsx::CoDataTableColumn"
455
455
  }
456
456
  }
@@ -1039,7 +1039,7 @@ export class CoDateRangePicker {
1039
1039
  "references": {
1040
1040
  "DateRangeValue": {
1041
1041
  "location": "local",
1042
- "path": "/Users/agox/worktrees/cobalt-release-093/packages/core/src/components/co-date-range-picker/co-date-range-picker.tsx",
1042
+ "path": "/Users/agox/worktrees/cobalt-rel-095/packages/core/src/components/co-date-range-picker/co-date-range-picker.tsx",
1043
1043
  "id": "src/components/co-date-range-picker/co-date-range-picker.tsx::DateRangeValue"
1044
1044
  }
1045
1045
  }
@@ -1060,7 +1060,7 @@ export class CoDateRangePicker {
1060
1060
  "references": {
1061
1061
  "DateRangeValue": {
1062
1062
  "location": "local",
1063
- "path": "/Users/agox/worktrees/cobalt-release-093/packages/core/src/components/co-date-range-picker/co-date-range-picker.tsx",
1063
+ "path": "/Users/agox/worktrees/cobalt-rel-095/packages/core/src/components/co-date-range-picker/co-date-range-picker.tsx",
1064
1064
  "id": "src/components/co-date-range-picker/co-date-range-picker.tsx::DateRangeValue"
1065
1065
  }
1066
1066
  }
@@ -91,7 +91,10 @@ export class CoEventPopover {
91
91
  // Dialog-pattern focus: focus the panel itself (tabIndex=-1). Slotted actions
92
92
  // live in light DOM and co-icon-button is shadow — querySelector here can't
93
93
  // reach them; Tab from the panel lands on the first slotted action naturally.
94
- this.panelEl.focus();
94
+ // preventScroll: an out-of-viewport panel (month view) would auto-scroll on
95
+ // focus, which the scroll-close listener below caught in the same frame —
96
+ // the popover opened and closed before paint (the "click does nothing" bug).
97
+ this.panelEl.focus({ preventScroll: true });
95
98
  window.addEventListener('resize', this.onScroll);
96
99
  window.addEventListener('scroll', this.onScroll, true);
97
100
  window.addEventListener('keydown', this.onKeydown, true);
@@ -115,7 +118,7 @@ export class CoEventPopover {
115
118
  this.coClose.emit();
116
119
  }
117
120
  render() {
118
- return (h(Host, { key: '2bf728a720fb724085b945b4128a4bad5831b870' }, h("div", { key: '81bf88204d662d59a9b4d0b2148063e8244287c3', class: "pop", popover: "manual", role: "dialog", "aria-modal": "false", "aria-label": this.popoverLabel, tabIndex: -1, ref: (el) => (this.panelEl = el) }, h("div", { key: '1dae9ef8ef905f269946cb0a842636d77af46e66', class: "pop__actions", part: "actions" }, h("slot", { key: 'ce5a5fa4ea60a6649d323953dbfa2cccd8840f7c', name: "actions" })), h("div", { key: '019f8e05e990563069e33dd1936655df664085ae', class: "pop__head" }, this.dot && h("span", { key: 'a1f11545250cbf9fb900840dfca4d6721cb98852', class: "pop__dot", style: this.color ? { background: this.color } : {} }), h("div", { key: 'e81876518297dde46ef6288538c4e471b5eab521', class: "pop__body", part: "body" }, h("slot", { key: '9818f107cee7d29278b58efd1af3109d345651b4' }))))));
121
+ return (h(Host, { key: '4a80f76492bda89a6082b4794f0c924ec929dc85' }, h("div", { key: 'e8ede438958439ae0e9f2689da9fcc88419b9837', class: "pop", popover: "manual", role: "dialog", "aria-modal": "false", "aria-label": this.popoverLabel, tabIndex: -1, ref: (el) => (this.panelEl = el) }, h("div", { key: 'f09ced9c1d8e312df3218929b267e976c64207e8', class: "pop__actions", part: "actions" }, h("slot", { key: '6cfe39bfca0783530950a4e9c482b17f2104157d', name: "actions" })), h("div", { key: '1f3938226f5767fd39d1e80c28f01f2daf023540', class: "pop__head" }, this.dot && h("span", { key: '729486152ea2ab84a72270deeef917ae89ddcdba', class: "pop__dot", style: this.color ? { background: this.color } : {} }), h("div", { key: '2b9f20c48495de4327ae9e27cf1fd305a860dc39', class: "pop__body", part: "body" }, h("slot", { key: '675ce278c7de391af91e8c9235a35aa85964726d' }))))));
119
122
  }
120
123
  static get is() { return "co-event-popover"; }
121
124
  static get encapsulation() { return "shadow"; }
@@ -317,6 +317,8 @@
317
317
  border: none;
318
318
  background: transparent;
319
319
  cursor: pointer;
320
+ /* La acción de descargar es un <a>: sin subrayado ni color de link del UA. */
321
+ text-decoration: none;
320
322
  color: var(--co-semantic-text-secondary);
321
323
  transition: color var(--co-motion-duration-fast) var(--co-motion-ease-out);
322
324
  }
@@ -362,7 +362,10 @@ export class CoFileField {
362
362
  [`co-file-field__row--${item.status}`]: true,
363
363
  'co-file-field__row--dragging': this.dragKey === key,
364
364
  'co-file-field__row--drop-target': this.overKey === key,
365
- }, part: "row", key: key, draggable: this.armedKey === key, onDragStart: (e) => this.handleRowDragStart(e, key), onDragOver: (e) => this.handleRowDragOver(e, key), onDrop: (e) => this.handleRowDrop(e, key), onDragEnd: this.handleRowDragEnd }, draggable ? (h("span", { class: "co-file-field__drag-handle", part: "drag-handle", title: s.dragToReorder, onMouseDown: () => (this.armedKey = key) }, h("co-icon", { name: "list", size: 18 }))) : (h("co-icon", { name: item.status === 'error'
365
+ }, part: "row", key: key, draggable: this.armedKey === key, onDragStart: (e) => this.handleRowDragStart(e, key), onDragOver: (e) => this.handleRowDragOver(e, key), onDrop: (e) => this.handleRowDrop(e, key), onDragEnd: this.handleRowDragEnd }, draggable ? (
366
+ // Regla del DS: control icon-only → co-tooltip, nunca `title`
367
+ // nativo (se pinta con el estilo del SO). Ver CLAUDE.md raíz.
368
+ h("co-tooltip", { content: s.dragToReorder }, h("span", { class: "co-file-field__drag-handle", part: "drag-handle", onMouseDown: () => (this.armedKey = key) }, h("co-icon", { name: "list", size: 18 })))) : (h("co-icon", { name: item.status === 'error'
366
369
  ? 'warning-circle'
367
370
  : item.status === 'uploading'
368
371
  ? 'spinner-gap'
@@ -371,14 +374,14 @@ export class CoFileField {
371
374
  'co-file-field__row-icon--spin': item.status === 'uploading',
372
375
  } })), h("div", { class: "co-file-field__row-body" }, h("span", { class: "co-file-field__row-name", title: item.name }, truncateLeft(item.name)), item.status === 'uploading' && (h("div", { class: "co-file-field__progress" }, h("div", { class: "co-file-field__progress-bar", style: typeof item.progress === 'number'
373
376
  ? { width: `${item.progress}%` }
374
- : undefined }))), item.status === 'error' && item.error && (h("span", { class: "co-file-field__row-error" }, item.error))), item.size != null && (h("span", { class: "co-file-field__row-size" }, formatBytes(item.size))), item.status === 'done' && !!item.url && (h("button", { class: {
377
+ : undefined }))), item.status === 'error' && item.error && (h("span", { class: "co-file-field__row-error" }, item.error))), item.size != null && (h("span", { class: "co-file-field__row-size" }, formatBytes(item.size))), item.status === 'done' && !!item.url && (h("co-tooltip", { content: s.downloadFile }, h("a", { class: "co-file-field__action", href: item.url, target: "_blank", rel: "noopener noreferrer", download: item.name, tabIndex: -1, "aria-label": s.downloadFile }, h("co-icon", { name: "download", size: 18 })))), item.status === 'done' && !!item.url && (h("co-tooltip", { content: this.copiedKey === key ? s.copied : s.copyUrl }, h("button", { class: {
375
378
  'co-file-field__action': true,
376
379
  'co-file-field__action--copied': this.copiedKey === key,
377
- }, type: "button", tabIndex: -1, title: this.copiedKey === key ? s.copied : s.copyUrl, "aria-label": s.copyUrl, onClick: () => this.handleCopy(item) }, h("co-icon", { name: this.copiedKey === key ? 'check' : 'copy', size: 18 }))), !this.disabled && !this.readonly && (h("button", { class: "co-file-field__action", type: "button", tabIndex: -1, title: s.removeFile, "aria-label": s.removeFile, onClick: () => this.coRemove.emit(key) }, h("co-icon", { name: "trash", size: 18 })))));
378
- })))), helper && (h("div", { key: 'fce82b34f47fbf65872fbd5dea20a87b4c99ae12', class: {
380
+ }, type: "button", tabIndex: -1, "aria-label": s.copyUrl, onClick: () => this.handleCopy(item) }, h("co-icon", { name: this.copiedKey === key ? 'check' : 'copy', size: 18 })))), !this.disabled && !this.readonly && (h("co-tooltip", { content: s.removeFile }, h("button", { class: "co-file-field__action", type: "button", tabIndex: -1, "aria-label": s.removeFile, onClick: () => this.coRemove.emit(key) }, h("co-icon", { name: "trash", size: 18 }))))));
381
+ })))), helper && (h("div", { key: 'd05514a8115362aa08a872baaf1293a55048ad79', class: {
379
382
  'co-file-field__helper': true,
380
383
  'co-file-field__helper--error': this.isInvalid,
381
- }, part: "helper" }, this.isInvalid && (h("co-icon", { key: '920361c5833f0252673779b716f872af151ae4b2', name: "warning-circle", size: 14, class: "co-file-field__helper-icon" })), h("span", { key: '6711fa168985fb206fdb79533834e4d8548da3dd', class: "co-file-field__helper-text" }, helper)))));
384
+ }, part: "helper" }, this.isInvalid && (h("co-icon", { key: '0e5f2c0feb7dff2da1d549b498ed1e7ae6051448', name: "warning-circle", size: 14, class: "co-file-field__helper-icon" })), h("span", { key: '716ea5cc929a44f1da1984952da2bb5a9ce0a791', class: "co-file-field__helper-text" }, helper)))));
382
385
  }
383
386
  static get is() { return "co-file-field"; }
384
387
  static get encapsulation() { return "shadow"; }
@@ -28,7 +28,23 @@ export function loadSvg(name, weight) {
28
28
  // priority:'low' → los iconos ceden ante JS/CSS/datos críticos del boot
29
29
  // (Fetch Priority API; ignorado sin daño donde no se soporta).
30
30
  const p = fetch(url, { priority: 'low' })
31
- .then((res) => (res.ok ? res.text() : '')) // 404 → '' (queda cacheado, no reintenta)
31
+ .then(async (res) => {
32
+ if (!res.ok)
33
+ return ''; // 404 real → '' (queda cacheado, no reintenta)
34
+ const text = await res.text();
35
+ // Un 200 puede NO ser el SVG: el fallback SPA de un dev/static server
36
+ // responde index.html COMPLETO para archivos faltantes (p.ej. durante la
37
+ // ventana de un rebuild que regenera dist/). Inyectar eso al shadow del
38
+ // icono pinta un documento entero dentro del icono (splash fullscreen,
39
+ // estilos position:fixed) y el caché lo perpetuaba. Solo aceptar SVG
40
+ // real; cualquier otra cosa se trata como fallo transitorio: no cachear,
41
+ // permitir reintento.
42
+ if (!/^\s*(<\?xml|<svg)/i.test(text)) {
43
+ iconCache.delete(key);
44
+ return '';
45
+ }
46
+ return text;
47
+ })
32
48
  .catch(() => {
33
49
  // Error de red: no envenenar el caché — permitir reintento futuro.
34
50
  iconCache.delete(key);
@@ -2,6 +2,13 @@
2
2
  display: inline-flex;
3
3
  }
4
4
 
5
+ /* Disabled must block clicks AT THE HOST: the inner button's
6
+ pointer-events:none re-targets clicks to the host element, where consumer
7
+ listeners (Vue @click) live — without this, "disabled" buttons still fire. */
8
+ :host([disabled]) {
9
+ pointer-events: none;
10
+ }
11
+
5
12
  .co-icon-button {
6
13
  display: inline-flex;
7
14
  align-items: center;
@@ -20,6 +20,9 @@ export class CoIconButton {
20
20
  */
21
21
  this.size = 'md';
22
22
  /** Disabled state */
23
+ /** Reflected so :host([disabled]) can kill pointer-events — the inner
24
+ * button's pointer-events:none re-targets clicks to the host, where
25
+ * consumers' click listeners live. */
23
26
  this.disabled = false;
24
27
  /** Accessible label */
25
28
  this.label = '';
@@ -41,7 +44,7 @@ export class CoIconButton {
41
44
  : 'var(--co-border-radius-full)',
42
45
  }
43
46
  : undefined;
44
- return (h("button", { key: '870a3f745f22073b730bf78c57712aefcd1f0ae1', class: {
47
+ return (h("button", { key: 'f562372b80c9bc181be338a2a8572ea5ba7071a8', class: {
45
48
  'co-icon-button': true,
46
49
  [`co-icon-button--${this.variant}`]: true,
47
50
  [`co-icon-button--${this.shape}`]: true,
@@ -196,11 +199,11 @@ export class CoIconButton {
196
199
  "optional": false,
197
200
  "docs": {
198
201
  "tags": [],
199
- "text": "Disabled state"
202
+ "text": "Reflected so :host([disabled]) can kill pointer-events \u2014 the inner\nbutton's pointer-events:none re-targets clicks to the host, where\nconsumers' click listeners live."
200
203
  },
201
204
  "getter": false,
202
205
  "setter": false,
203
- "reflect": false,
206
+ "reflect": true,
204
207
  "attribute": "disabled",
205
208
  "defaultValue": "false"
206
209
  },
@@ -188,6 +188,19 @@
188
188
  color: var(--co-semantic-text-muted);
189
189
  }
190
190
 
191
+ /* type=number: ocultar los spinners nativos. co-number-field es la vía canónica
192
+ para incrementar con botones; un co-input[type=number] los quiere fuera (los
193
+ pseudo-elementos del spinner no se alcanzan por ::part desde el host). */
194
+ .co-input__native[type='number']::-webkit-inner-spin-button,
195
+ .co-input__native[type='number']::-webkit-outer-spin-button {
196
+ -webkit-appearance: none;
197
+ margin: 0;
198
+ }
199
+ .co-input__native[type='number'] {
200
+ -moz-appearance: textfield;
201
+ appearance: textfield;
202
+ }
203
+
191
204
  /* ---- Icons ---- */
192
205
  .co-input__icon {
193
206
  flex-shrink: 0;
@@ -86,6 +86,21 @@ export class CoInput {
86
86
  this.coAction.emit();
87
87
  };
88
88
  }
89
+ /**
90
+ * Refleja en el <input> los cambios de `value` que vienen de AFUERA (host que
91
+ * setea la prop programáticamente: cálculos, refresh, seed diferido). El
92
+ * <input> controlado de Stencil no repinta ante esos cambios bajo el lazy
93
+ * loader; escribir `inputEl.value` a mano lo sincroniza. Guard `hasFocus`:
94
+ * mientras el usuario tipea NO lo pisamos (movería el caret). Mismo patrón que
95
+ * co-number-field.onValueChange.
96
+ */
97
+ onValueChange(next) {
98
+ if (!this.inputEl || this.hasFocus)
99
+ return;
100
+ const v = next == null ? '' : String(next);
101
+ if (this.inputEl.value !== v)
102
+ this.inputEl.value = v;
103
+ }
89
104
  /** Programmatically focus the inner input (post-hydration safe). */
90
105
  async setFocus() {
91
106
  var _a;
@@ -725,4 +740,10 @@ export class CoInput {
725
740
  };
726
741
  }
727
742
  static get elementRef() { return "el"; }
743
+ static get watchers() {
744
+ return [{
745
+ "propName": "value",
746
+ "methodName": "onValueChange"
747
+ }];
748
+ }
728
749
  }
@@ -50,9 +50,11 @@
50
50
  animation: co-loader-bounce 2s infinite cubic-bezier(0.28, 0.84, 0.42, 1);
51
51
  }
52
52
 
53
- .co-loader__ball--blue { background-color: #4285f4; }
54
- .co-loader__ball--yellow { background-color: #fdbd00; animation-delay: 0.4s; }
55
- .co-loader__ball--red { background-color: #d4145a; animation-delay: 0.8s; }
53
+ /* Brand primaries with the legacy hex as fallback: themeable per tenant and
54
+ readable on both surfaces (the old fixed hex couldn't be re-themed). */
55
+ .co-loader__ball--blue { background-color: var(--co-color-primary-azul, #4285f4); }
56
+ .co-loader__ball--yellow { background-color: var(--co-color-primary-amarillo, #fdbd00); animation-delay: 0.4s; }
57
+ .co-loader__ball--red { background-color: var(--co-color-primary-rosado, #d4145a); animation-delay: 0.8s; }
56
58
 
57
59
  .co-loader__text {
58
60
  margin: 0;
@@ -70,6 +70,21 @@ export class CoNumberField {
70
70
  }
71
71
  };
72
72
  }
73
+ /**
74
+ * Refleja en el <input> los cambios de `value` que vienen de AFUERA (host que
75
+ * setea la prop: refresh de tasas, seed al abrir un form, cálculos). El render
76
+ * de Stencil no repinta el input controlado ante esos cambios bajo el lazy
77
+ * loader (verificado en vivo 2026-08-20: prop=0.000326 y el input seguía en
78
+ * "0"). Escribir `inputEl.value` a mano lo sincroniza. Guard `focused`: mientras
79
+ * el usuario tipea, su propio input manda — no lo pisamos (movería el caret).
80
+ */
81
+ onValueChange() {
82
+ if (!this.inputEl || this.focused)
83
+ return;
84
+ const next = this.isEmpty ? '' : String(this.toDisplay(this.value));
85
+ if (this.inputEl.value !== next)
86
+ this.inputEl.value = next;
87
+ }
73
88
  /** True when there is no numeric value (cleared / empty). */
74
89
  get isEmpty() {
75
90
  return this.value === null || this.value === undefined || Number.isNaN(this.value);
@@ -124,13 +139,13 @@ export class CoNumberField {
124
139
  this.coChange.emit(clamped);
125
140
  }
126
141
  render() {
127
- return (h("div", { key: 'e21d2694b5fd0fd5b77f514d8455c71f455a894b', class: {
142
+ return (h("div", { key: '0c6bc83afe9b061ce2cb99b5ae7c1f6aed3f779a', class: {
128
143
  'co-number-field': true,
129
144
  'co-number-field--disabled': this.disabled,
130
145
  'co-number-field--focused': this.focused,
131
146
  [`co-number-field--${this.size}`]: true,
132
147
  [`co-number-field--${this.status}`]: this.status !== 'default',
133
- } }, (this.label || this.secondaryLabel) && (h("div", { key: '17efd9e4987c6ea49173cac684b0bff5a218c5c6', class: "co-number-field__labels" }, this.label && h("label", { key: '977f2f3606ccf1080028fa45bf039dc419e51501', class: "co-number-field__label" }, this.label, h(RequiredMark, { key: '79866d27266b934c2bbf0b2c9b7ff5234e3ee31c', required: this.required })), this.secondaryLabel && h("span", { key: '0f336f36b8c40655088cbe25e42c582df103b235', class: "co-number-field__secondary-label" }, this.secondaryLabel))), h("div", { key: 'a46ab7533a82a23c935e76dc44d1d6f6cf3c1cad', class: "co-number-field__row" }, h("button", { key: '8ade028bbfe79d177a95b3a72823ddf325fb39bf', class: "co-number-field__btn co-number-field__btn--minus", type: "button", tabIndex: -1, disabled: !this.canDecrement, onClick: this.handleDecrement, "aria-label": "Decrease" }, h("co-icon", { key: '85f7ecc76fab9ac8776be5669fe1dc7f494b55a2', name: "minus", size: 16 })), h("input", { key: '0e3959431a17c29a6ee42c18f893be71d6ff156f', ref: el => (this.inputEl = el), class: "co-number-field__input", type: "text", inputMode: "decimal", value: this.isEmpty ? '' : String(this.toDisplay(this.value)), placeholder: this.placeholder, disabled: this.disabled, onInput: this.handleInput, onFocus: this.handleFocus, onBlur: this.handleBlur, onKeyDown: this.handleKeyDown }), this.scaled && !this.isEmpty && (h("span", { key: 'f5d2518f8bb4ae3aefdf7ee059ad92e6fee66e9c', class: "co-number-field__affix", "aria-hidden": "true" }, "%")), this.clearable && !this.isEmpty && !this.disabled && (h("button", { key: '5ee9748d2a17601638276af4ce5cc7eb57a75ac9', class: "co-number-field__clear", type: "button", tabIndex: -1, onClick: this.handleClear, "aria-label": "Clear" }, h("co-icon", { key: '05e5ebbbb8f8403b8fca2e53d2df4e915e53af21', name: "x-circle", size: 16, weight: "fill" }))), h("button", { key: 'f1d0473bec40293d4bd4cd558516118731069b4e', class: "co-number-field__btn co-number-field__btn--plus", type: "button", tabIndex: -1, disabled: !this.canIncrement, onClick: this.handleIncrement, "aria-label": "Increase" }, h("co-icon", { key: 'b8fca118622fab53168fb5123e20029fe5864ce9', name: "plus", size: 16 }))), this.helperText && (h("div", { key: '9feea41492ad64cb440c03ad69410ad49f4130c1', class: `co-number-field__helper co-number-field__helper--${this.status}` }, this.statusIcon && h("co-icon", { key: '66217b4f1a8a44e111bc9b73abf6f8a44665bf12', name: this.statusIcon, size: 14, weight: "fill", class: "co-number-field__helper-icon" }), h("span", { key: '201c84b2cb3a055e08e3eb004e50666513828038', class: "co-number-field__helper-text" }, this.helperText)))));
148
+ } }, (this.label || this.secondaryLabel) && (h("div", { key: '203720b71c1962ec93f5aefa8dd3cbd67a0294fc', class: "co-number-field__labels" }, this.label && h("label", { key: '114cc0e2a0aa9d351911cee4d1c9c1494259ce3a', class: "co-number-field__label" }, this.label, h(RequiredMark, { key: 'bf4794dd4d5e21052c529ff7eb8e47a79ff9ddb4', required: this.required })), this.secondaryLabel && h("span", { key: '60519c76314068312514d47ef2284ccdd00b5c70', class: "co-number-field__secondary-label" }, this.secondaryLabel))), h("div", { key: 'c0584ba632adaa29f439f896cbab3f73663f2b0b', class: "co-number-field__row" }, h("button", { key: '21979d6ca5667f7f278b5c4674e6497cf1e3911d', class: "co-number-field__btn co-number-field__btn--minus", type: "button", tabIndex: -1, disabled: !this.canDecrement, onClick: this.handleDecrement, "aria-label": "Decrease" }, h("co-icon", { key: 'a1173b08171bca43b50a6ca3dc8bb637cb0c43b3', name: "minus", size: 16 })), h("input", { key: 'c5584bbabde195e8178fff12eb98b4919b21e0c8', ref: el => (this.inputEl = el), class: "co-number-field__input", type: "text", inputMode: "decimal", value: this.isEmpty ? '' : String(this.toDisplay(this.value)), placeholder: this.placeholder, disabled: this.disabled, onInput: this.handleInput, onFocus: this.handleFocus, onBlur: this.handleBlur, onKeyDown: this.handleKeyDown }), this.scaled && !this.isEmpty && (h("span", { key: '86705658b5b1ec0feb9be58afbf7966f382aaa9b', class: "co-number-field__affix", "aria-hidden": "true" }, "%")), this.clearable && !this.isEmpty && !this.disabled && (h("button", { key: '5e030b36c3c95a2416544930e2e4f69b06decf61', class: "co-number-field__clear", type: "button", tabIndex: -1, onClick: this.handleClear, "aria-label": "Clear" }, h("co-icon", { key: '5492f06d71885eb432122984160e5f93153a226f', name: "x-circle", size: 16, weight: "fill" }))), h("button", { key: '8987e2c51aef9fcd54e3394066543607edcd764b', class: "co-number-field__btn co-number-field__btn--plus", type: "button", tabIndex: -1, disabled: !this.canIncrement, onClick: this.handleIncrement, "aria-label": "Increase" }, h("co-icon", { key: '2398e8b5e94071de8ffccbd3625976ddf93878d3', name: "plus", size: 16 }))), this.helperText && (h("div", { key: '16fc9f87db0ad43c6169eebb5be7ec57abd33e98', class: `co-number-field__helper co-number-field__helper--${this.status}` }, this.statusIcon && h("co-icon", { key: '1d3006cb9ba6d6b0f30fb6d09aad6b28fdf764d8', name: this.statusIcon, size: 14, weight: "fill", class: "co-number-field__helper-icon" }), h("span", { key: '6d727671c30c45655c84319b6a269e4997c3ef6b', class: "co-number-field__helper-text" }, this.helperText)))));
134
149
  }
135
150
  static get is() { return "co-number-field"; }
136
151
  static get encapsulation() { return "shadow"; }
@@ -481,4 +496,10 @@ export class CoNumberField {
481
496
  }];
482
497
  }
483
498
  static get elementRef() { return "el"; }
499
+ static get watchers() {
500
+ return [{
501
+ "propName": "value",
502
+ "methodName": "onValueChange"
503
+ }];
504
+ }
484
505
  }
@@ -738,7 +738,10 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
738
738
 
739
739
  /* ── Options container ───────────────────────────────────── */
740
740
  .co-option-list__options {
741
- max-height: 280px;
741
+ /* Overridable por host (hereda a través del shadow boundary). Con `virtual`
742
+ el viewport renderizado sigue siendo VIRTUAL_VIEWPORT_ITEMS — no subir
743
+ este var en listas virtualizadas sin ajustar ese límite. */
744
+ max-height: var(--co-option-list-max-height, 280px);
742
745
  overflow-y: auto;
743
746
  overflow-x: hidden;
744
747
  padding: var(--co-spacing-md, 12px);
@@ -780,7 +783,9 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
780
783
  font-size: var(--co-font-size-14, 14px);
781
784
  letter-spacing: var(--co-font-letter-spacing-body, -0.03em);
782
785
  color: var(--co-semantic-text-default, #1f1c1b);
783
- transition: background var(--co-motion-duration-fast) var(--co-motion-ease-out);
786
+ transition:
787
+ background var(--co-motion-duration-fast) var(--co-motion-ease-out),
788
+ opacity var(--co-motion-duration-fast) var(--co-motion-ease-out);
784
789
  }
785
790
 
786
791
  /* Filas virtualizadas: alto FIJO 32 + margen 2 = pitch 34 exacto
@@ -865,6 +870,14 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
865
870
  line-height: 16px;
866
871
  }
867
872
 
873
+ /* Badge con tooltip: el host de co-tooltip pasa a ser el flex-item del título,
874
+ así que hereda el no-shrink y el centrado que tenía el pill. */
875
+ .co-option-list__badge-tip {
876
+ display: inline-flex;
877
+ align-items: center;
878
+ flex-shrink: 0;
879
+ }
880
+
868
881
  .co-option-list__desc {
869
882
  font-size: var(--co-font-size-12, 12px);
870
883
  color: var(--co-semantic-text-muted, #888888);
@@ -899,6 +912,26 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
899
912
  color: var(--co-semantic-text-default, #1f1c1b);
900
913
  }
901
914
 
915
+ /* ── Pin por fila (pinnable) ─────────────────────────────── */
916
+ .co-option-list__pin {
917
+ flex-shrink: 0;
918
+ display: flex;
919
+ align-items: center;
920
+ justify-content: center;
921
+ border: 0;
922
+ padding: var(--co-spacing-xxs, 2px);
923
+ background: transparent;
924
+ cursor: pointer;
925
+ border-radius: var(--co-border-radius-xxs, 4px);
926
+ color: var(--co-semantic-text-muted, #888888);
927
+ }
928
+ .co-option-list__pin:hover {
929
+ color: var(--co-semantic-text-default, #1f1c1b);
930
+ }
931
+ .co-option-list__pin--active {
932
+ color: var(--co-semantic-text-default, #1f1c1b);
933
+ }
934
+
902
935
  /* ── Reorder (drag del bloque selected-first) ────────────── */
903
936
  .co-option-list__drag-handle {
904
937
  display: inline-flex;
@@ -909,7 +942,17 @@ html[data-overlayscrollbars-viewport~=scrollbarHidden] > body::-webkit-scrollbar
909
942
  flex: 0 0 auto;
910
943
  }
911
944
  .co-option-list__drag-handle:active { cursor: grabbing; }
945
+ /* touch-action: el gesto sobre el handle es SIEMPRE drag, nunca scroll. */
946
+ .co-option-list__drag-handle { touch-action: none; }
912
947
  .co-option-list__option--dragging { opacity: 0.5; }
948
+ /* Fila lifted (drag por puntero): sigue al cursor con sombra y fondo sólido. */
949
+ .co-option-list__option--lifted {
950
+ position: relative;
951
+ z-index: 2;
952
+ background: var(--co-semantic-surface-page, #fff);
953
+ box-shadow: var(--co-shadow-lg);
954
+ cursor: grabbing;
955
+ }
913
956
  .co-option-list__option--drop-before {
914
957
  box-shadow: inset 0 2px 0 0 var(--co-semantic-border-focus);
915
958
  }