@prolibu-suite/cobalt-core 0.9.3 → 0.9.4

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 (244) 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 +11 -5
  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 +87 -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-0caa059c.entry.js +1 -0
  28. package/dist/cobalt/{p-3ced4269.entry.js → p-2828ecf6.entry.js} +1 -1
  29. package/dist/cobalt/p-2f88d151.entry.js +1 -0
  30. package/dist/cobalt/p-409f28bb.entry.js +1 -0
  31. package/dist/cobalt/{p-18af9e44.entry.js → p-568cfe8d.entry.js} +1 -1
  32. package/dist/cobalt/p-6bf814f9.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-f00be11f.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.js +8 -5
  66. package/dist/collection/components/co-icon/iconLoader.js +17 -1
  67. package/dist/collection/components/co-icon-button/co-icon-button.css +7 -0
  68. package/dist/collection/components/co-icon-button/co-icon-button.js +6 -3
  69. package/dist/collection/components/co-input/co-input.css +13 -0
  70. package/dist/collection/components/co-input/co-input.js +21 -0
  71. package/dist/collection/components/co-loader/co-loader.css +5 -3
  72. package/dist/collection/components/co-number-field/co-number-field.js +23 -2
  73. package/dist/collection/components/co-option-list/co-option-list.css +45 -2
  74. package/dist/collection/components/co-option-list/co-option-list.js +468 -18
  75. package/dist/collection/components/co-option-list/optionListLogic.js +25 -0
  76. package/dist/collection/components/co-popover/co-popover.js +1 -1
  77. package/dist/collection/components/co-radio-group/co-radio-group.js +1 -1
  78. package/dist/collection/components/co-ref-field/co-ref-field.css +49 -0
  79. package/dist/collection/components/co-ref-field/co-ref-field.js +240 -12
  80. package/dist/collection/components/co-segmented-bar/co-segmented-bar.js +1 -1
  81. package/dist/collection/components/co-select/co-select.css +19 -0
  82. package/dist/collection/components/co-select/co-select.js +275 -9
  83. package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.js +1 -1
  84. package/dist/collection/components/co-toast/co-toast.js +2 -2
  85. package/dist/collection/components/co-transfer-list/co-transfer-list.js +1 -1
  86. package/dist/collection/utils/fieldChip.js +1 -1
  87. package/dist/collection/utils/fileI18n.js +3 -0
  88. package/dist/components/co-accordion.js +1 -1
  89. package/dist/components/co-action-bar.js +1 -1
  90. package/dist/components/co-audio-player.js +1 -1
  91. package/dist/components/co-autocomplete.js +1 -1
  92. package/dist/components/co-avatar-group.js +1 -1
  93. package/dist/components/co-avatar.js +1 -1
  94. package/dist/components/co-breadcrumb-item.js +1 -1
  95. package/dist/components/co-breadcrumb.js +1 -1
  96. package/dist/components/co-button.js +1 -1
  97. package/dist/components/co-calendar-month.js +1 -1
  98. package/dist/components/co-calendar-timegrid.js +1 -1
  99. package/dist/components/co-calendar.js +1 -1
  100. package/dist/components/co-carousel.js +1 -1
  101. package/dist/components/co-checkbox-group.js +1 -1
  102. package/dist/components/co-checkbox.js +1 -1
  103. package/dist/components/co-chip.js +1 -1
  104. package/dist/components/co-color-picker.js +1 -1
  105. package/dist/components/co-column-picker.js +1 -1
  106. package/dist/components/co-combobox.js +1 -1
  107. package/dist/components/co-command-search.js +1 -1
  108. package/dist/components/co-data-table-pagination.js +1 -1
  109. package/dist/components/co-data-table.js +1 -1
  110. package/dist/components/co-date-field.js +1 -1
  111. package/dist/components/co-date-picker.js +1 -1
  112. package/dist/components/co-date-range-picker.js +1 -1
  113. package/dist/components/co-date-range.js +1 -1
  114. package/dist/components/co-date-time-picker.js +1 -1
  115. package/dist/components/co-drawer.js +1 -1
  116. package/dist/components/co-drive-card.js +1 -1
  117. package/dist/components/co-drop-zone.js +1 -1
  118. package/dist/components/co-emoji-picker.js +1 -1
  119. package/dist/components/co-empty-state.js +1 -1
  120. package/dist/components/co-event-calendar.js +1 -1
  121. package/dist/components/co-event-popover.js +1 -1
  122. package/dist/components/co-fab.js +1 -1
  123. package/dist/components/co-file-field.js +1 -1
  124. package/dist/components/co-file-type-tile.js +1 -1
  125. package/dist/components/co-helper-text.js +1 -1
  126. package/dist/components/co-icon-button.js +1 -1
  127. package/dist/components/co-icon.js +1 -1
  128. package/dist/components/co-input.js +1 -1
  129. package/dist/components/co-json-field.js +1 -1
  130. package/dist/components/co-lightbox.js +1 -1
  131. package/dist/components/co-list-footer.js +1 -1
  132. package/dist/components/co-list-item.js +1 -1
  133. package/dist/components/co-loader.js +1 -1
  134. package/dist/components/co-menu-item.js +1 -1
  135. package/dist/components/co-modal.js +1 -1
  136. package/dist/components/co-number-field.js +1 -1
  137. package/dist/components/co-option-list.js +1 -1
  138. package/dist/components/co-page-header.js +1 -1
  139. package/dist/components/co-phone-field.js +1 -1
  140. package/dist/components/co-radio-group.js +1 -1
  141. package/dist/components/co-rating.js +1 -1
  142. package/dist/components/co-ref-field.js +1 -1
  143. package/dist/components/co-rich-text-editor.js +1 -1
  144. package/dist/components/co-rich-text-toolbar.js +1 -1
  145. package/dist/components/co-select.js +1 -1
  146. package/dist/components/co-sidebar-nav.js +1 -1
  147. package/dist/components/co-slider.js +1 -1
  148. package/dist/components/co-switch.js +1 -1
  149. package/dist/components/co-tab.js +1 -1
  150. package/dist/components/co-tags-field.js +1 -1
  151. package/dist/components/co-textarea.js +1 -1
  152. package/dist/components/co-toast.js +1 -1
  153. package/dist/components/co-toggle-button.js +1 -1
  154. package/dist/components/co-transfer-list.js +1 -1
  155. package/dist/components/co-video.js +1 -1
  156. package/dist/components/{p-CklsvHeL.js → p-B0Dc-I_C.js} +1 -1
  157. package/dist/components/{p-DzoNGEDU.js → p-BH184F0X.js} +1 -1
  158. package/dist/components/{p-BGD3oQ73.js → p-BHYtxTzM.js} +1 -1
  159. package/dist/components/{p-mom5kiBa.js → p-BTQEg3UO.js} +1 -1
  160. package/dist/components/p-BZIB4JDs.js +1 -0
  161. package/dist/components/p-Bbny3WUc.js +1 -0
  162. package/dist/components/{p-D5QJpmqf.js → p-Bxk96Zgc.js} +1 -1
  163. package/dist/components/p-C1Kv3zYZ.js +1 -0
  164. package/dist/components/p-C4U2tbRp.js +1 -0
  165. package/dist/components/{p-CyMaOb1j.js → p-CA_JAK9s.js} +1 -1
  166. package/dist/components/{p-AvSaw4Ua.js → p-CR0izsJC.js} +1 -1
  167. package/dist/components/p-CuZXTvDM.js +1 -0
  168. package/dist/components/{p-_131DL6m.js → p-D4qzGifz.js} +1 -1
  169. package/dist/components/{p-BsQQ7Mki.js → p-D5EdMieb.js} +1 -1
  170. package/dist/components/p-Dabi98BI.js +1 -0
  171. package/dist/components/p-DbipMAyT.js +1 -0
  172. package/dist/components/p-DgUBcJIS.js +1 -0
  173. package/dist/components/p-Dj1EZ5qD.js +1 -0
  174. package/dist/components/{p-DkmKOF60.js → p-P8wvwhM2.js} +1 -1
  175. package/dist/components/{p-nwy6X1QT.js → p-hfGFsvaD.js} +1 -1
  176. package/dist/esm/co-audio-player.entry.js +107 -18
  177. package/dist/esm/co-avatar_2.entry.js +6 -30
  178. package/dist/esm/co-button.entry.js +6 -4
  179. package/dist/esm/co-calendar-month_2.entry.js +59 -2
  180. package/dist/esm/co-checkbox.entry.js +10 -4
  181. package/dist/esm/co-chip_2.entry.js +388 -18
  182. package/dist/esm/co-color-picker.entry.js +36 -3
  183. package/dist/esm/co-combobox.entry.js +44 -4
  184. package/dist/esm/co-event-popover.entry.js +5 -2
  185. package/dist/esm/co-file-field.entry.js +11 -5
  186. package/dist/esm/co-icon-button.entry.js +5 -2
  187. package/dist/esm/co-icon.entry.js +17 -1
  188. package/dist/esm/co-input.entry.js +21 -1
  189. package/dist/esm/co-loader.entry.js +1 -1
  190. package/dist/esm/co-number-field.entry.js +22 -2
  191. package/dist/esm/co-ref-field.entry.js +87 -13
  192. package/dist/esm/co-select.entry.js +273 -8
  193. package/dist/esm/co-tags-field.entry.js +1 -1
  194. package/dist/esm/cobalt.js +1 -1
  195. package/dist/esm/color-BG4WRR22.js +30 -0
  196. package/dist/esm/fieldChip-DsAfq1e0.js +5 -0
  197. package/dist/esm/index-CrtiywTB.js +4 -4
  198. package/dist/esm/loader.js +1 -1
  199. package/dist/types/components/co-audio-player/co-audio-player.d.ts +13 -0
  200. package/dist/types/components/co-audio-player/co-audio-player.utils.d.ts +18 -1
  201. package/dist/types/components/co-button/co-button.d.ts +3 -1
  202. package/dist/types/components/co-calendar-month/co-calendar-month.d.ts +7 -0
  203. package/dist/types/components/co-checkbox/co-checkbox.d.ts +1 -0
  204. package/dist/types/components/co-color-picker/co-color-picker.d.ts +15 -0
  205. package/dist/types/components/co-combobox/co-combobox.d.ts +17 -0
  206. package/dist/types/components/co-icon-button/co-icon-button.d.ts +3 -0
  207. package/dist/types/components/co-input/co-input.d.ts +9 -0
  208. package/dist/types/components/co-number-field/co-number-field.d.ts +9 -0
  209. package/dist/types/components/co-option-list/co-option-list.d.ts +79 -0
  210. package/dist/types/components/co-option-list/optionListLogic.d.ts +23 -1
  211. package/dist/types/components/co-ref-field/co-ref-field.d.ts +46 -0
  212. package/dist/types/components/co-select/co-select.d.ts +67 -0
  213. package/dist/types/components.d.ts +110 -4
  214. package/dist/types/utils/fieldChip.d.ts +5 -0
  215. package/dist/types/utils/fileI18n.d.ts +1 -0
  216. package/package.json +3 -3
  217. package/dist/cjs/fieldChip-xNJPEFcS.js +0 -7
  218. package/dist/cobalt/p-02ac492f.entry.js +0 -1
  219. package/dist/cobalt/p-0ccb672b.entry.js +0 -1
  220. package/dist/cobalt/p-2d81b292.entry.js +0 -1
  221. package/dist/cobalt/p-4a503187.entry.js +0 -1
  222. package/dist/cobalt/p-55566b37.entry.js +0 -1
  223. package/dist/cobalt/p-680d3db8.entry.js +0 -1
  224. package/dist/cobalt/p-7457aa89.entry.js +0 -1
  225. package/dist/cobalt/p-77719335.entry.js +0 -1
  226. package/dist/cobalt/p-8f600512.entry.js +0 -1
  227. package/dist/cobalt/p-CQAYgqA6.js +0 -1
  228. package/dist/cobalt/p-a02db338.entry.js +0 -1
  229. package/dist/cobalt/p-a51d8775.entry.js +0 -1
  230. package/dist/cobalt/p-aafb9d11.entry.js +0 -1
  231. package/dist/cobalt/p-b28dc0fe.entry.js +0 -1
  232. package/dist/cobalt/p-c6b9b9d6.entry.js +0 -1
  233. package/dist/cobalt/p-d4debd6f.entry.js +0 -1
  234. package/dist/cobalt/p-d629fb4e.entry.js +0 -1
  235. package/dist/components/p-B3TkpLNh.js +0 -1
  236. package/dist/components/p-B7hvddnu.js +0 -1
  237. package/dist/components/p-BT5tSgZa.js +0 -1
  238. package/dist/components/p-CXLX8DpD.js +0 -1
  239. package/dist/components/p-DTvb412h.js +0 -1
  240. package/dist/components/p-DvhR3H61.js +0 -1
  241. package/dist/components/p-KWTokD0C.js +0 -1
  242. package/dist/components/p-Q6caHt79.js +0 -1
  243. package/dist/components/p-WWlZiln1.js +0 -1
  244. package/dist/esm/fieldChip-BZDUy9Z-.js +0 -5
@@ -2,13 +2,38 @@
2
2
 
3
3
  var index = require('./index-DK-2Lzmf.js');
4
4
 
5
- /** Seconds → "m:ss" (floors; 0 for NaN/negative). */
5
+ /** Rendered in place of `m:ss` while a time is not known.
6
+ *
7
+ * Not an error state: `<audio>.duration` is `Infinity` for any container whose
8
+ * header carries no duration — every blob `MediaRecorder` produces, i.e. every
9
+ * freshly recorded voice note — and Chrome keeps it that way until the clip has
10
+ * been played end to end. `0:00` there would read as a zero-length recording;
11
+ * `--:--` reads as "not known yet", which is the truth. */
12
+ const UNKNOWN_TIME = '--:--';
13
+ /** Seconds → "m:ss" (floors). Anything that is not a finite, non-negative number
14
+ * (`Infinity`, `NaN`, negatives) → `UNKNOWN_TIME` — never `"Infinity:NaN"`. */
6
15
  function formatTime(seconds) {
7
- const s = Math.max(0, Math.floor(seconds || 0));
16
+ if (!Number.isFinite(seconds) || seconds < 0)
17
+ return UNKNOWN_TIME;
18
+ const s = Math.floor(seconds);
8
19
  const m = Math.floor(s / 60);
9
20
  const sec = s % 60;
10
21
  return `${m}:${sec.toString().padStart(2, '0')}`;
11
22
  }
23
+ /** Picks the duration to trust (seconds), or `NaN` when neither source knows it.
24
+ *
25
+ * `<audio>.duration` is authoritative *when it is a real number*. It is not for
26
+ * a duration-less container (see `UNKNOWN_TIME`), where it reports `Infinity`.
27
+ * The WebAudio decode the player already runs to draw the waveform does know the
28
+ * real length (`AudioBuffer.duration`), so it is the fallback. `0` from either
29
+ * source means "empty/unknown" too, so it never wins. */
30
+ function resolveDuration(fromAudio, fromDecode) {
31
+ if (Number.isFinite(fromAudio) && fromAudio > 0)
32
+ return fromAudio;
33
+ if (Number.isFinite(fromDecode) && fromDecode > 0)
34
+ return fromDecode;
35
+ return NaN;
36
+ }
12
37
  /** Downsample raw PCM to `bars` peak heights, each normalized to a 0..1 fraction. */
13
38
  function resamplePeaks(channelData, bars) {
14
39
  const len = channelData.length;
@@ -75,7 +100,10 @@ const CoAudioPlayer = class {
75
100
  this.isLoading = false;
76
101
  this.hasError = false;
77
102
  this.currentTime = 0;
78
- this.duration = 0;
103
+ /** Playback length in seconds, or `NaN` while it is not known — which is the
104
+ * normal state for a `MediaRecorder` blob until the decode lands. Everything
105
+ * that does arithmetic with it goes through `knownDuration`. */
106
+ this.duration = NaN;
79
107
  this.peaks = [];
80
108
  /** Measured wave width (px); 0 until the ResizeObserver reports it. */
81
109
  this.containerWidth = 0;
@@ -83,7 +111,13 @@ const CoAudioPlayer = class {
83
111
  this.playbackRate = 1;
84
112
  // Decoded mono PCM, kept so bars can be re-resampled on resize without re-fetching.
85
113
  this.rawChannelData = null;
86
- this.onMeta = () => { var _a; this.duration = ((_a = this.audio) === null || _a === void 0 ? void 0 : _a.duration) || 0; };
114
+ // Length reported by the WebAudio decode; NaN when nothing has decoded (yet).
115
+ // It is the only trustworthy duration for a container without a duration header.
116
+ this.decodedDuration = NaN;
117
+ // Bumped by every init(); an in-flight extractPeaks whose token no longer matches
118
+ // belongs to a superseded `src` and must not write peaks/duration.
119
+ this.loadToken = 0;
120
+ this.onMeta = () => { this.syncDuration(); };
87
121
  this.onCanPlay = () => { this.isLoading = false; };
88
122
  this.onWaiting = () => { this.isLoading = true; };
89
123
  this.onTime = () => { var _a; this.currentTime = ((_a = this.audio) === null || _a === void 0 ? void 0 : _a.currentTime) || 0; };
@@ -110,11 +144,15 @@ const CoAudioPlayer = class {
110
144
  if (this.audio)
111
145
  this.audio.playbackRate = this.playbackRate;
112
146
  };
147
+ // Scrubbing needs a real total to map the click fraction onto: with an unknown
148
+ // duration `frac * duration` is Infinity (or NaN at frac 0), and assigning that
149
+ // to `currentTime` throws. No total → no scrub.
113
150
  this.seekAt = (clientX) => {
114
- if (!this.audio || !this.waveEl || !this.duration)
151
+ const total = this.knownDuration;
152
+ if (!this.audio || !this.waveEl || !total)
115
153
  return;
116
154
  const frac = scrubFraction(clientX, this.waveEl.getBoundingClientRect());
117
- this.audio.currentTime = frac * this.duration;
155
+ this.audio.currentTime = frac * total;
118
156
  this.currentTime = this.audio.currentTime;
119
157
  };
120
158
  this.onWaveKey = (e) => {
@@ -123,17 +161,29 @@ const CoAudioPlayer = class {
123
161
  this.toggle();
124
162
  return;
125
163
  }
126
- if (!this.audio || !this.duration)
164
+ if (!this.audio)
127
165
  return;
166
+ // Relative nudges stay available even with an unknown duration (the media
167
+ // element clamps a forward seek to its own seekable end); only the upper
168
+ // clamp needs a total, and both operands stay finite either way.
169
+ const total = this.knownDuration;
170
+ const at = this.audio.currentTime;
128
171
  if (e.key === 'ArrowRight')
129
- this.audio.currentTime = Math.min(this.duration, this.audio.currentTime + 5);
172
+ this.audio.currentTime = total ? Math.min(total, at + 5) : at + 5;
130
173
  else if (e.key === 'ArrowLeft')
131
- this.audio.currentTime = Math.max(0, this.audio.currentTime - 5);
174
+ this.audio.currentTime = Math.max(0, at - 5);
132
175
  else
133
176
  return;
134
177
  this.currentTime = this.audio.currentTime;
135
178
  };
136
179
  }
180
+ /** Duration usable for arithmetic (seek target, progress %, ARIA): `0` when it
181
+ * is not known, so every caller can bail on a plain falsy check instead of
182
+ * letting `Infinity`/`NaN` reach `audio.currentTime` — that setter takes a
183
+ * restricted `double` and THROWS a TypeError on a non-finite value. */
184
+ get knownDuration() {
185
+ return Number.isFinite(this.duration) && this.duration > 0 ? this.duration : 0;
186
+ }
137
187
  /** Bar count: derived from the measured width (V1-style density) once known,
138
188
  * else the `bars` fallback. Floored at 24 so a narrow player still reads as a wave. */
139
189
  get effectiveBars() {
@@ -171,6 +221,7 @@ const CoAudioPlayer = class {
171
221
  }
172
222
  disconnectedCallback() {
173
223
  var _a;
224
+ this.loadToken++; // orphan any in-flight decode so it can't write to a dead instance
174
225
  this.teardown();
175
226
  (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
176
227
  this.resizeObserver = undefined;
@@ -185,16 +236,18 @@ const CoAudioPlayer = class {
185
236
  }
186
237
  init() {
187
238
  this.teardown();
239
+ const token = ++this.loadToken;
188
240
  this.rawChannelData = null;
241
+ this.decodedDuration = NaN;
189
242
  this.peaks = fallbackPeaks(this.effectiveBars); // draw immediately; refine with real peaks
190
243
  this.currentTime = 0;
191
- this.duration = 0;
244
+ this.duration = NaN; // unknown until `loadedmetadata` or the decode says otherwise
192
245
  this.playbackRate = 1; // a fresh source starts at 1x (new <audio> defaults to 1)
193
246
  this.hasError = false;
194
247
  if (!this.src)
195
248
  return;
196
249
  this.isLoading = true;
197
- this.extractPeaks(this.src);
250
+ this.extractPeaks(this.src, token);
198
251
  if (typeof Audio === 'undefined')
199
252
  return; // test/SSR guard
200
253
  const el = new Audio();
@@ -223,22 +276,52 @@ const CoAudioPlayer = class {
223
276
  }
224
277
  this.isPlaying = false;
225
278
  }
226
- async extractPeaks(url) {
279
+ async extractPeaks(url, token) {
280
+ let ctx;
227
281
  try {
228
282
  const Ctx = window.AudioContext || window.webkitAudioContext;
229
283
  if (!Ctx || typeof fetch === 'undefined')
230
284
  return; // keep fallback
231
- const ctx = new Ctx();
285
+ ctx = new Ctx();
232
286
  const buf = await (await fetch(url)).arrayBuffer();
233
287
  const audioBuf = await ctx.decodeAudioData(buf);
288
+ if (token !== this.loadToken)
289
+ return; // a newer src superseded this decode
234
290
  this.rawChannelData = audioBuf.getChannelData(0);
291
+ this.decodedDuration = audioBuf.duration;
235
292
  this.peaks = resamplePeaks(this.rawChannelData, this.effectiveBars);
236
- ctx.close();
237
293
  }
238
294
  catch (_a) {
295
+ if (token !== this.loadToken)
296
+ return;
297
+ // Undecodable (codec WebAudio can't handle, CORS, network): keep the
298
+ // deterministic fallback wave and let <audio> own the duration — playback,
299
+ // seek and the time readout all still work, or degrade to `--:--`.
239
300
  this.rawChannelData = null;
301
+ this.decodedDuration = NaN;
240
302
  this.peaks = fallbackPeaks(this.effectiveBars); // stays functional
241
303
  }
304
+ finally {
305
+ // Always release the context. Chrome caps concurrent AudioContexts per
306
+ // document, so leaking one per failed decode would eventually stop every
307
+ // later player on the page from decoding at all.
308
+ try {
309
+ await (ctx === null || ctx === void 0 ? void 0 : ctx.close());
310
+ }
311
+ catch ( /* already closed */_b) { /* already closed */ }
312
+ }
313
+ if (token === this.loadToken)
314
+ this.syncDuration();
315
+ }
316
+ /** Re-derive the shown duration from whichever source knows it. Called from both
317
+ * `loadedmetadata` and the end of the decode, because either can land first. */
318
+ syncDuration() {
319
+ var _a, _b;
320
+ const next = resolveDuration((_b = (_a = this.audio) === null || _a === void 0 ? void 0 : _a.duration) !== null && _b !== void 0 ? _b : NaN, this.decodedDuration);
321
+ // Object.is, not !==: Stencil's @State setter re-renders on any `oldVal !== newVal`,
322
+ // and NaN !== NaN — so a plain assignment would re-render on every no-op sync.
323
+ if (!Object.is(next, this.duration))
324
+ this.duration = next;
242
325
  }
243
326
  async download() {
244
327
  if (!this.src || typeof fetch === 'undefined')
@@ -259,14 +342,20 @@ const CoAudioPlayer = class {
259
342
  render() {
260
343
  const H = 40, UNIT = 3, W = 1.8, R = 0.6;
261
344
  const vbW = Math.max(1, this.peaks.length * UNIT);
262
- const pct = this.duration ? (this.currentTime / this.duration) * 100 : 0;
263
- const bar = (hFrac, i, played = false) => (index.h("rect", { key: 'ffe5ce97626e52c12e60b953b62d237f14acb582', x: i * UNIT, y: H / 2 - (hFrac * H) / 2, width: W, height: Math.max(hFrac * H, 2), rx: R, class: { 'co-audio-player__bar': true, 'co-audio-player__bar--played': played } }));
264
- return (index.h("div", { key: '012710aded6ca183e80d7fde087cb0fdf413249b', class: {
345
+ const total = this.knownDuration; // 0 while unknown → no progress fill, no ARIA max
346
+ const pct = total ? (this.currentTime / total) * 100 : 0;
347
+ // Undefined drops the attribute (Stencil removes null/undefined attrs). An
348
+ // `aria-valuemax="Infinity"`/`"NaN"` is invalid, and a stand-in `"0"` would sit
349
+ // below `aria-valuenow` the moment playback advances. ARIA 1.2 makes valuemax
350
+ // optional for `slider`, so leaving it off while unknown is well-formed.
351
+ const ariaMax = total ? Math.floor(total) : undefined;
352
+ const bar = (hFrac, i, played = false) => (index.h("rect", { key: '997dcefc32f5188c41afa0a7b5135c70cceeed1d', x: i * UNIT, y: H / 2 - (hFrac * H) / 2, width: W, height: Math.max(hFrac * H, 2), rx: R, class: { 'co-audio-player__bar': true, 'co-audio-player__bar--played': played } }));
353
+ return (index.h("div", { key: '8ac91ab3f8eb417df5e7cf4d1e016d6ca7eb45a3', class: {
265
354
  'co-audio-player': true,
266
355
  'co-audio-player--compact': this.compact,
267
356
  'co-audio-player--error': this.hasError,
268
357
  'co-audio-player--playing': this.isPlaying,
269
- }, part: "player" }, index.h("button", { key: '2505b88e97e73fd39aa31e3dad5e7fe0c1b94c80', type: "button", class: "co-audio-player__play", part: "play", "aria-label": this.hasError ? 'Audio no disponible' : this.isPlaying ? 'Pausar' : 'Reproducir', "aria-busy": this.isLoading ? 'true' : 'false', disabled: this.hasError || !this.src, onClick: this.toggle }, index.h("co-icon", { key: 'e0e0d2dd5f6e0578ba80a3c235e5c221a6e8fe21', name: this.hasError ? 'warning-circle' : this.isPlaying ? 'pause' : 'play', weight: "fill", size: this.compact ? 12 : 14 })), index.h("div", { key: 'd2b32119c69c64d2f68d469fe4ae056780446322', class: "co-audio-player__wave", part: "wave", role: "slider", tabindex: "0", "aria-label": "Progreso de reproducci\u00F3n", "aria-valuemin": 0, "aria-valuemax": Math.floor(this.duration), "aria-valuenow": Math.floor(this.currentTime), ref: (el) => (this.waveEl = el), onClick: (e) => this.seekAt(e.clientX), onKeyDown: this.onWaveKey }, index.h("svg", { key: 'fb9643df152d2d0b119580954f639cb3a9c2cd66', class: "co-audio-player__svg", viewBox: `0 0 ${vbW} ${H}`, preserveAspectRatio: "none", "aria-hidden": "true" }, this.peaks.map((hFrac, i) => bar(hFrac, i)), index.h("clipPath", { key: 'c2901cfe7c7e910bd53c8c92894b2d2395cde270', id: "co-ap-clip" }, index.h("rect", { key: '8129a85201e09ba6646b08ed0075798b0a0b0dfc', x: "0", y: "0", width: (pct / 100) * vbW, height: H })), index.h("g", { key: '69bc1780122d48f1a545d1c59bf7ed6536285ed2', "clip-path": "url(#co-ap-clip)" }, this.peaks.map((hFrac, i) => bar(hFrac, i, true))))), index.h("span", { key: '3747622619bd81545f85e7eb2f9c19b1aca6e7c2', class: "co-audio-player__time", part: "time" }, formatTime(this.currentTime), " / ", formatTime(this.duration)), !this.compact && (index.h("button", { key: '84341856fb2e0b6a094c673a727370b148190e30', type: "button", class: "co-audio-player__speed", part: "speed", "aria-label": `Velocidad de reproducción ${this.playbackRate}x`, onClick: this.cycleSpeed }, this.playbackRate, "x")), !this.compact && !this.noDownload && (index.h("button", { key: 'd6767d185317f20299b40c4050a806d88165682f', type: "button", class: "co-audio-player__dl", part: "download", "aria-label": "Descargar", onClick: () => this.download() }, index.h("co-icon", { key: 'a0f0a09cdf705ecf15e0156cf93011f89f41ffa5', name: "download-simple", size: 14 })))));
358
+ }, part: "player" }, index.h("button", { key: '0e5897dc64c91ee67432f17d7b0d57a27f44cd0e', type: "button", class: "co-audio-player__play", part: "play", "aria-label": this.hasError ? 'Audio no disponible' : this.isPlaying ? 'Pausar' : 'Reproducir', "aria-busy": this.isLoading ? 'true' : 'false', disabled: this.hasError || !this.src, onClick: this.toggle }, index.h("co-icon", { key: '4843751a2a3709942a49ae03ff9ba0eb08ab7d97', name: this.hasError ? 'warning-circle' : this.isPlaying ? 'pause' : 'play', weight: "fill", size: this.compact ? 12 : 14 })), index.h("div", { key: 'b7aebd0e0c5197b0dec6257bbec7c9dd8dd55d6f', class: "co-audio-player__wave", part: "wave", role: "slider", tabindex: "0", "aria-label": "Progreso de reproducci\u00F3n", "aria-valuemin": 0, "aria-valuemax": ariaMax, "aria-valuenow": Math.floor(this.currentTime), ref: (el) => (this.waveEl = el), onClick: (e) => this.seekAt(e.clientX), onKeyDown: this.onWaveKey }, index.h("svg", { key: 'a504d058a27bb33dd57733ec32db306eb0ed87e9', class: "co-audio-player__svg", viewBox: `0 0 ${vbW} ${H}`, preserveAspectRatio: "none", "aria-hidden": "true" }, this.peaks.map((hFrac, i) => bar(hFrac, i)), index.h("clipPath", { key: '9cfa69ba28801893baf62c8f66b18a31319fdebe', id: "co-ap-clip" }, index.h("rect", { key: '6e5cb34baeb2b7dddd6ef7e94f8585ef912e0315', x: "0", y: "0", width: (pct / 100) * vbW, height: H })), index.h("g", { key: '4b78a29dde762cabc85d7921aacbcd261d8fa6b5', "clip-path": "url(#co-ap-clip)" }, this.peaks.map((hFrac, i) => bar(hFrac, i, true))))), index.h("span", { key: '9067d22b0e2994e46ef49c60356292ec59f61a21', class: "co-audio-player__time", part: "time" }, formatTime(this.currentTime), " / ", formatTime(this.duration)), !this.compact && (index.h("button", { key: 'f6149a9996e6ce15230221c2f6fcec95fec5f485', type: "button", class: "co-audio-player__speed", part: "speed", "aria-label": `Velocidad de reproducción ${this.playbackRate}x`, onClick: this.cycleSpeed }, this.playbackRate, "x")), !this.compact && !this.noDownload && (index.h("button", { key: '73d291d31d92bcb0e18e230fe0ac35d3ab4077b2', type: "button", class: "co-audio-player__dl", part: "download", "aria-label": "Descargar", onClick: () => this.download() }, index.h("co-icon", { key: '9ab09f5d6b975f4f5544019f70bd2ca1ee521068', name: "download-simple", size: 14 })))));
270
359
  }
271
360
  static get watchers() { return {
272
361
  "src": [{
@@ -1,37 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var index = require('./index-DK-2Lzmf.js');
4
+ var color = require('./color-YhUkm10t.js');
4
5
  var positioning = require('./positioning-DCj_AJ2T.js');
5
6
 
6
- /**
7
- * Shared color utilities for Cobalt components.
8
- * WCAG sRGB relative luminance for contrast detection.
9
- */
10
- function parseHex(hex) {
11
- if (!hex || typeof hex !== 'string')
12
- return null;
13
- const h = hex.replace('#', '');
14
- if (h.length === 3) {
15
- return { r: parseInt(h[0] + h[0], 16), g: parseInt(h[1] + h[1], 16), b: parseInt(h[2] + h[2], 16) };
16
- }
17
- if (h.length === 6) {
18
- return { r: parseInt(h.slice(0, 2), 16), g: parseInt(h.slice(2, 4), 16), b: parseInt(h.slice(4, 6), 16) };
19
- }
20
- return null;
21
- }
22
- /** WCAG sRGB relative luminance (0–1). */
23
- function luminance(hex) {
24
- const c = parseHex(hex);
25
- if (!c)
26
- return 0;
27
- const [rs, gs, bs] = [c.r / 255, c.g / 255, c.b / 255].map((v) => v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4));
28
- return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
29
- }
30
- /** Returns true when the color is perceptually light (needs dark foreground). */
31
- function isLightColor(hex) {
32
- return luminance(hex) > 0.4;
33
- }
34
-
35
7
  const coAvatarCss = () => `:host{display:inline-flex;--co-avatar-squircle:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'><path d='M100 50L99.94 68.06L99.75 73.81L99.44 77.94L99.01 81.26L98.44 84.05L97.74 86.46L96.91 88.57L95.94 90.43L94.81 92.07L93.53 93.53L92.07 94.81L90.43 95.94L88.57 96.91L86.46 97.74L84.05 98.44L81.26 99.01L77.94 99.44L73.81 99.75L68.06 99.94L50 100L31.94 99.94L26.19 99.75L22.06 99.44L18.74 99.01L15.95 98.44L13.54 97.74L11.43 96.91L9.57 95.94L7.93 94.81L6.47 93.53L5.19 92.07L4.06 90.43L3.09 88.57L2.26 86.46L1.56 84.05L0.99 81.26L0.56 77.94L0.25 73.81L0.06 68.06L0 50L0.06 31.94L0.25 26.19L0.56 22.06L0.99 18.74L1.56 15.95L2.26 13.54L3.09 11.43L4.06 9.57L5.19 7.93L6.47 6.47L7.93 5.19L9.57 4.06L11.43 3.09L13.54 2.26L15.95 1.56L18.74 0.99L22.06 0.56L26.19 0.25L31.94 0.06L50 0L68.06 0.06L73.81 0.25L77.94 0.56L81.26 0.99L84.05 1.56L86.46 2.26L88.57 3.09L90.43 4.06L92.07 5.19L93.53 6.47L94.81 7.93L95.94 9.57L96.91 11.43L97.74 13.54L98.44 15.95L99.01 18.74L99.44 22.06L99.75 26.19L99.94 31.94Z' fill='%23fff'/></svg>")}.co-avatar{position:relative;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--co-border-radius-full);background:var(--co-semantic-surface-primary);color:var(--co-semantic-on-primary);font-family:var(--co-font-family-primary);font-weight:600;line-height:1;letter-spacing:var(--co-font-letter-spacing-body);overflow:hidden;flex-shrink:0;user-select:none;-webkit-font-smoothing:antialiased}.co-avatar::after{content:'';position:absolute;inset:0;pointer-events:none;border-radius:inherit;box-shadow:inset 0 0 0 var(--co-avatar-border-width, 1px) var(--co-avatar-border-color, transparent)}.co-avatar__text{text-transform:uppercase}.co-avatar__img{width:100%;height:100%;object-fit:cover;display:block}.co-avatar--square{border-radius:0;-webkit-mask:var(--co-avatar-squircle) center / 100% 100% no-repeat;mask:var(--co-avatar-squircle) center / 100% 100% no-repeat}.co-avatar--square::after{--co-avatar-bw:var(--co-avatar-border-width, 1px);box-shadow:none;background:var(--co-avatar-border-color, transparent);-webkit-mask:var(--co-avatar-squircle) center / 100% 100% no-repeat, var(--co-avatar-squircle) center / calc(100% - 2 * var(--co-avatar-bw)) calc(100% - 2 * var(--co-avatar-bw)) no-repeat;-webkit-mask-composite:xor;mask:var(--co-avatar-squircle) center / 100% 100% no-repeat, var(--co-avatar-squircle) center / calc(100% - 2 * var(--co-avatar-bw)) calc(100% - 2 * var(--co-avatar-bw)) no-repeat;mask-composite:exclude}.co-avatar--light{color:rgba(0, 0, 0, 0.87)}co-tooltip{display:inline-flex;align-items:center;line-height:0}`;
36
8
 
37
9
  const SIZE_MAP = {
@@ -72,6 +44,10 @@ const CoAvatar = class {
72
44
  const iconSize = (_b = ICON_SIZE_MAP[this.size]) !== null && _b !== void 0 ? _b : 24;
73
45
  const fontSize = (_c = FONT_SIZE_MAP[this.size]) !== null && _c !== void 0 ? _c : 'var(--co-font-size-18)';
74
46
  const showImage = this.type === 'image' && this.src && !this.imgFailed;
47
+ // Broken/missing image without initials falls back to the ICON (default
48
+ // "user") — never an empty disc. With `text` present, initials win (they
49
+ // identify the record better than a generic glyph).
50
+ const showIcon = this.type === 'icon' || (this.type === 'image' && !showImage && !this.text);
75
51
  const ariaLabel = this.type === 'text'
76
52
  ? this.text
77
53
  : this.type === 'image'
@@ -82,10 +58,10 @@ const CoAvatar = class {
82
58
  [`co-avatar--${this.size}`]: true,
83
59
  [`co-avatar--${this.type}`]: true,
84
60
  'co-avatar--square': this.shape === 'square',
85
- 'co-avatar--light': !!this.color && isLightColor(this.color),
61
+ 'co-avatar--light': !!this.color && color.isLightColor(this.color),
86
62
  }, style: Object.assign(Object.assign({ width: `var(--co-avatar-size, ${dim}px)`, height: `var(--co-avatar-size, ${dim}px)`, fontSize }, (this.color ? { background: this.color } : {})), (this.ringColor
87
63
  ? { '--co-avatar-border-color': this.ringColor, '--co-avatar-border-width': '2px' }
88
- : {})), part: "avatar", role: "img", "aria-label": ariaLabel }, showImage ? (index.h("img", { class: "co-avatar__img", src: this.src, alt: (_g = (_f = this.alt) !== null && _f !== void 0 ? _f : this.text) !== null && _g !== void 0 ? _g : '', onError: this.handleImgError })) : this.type === 'icon' ? (index.h("co-icon", { name: this.icon, weight: this.iconWeight, size: iconSize })) : (index.h("span", { class: "co-avatar__text" }, this.text))));
64
+ : {})), part: "avatar", role: "img", "aria-label": ariaLabel }, showImage ? (index.h("img", { class: "co-avatar__img", src: this.src, alt: (_g = (_f = this.alt) !== null && _f !== void 0 ? _f : this.text) !== null && _g !== void 0 ? _g : '', onError: this.handleImgError })) : showIcon ? (index.h("co-icon", { name: this.icon, weight: this.iconWeight, size: iconSize })) : (index.h("span", { class: "co-avatar__text" }, this.text))));
89
65
  // No tooltip when `name` is unset/empty — renders exactly as before, no wrapper.
90
66
  if (!this.name)
91
67
  return disc;
@@ -2,7 +2,7 @@
2
2
 
3
3
  var index = require('./index-DK-2Lzmf.js');
4
4
 
5
- const coButtonCss = () => `:host{display:inline-flex}.co-button{display:inline-flex;align-items:center;justify-content:center;cursor:pointer;border:1px solid transparent;outline:none;font-family:var(--co-font-family-primary);font-weight:400;line-height:1;letter-spacing:var(--co-font-letter-spacing-body);white-space:nowrap;-webkit-font-smoothing:antialiased;transition:opacity var(--co-motion-duration-fast) var(--co-motion-ease-out), background var(--co-motion-duration-fast) var(--co-motion-ease-out), transform var(--co-motion-duration-fast) var(--co-motion-ease-out);box-sizing:border-box;-webkit-backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate));backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate))}.co-button--primary{background:var(--co-semantic-surface-primary);color:var(--co-semantic-on-primary);border-color:color-mix(in srgb, var(--co-semantic-on-primary) 28%, transparent)}.co-button--secondary{background:color-mix(in srgb, var(--co-semantic-surface-secondary) 55%, transparent);color:var(--co-semantic-on-secondary);border-color:var(--co-semantic-border-subtle)}.co-button--stroke{background:color-mix(in srgb, var(--co-semantic-surface-secondary) 25%, transparent);color:var(--co-semantic-text-default);border-color:var(--co-semantic-border-default)}.co-button--ghost{background:transparent;color:var(--co-semantic-text-default);border-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.co-button--danger{background:var(--co-semantic-status-error);color:var(--co-color-base-blanco);border-color:transparent}.co-button--success{background:var(--co-semantic-status-success);color:var(--co-color-base-blanco);border-color:transparent}.co-button--rounded.co-button--l{padding:var(--co-spacing-xl) var(--co-spacing-2xl);gap:var(--co-spacing-md);font-size:var(--co-font-size-18);border-radius:var(--co-button-radius, var(--co-border-radius-full))}.co-button--rounded.co-button--m{padding:var(--co-spacing-lg) var(--co-spacing-xl);gap:var(--co-spacing-md);font-size:var(--co-font-size-16);border-radius:var(--co-button-radius, var(--co-border-radius-full))}.co-button--rounded.co-button--s{padding:var(--co-spacing-md) var(--co-spacing-lg);gap:var(--co-spacing-sm2);font-size:var(--co-font-size-14);border-radius:var(--co-button-radius, var(--co-border-radius-full))}.co-button--rounded.co-button--xs{padding:var(--co-spacing-md) var(--co-spacing-lg);gap:var(--co-spacing-sm2);font-size:var(--co-font-size-12);border-radius:var(--co-button-radius, var(--co-border-radius-full))}.co-button--square.co-button--l{padding:var(--co-spacing-lg) var(--co-spacing-xl);gap:var(--co-spacing-md);font-size:var(--co-font-size-18);border-radius:var(--co-border-radius-lg)}.co-button--square.co-button--m{padding:var(--co-spacing-md) var(--co-spacing-lg);gap:var(--co-spacing-sm2);font-size:var(--co-font-size-16);border-radius:var(--co-border-radius-sm)}.co-button--square.co-button--s{padding:var(--co-spacing-sm2) var(--co-spacing-md);gap:var(--co-spacing-sm);font-size:var(--co-font-size-14);border-radius:var(--co-border-radius-xs)}.co-button--square.co-button--xs{padding:var(--co-spacing-sm) var(--co-spacing-sm2);gap:var(--co-spacing-xs);font-size:var(--co-font-size-12);border-radius:var(--co-spacing-sm)}.co-button--disabled,.co-button:disabled{opacity:0.4;cursor:not-allowed;pointer-events:none}.co-button--primary:hover:not(:disabled){opacity:0.88}.co-button--secondary:hover:not(:disabled),.co-button--stroke:hover:not(:disabled){background:var(--co-semantic-surface-hover)}.co-button--ghost:hover:not(:disabled){background:color-mix(in srgb, var(--co-semantic-surface-hover) 60%, transparent);-webkit-backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate));backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate))}.co-button--danger:hover:not(:disabled),.co-button--success:hover:not(:disabled){opacity:0.88}.co-button:active:not(:disabled){transform:scale(0.97);transition-duration:var(--co-motion-duration-instant)}.co-button--primary{transition:opacity var(--co-motion-duration-fast) var(--co-motion-ease-out), background var(--co-motion-duration-fast) var(--co-motion-ease-out), transform var(--co-motion-duration-slow) var(--co-motion-ease-spring)}.co-button--secondary.co-button--elevated{box-shadow:var(--co-shadow-sm, 0 1px 2px 0 rgba(26, 26, 26, 0.04)), inset 0 0 0 1px var(--co-color-opacity-negro-8)}.co-button--ghost.co-button--surface-dark,.co-button--stroke.co-button--surface-dark{color:var(--co-color-base-blanco, #fff)}.co-button--ghost.co-button--surface-dark:hover:not(:disabled),.co-button--stroke.co-button--surface-dark:hover:not(:disabled){background:var(--co-color-opacity-blanco-16);-webkit-backdrop-filter:none;backdrop-filter:none}.co-button--danger.co-button--surface-dark:hover:not(:disabled){opacity:1;background:color-mix(in srgb, var(--co-semantic-status-error) 84%, var(--co-color-base-blanco, #fff))}.co-button--danger.co-button--surface-dark:focus-visible{box-shadow:0 0 0 2px color-mix(in srgb, var(--co-color-base-blanco, #fff) 45%, transparent)}::slotted([slot="icon-left"]),::slotted([slot="icon-right"]){display:inline-flex;flex-shrink:0}@supports not (background: color-mix(in srgb, red, transparent)){.co-button--primary{background:var(--co-semantic-surface-primary)}.co-button--secondary{background:var(--co-semantic-surface-secondary)}.co-button--stroke{background:transparent}}`;
5
+ const coButtonCss = () => `:host{display:inline-flex}:host([disabled]){pointer-events:none}.co-button{display:inline-flex;align-items:center;justify-content:center;cursor:pointer;border:1px solid transparent;outline:none;font-family:var(--co-font-family-primary);font-weight:400;line-height:1;letter-spacing:var(--co-font-letter-spacing-body);white-space:nowrap;-webkit-font-smoothing:antialiased;transition:opacity var(--co-motion-duration-fast) var(--co-motion-ease-out), background var(--co-motion-duration-fast) var(--co-motion-ease-out), transform var(--co-motion-duration-fast) var(--co-motion-ease-out);box-sizing:border-box;-webkit-backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate));backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate))}.co-button--primary{background:var(--co-semantic-surface-primary);color:var(--co-semantic-on-primary);border-color:color-mix(in srgb, var(--co-semantic-on-primary) 28%, transparent)}.co-button--secondary{background:color-mix(in srgb, var(--co-semantic-surface-secondary) 55%, transparent);color:var(--co-semantic-on-secondary);border-color:var(--co-semantic-border-subtle)}.co-button--stroke{background:color-mix(in srgb, var(--co-semantic-surface-secondary) 25%, transparent);color:var(--co-semantic-text-default);border-color:var(--co-semantic-border-default)}.co-button--ghost{background:transparent;color:var(--co-semantic-text-default);border-color:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}.co-button--danger{background:var(--co-semantic-status-error);color:var(--co-color-base-blanco);border-color:transparent}.co-button--success{background:var(--co-semantic-status-success);color:var(--co-color-base-blanco);border-color:transparent}.co-button--rounded.co-button--l{padding:var(--co-spacing-xl) var(--co-spacing-2xl);gap:var(--co-spacing-md);font-size:var(--co-font-size-18);border-radius:var(--co-button-radius, var(--co-border-radius-full))}.co-button--rounded.co-button--m{padding:var(--co-spacing-lg) var(--co-spacing-xl);gap:var(--co-spacing-md);font-size:var(--co-font-size-16);border-radius:var(--co-button-radius, var(--co-border-radius-full))}.co-button--rounded.co-button--s{padding:var(--co-spacing-md) var(--co-spacing-lg);gap:var(--co-spacing-sm2);font-size:var(--co-font-size-14);border-radius:var(--co-button-radius, var(--co-border-radius-full))}.co-button--rounded.co-button--xs{padding:var(--co-spacing-md) var(--co-spacing-lg);gap:var(--co-spacing-sm2);font-size:var(--co-font-size-12);border-radius:var(--co-button-radius, var(--co-border-radius-full))}.co-button--square.co-button--l{padding:var(--co-spacing-lg) var(--co-spacing-xl);gap:var(--co-spacing-md);font-size:var(--co-font-size-18);border-radius:var(--co-border-radius-lg)}.co-button--square.co-button--m{padding:var(--co-spacing-md) var(--co-spacing-lg);gap:var(--co-spacing-sm2);font-size:var(--co-font-size-16);border-radius:var(--co-border-radius-sm)}.co-button--square.co-button--s{padding:var(--co-spacing-sm2) var(--co-spacing-md);gap:var(--co-spacing-sm);font-size:var(--co-font-size-14);border-radius:var(--co-border-radius-xs)}.co-button--square.co-button--xs{padding:var(--co-spacing-sm) var(--co-spacing-sm2);gap:var(--co-spacing-xs);font-size:var(--co-font-size-12);border-radius:var(--co-spacing-sm)}.co-button--disabled,.co-button:disabled{opacity:0.4;cursor:not-allowed;pointer-events:none}.co-button--primary:hover:not(:disabled){opacity:0.88}.co-button--secondary:hover:not(:disabled),.co-button--stroke:hover:not(:disabled){background:var(--co-semantic-surface-hover)}.co-button--ghost:hover:not(:disabled){background:color-mix(in srgb, var(--co-semantic-surface-hover) 60%, transparent);-webkit-backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate));backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate))}.co-button--danger:hover:not(:disabled),.co-button--success:hover:not(:disabled){opacity:0.88}.co-button:active:not(:disabled){transform:scale(0.97);transition-duration:var(--co-motion-duration-instant)}.co-button--primary{transition:opacity var(--co-motion-duration-fast) var(--co-motion-ease-out), background var(--co-motion-duration-fast) var(--co-motion-ease-out), transform var(--co-motion-duration-slow) var(--co-motion-ease-spring)}.co-button--secondary.co-button--elevated{box-shadow:var(--co-shadow-sm, 0 1px 2px 0 rgba(26, 26, 26, 0.04)), inset 0 0 0 1px var(--co-color-opacity-negro-8)}.co-button--ghost.co-button--surface-dark,.co-button--stroke.co-button--surface-dark{color:var(--co-color-base-blanco, #fff)}.co-button--ghost.co-button--surface-dark:hover:not(:disabled),.co-button--stroke.co-button--surface-dark:hover:not(:disabled){background:var(--co-color-opacity-blanco-16);-webkit-backdrop-filter:none;backdrop-filter:none}.co-button--danger.co-button--surface-dark:hover:not(:disabled){opacity:1;background:color-mix(in srgb, var(--co-semantic-status-error) 84%, var(--co-color-base-blanco, #fff))}.co-button--danger.co-button--surface-dark:focus-visible{box-shadow:0 0 0 2px color-mix(in srgb, var(--co-color-base-blanco, #fff) 45%, transparent)}::slotted([slot="icon-left"]),::slotted([slot="icon-right"]){display:inline-flex;flex-shrink:0}@supports not (background: color-mix(in srgb, red, transparent)){.co-button--primary{background:var(--co-semantic-surface-primary)}.co-button--secondary{background:var(--co-semantic-surface-secondary)}.co-button--stroke{background:transparent}}`;
6
6
 
7
7
  const ICON_SIZE = { l: 20, m: 18, s: 16, xs: 14 };
8
8
  const CoButton = class {
@@ -25,7 +25,9 @@ const CoButton = class {
25
25
  * `variant="danger" surface="dark"`.
26
26
  */
27
27
  this.surface = 'light';
28
- /** Disabled state */
28
+ /** Disabled state. Reflected so :host([disabled]) can kill pointer-events —
29
+ * the inner button's own pointer-events:none re-targets clicks to the host,
30
+ * where consumers' click listeners live. */
29
31
  this.disabled = false;
30
32
  /** Icon weight applied to both iconLeft and iconRight */
31
33
  this.iconWeight = 'regular';
@@ -56,7 +58,7 @@ const CoButton = class {
56
58
  customStyle.background = this.color;
57
59
  if (this.textColor)
58
60
  customStyle.color = this.textColor;
59
- return (index.h("button", { key: 'e765a1fcb3b4efcc7c43e155015b3c178a536d3c', class: {
61
+ return (index.h("button", { key: '651f8d079c09cf21d076aa20564a462a15ca8c4a', class: {
60
62
  'co-button': true,
61
63
  [`co-button--${this.variant}`]: true,
62
64
  [`co-button--${this.shape}`]: true,
@@ -66,7 +68,7 @@ const CoButton = class {
66
68
  'co-button--disabled': this.disabled,
67
69
  }, style: Object.keys(customStyle).length ? customStyle : undefined, type: this.type, disabled: this.disabled, "aria-label": this.ariaLabelText || undefined, onClick: this.handleClick, part: "button" }, this.iconLeft
68
70
  ? index.h("co-icon", { name: this.iconLeft, weight: this.iconWeight, size: iconSize })
69
- : null, index.h("slot", { key: '8dd3e816276a67ba6072eeed1ad34a982b60389e' }, this.label), this.iconRight
71
+ : null, index.h("slot", { key: 'b8c5b230a473fe4a57aa087533186e410db64bed' }, this.label), this.iconRight
70
72
  ? index.h("co-icon", { name: this.iconRight, weight: this.iconWeight, size: iconSize })
71
73
  : null));
72
74
  }
@@ -367,6 +367,11 @@ function readableTextToken(host, bg) {
367
367
 
368
368
  const coCalendarMonthCss = () => `:host{display:block;font-family:var(--co-font-family-primary);--co-cal-daynum-h:24px;--co-cal-lane-h:22px;--co-cal-min-week-h:92px;--co-cal-gap:2px;--co-cal-surface:var(--co-semantic-surface-page);--co-cal-border:var(--co-semantic-border-default);--co-cal-text:var(--co-semantic-text-default);--co-cal-text-muted:var(--co-semantic-text-muted);--co-cal-hover:var(--co-semantic-surface-hover);--co-cal-today-ring:var(--co-color-primary-azul);--co-cal-event-radius:6px;--co-cal-elevation-hover:var(--co-shadow-lg);--co-cal-event-bg:var(--co-color-primary-azul);--co-cal-event-border:transparent;--co-cal-event-text:var(--co-color-base-blanco, #fff);--co-cal-event-text-light:var(--co-color-base-blanco, #fff);--co-cal-event-text-dark:var(--co-semantic-text-default)}.cal-month{display:flex;flex-direction:column;height:100%;border-radius:var(--co-border-radius-xs);overflow:hidden;background:var(--co-cal-surface)}.cal-month__dow{display:grid;grid-template-columns:repeat(7, 1fr);border-bottom:1px solid var(--co-cal-border)}.cal-month__dow-cell{padding:var(--co-spacing-xs) var(--co-spacing-sm);font-size:var(--co-font-size-10, 10px);font-weight:600;text-transform:uppercase;letter-spacing:0.04em;color:var(--co-cal-text-muted);text-align:right}.cal-month__week{position:relative;min-height:var(--co-cal-min-week-h);flex:1 0 auto}.cal-month__week:not(:last-child){border-bottom:1px solid var(--co-cal-border)}.cal-month__days{display:grid;grid-template-columns:repeat(7, 1fr);height:100%;position:absolute;inset:0}.cal-month__day{border-right:1px solid var(--co-cal-border);padding:var(--co-spacing-xxs);cursor:pointer;transition:background var(--co-motion-duration-fast) var(--co-motion-ease-out)}.cal-month__day:last-child{border-right:0}.cal-month__day:hover{background:var(--co-cal-hover)}.cal-month__day:focus-visible{outline:2px solid var(--co-semantic-border-focus);outline-offset:-2px}.cal-month__day--outside .cal-month__daynum{color:var(--co-cal-text-muted)}.cal-month__day--disabled{cursor:not-allowed;background:color-mix(in srgb, var(--co-cal-border) 20%, transparent)}.cal-month__day--drag-over{background:color-mix(in srgb, var(--co-cal-today-ring) 14%, transparent);box-shadow:inset 0 0 0 2px var(--co-cal-today-ring)}.cal-month__day--selected{background:color-mix(in srgb, var(--co-cal-today-ring) 10%, transparent)}.cal-month__daynum{display:inline-flex;align-items:center;justify-content:center;min-width:22px;height:22px;margin-left:auto;float:right;font-size:var(--co-font-size-12, 12px);color:var(--co-cal-text);border-radius:var(--co-border-radius-full)}.cal-month__day--today .cal-month__daynum{background:var(--co-cal-today-ring);color:var(--co-color-base-blanco, #fff);font-weight:600}.cal-month__events{position:absolute;inset:0;pointer-events:none;}.cal-chip,.cal-month__more{position:absolute;height:calc(var(--co-cal-lane-h) - 3px);box-sizing:border-box;pointer-events:auto;display:flex;align-items:center;gap:var(--co-spacing-xxs);margin:0 3px;padding:0 var(--co-spacing-xs);border:1px solid var(--co-cal-event-border);border-radius:var(--co-cal-event-radius);font-family:inherit;font-size:var(--co-font-size-12, 12px);line-height:1;text-align:left;cursor:pointer;overflow:hidden;white-space:nowrap}.cal-chip{background:var(--co-cal-event-bg);color:var(--co-cal-event-text);user-select:none;-webkit-user-select:none;touch-action:none}.cal-month__chip-skeleton{position:absolute;height:calc(var(--co-cal-lane-h) - 3px);box-sizing:border-box;margin:0 3px;border-radius:var(--co-cal-event-radius);overflow:hidden;pointer-events:none}.cal-month__chip-skeleton co-skeleton{display:block;block-size:100%}.cal-chip--all-day:hover{filter:brightness(0.95);box-shadow:var(--co-cal-elevation-hover)}.cal-chip:focus-visible{outline:2px solid var(--co-semantic-border-focus);outline-offset:1px}.cal-chip--all-day{font-weight:500}.cal-chip__dot{flex:0 0 auto;width:7px;height:7px;border-radius:var(--co-border-radius-full);background:var(--co-cal-event-bg)}.cal-chip:not(.cal-chip--all-day){background:transparent;color:var(--co-cal-text);border-color:transparent}.cal-chip:not(.cal-chip--all-day):hover{background:var(--co-cal-hover);filter:none}.cal-chip__time{flex:0 0 auto;color:var(--co-cal-text-muted);font-variant-numeric:tabular-nums}.cal-chip__title{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}.cal-chip__ext{flex:0 0 auto;margin-inline-start:auto;opacity:0.8}.cal-chip--past{opacity:0.55}.cal-chip--locked{cursor:default}.cal-chip--external{border-style:dashed}.cal-chip--dragging{opacity:0.4}.cal-month--interacting .cal-chip{pointer-events:none}.cal-chip--all-day.cal-chip--tentative{background-image:repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.5) 0 4px, transparent 4px 8px)}.cal-chip--cancelled{opacity:0.6}.cal-chip--cancelled .cal-chip__title{text-decoration:line-through}.cal-chip--continues-before{border-top-left-radius:0;border-bottom-left-radius:0;margin-left:0}.cal-chip--continues-after{border-top-right-radius:0;border-bottom-right-radius:0;margin-right:0}.cal-month__more{background:transparent;color:var(--co-cal-text-muted);border-color:transparent;font-weight:600;font-size:var(--co-font-size-11, 11px)}.cal-month__more:hover{background:var(--co-cal-hover);color:var(--co-cal-text)}`;
369
369
 
370
+ // Distancia (px) que el puntero debe recorrer tras el pointerdown para que un drag
371
+ // de evento se comprometa. Por debajo de esto el gesto es un CLICK: el drag no
372
+ // arranca, el chip conserva sus pointer-events y su click abre el popover. Mismo
373
+ // literal/mecanismo que co-calendar-timegrid.tsx (DRAG_THRESHOLD_PX ahí, línea ~28).
374
+ const DRAG_THRESHOLD_PX$1 = 5;
370
375
  const CoCalendarMonth = class {
371
376
  constructor(hostRef) {
372
377
  index.registerInstance(this, hostRef);
@@ -397,6 +402,21 @@ const CoCalendarMonth = class {
397
402
  /** Epoch ms of "now", refreshed on a 60s timer so `past` styling stays live. */
398
403
  this.nowMs = 0;
399
404
  this.onPointerUp = () => this.finishDrag();
405
+ this.onPointerMove = (e) => this.trackDrag(e);
406
+ // Drag ARMADO pero aún no comprometido: `startDrag` guarda el id y el punto de
407
+ // agarre acá; el drag pasa a activo (`dragId`) recién cuando el puntero cruza
408
+ // DRAG_THRESHOLD_PX en `trackDrag` (mismo patrón que co-calendar-timegrid.tsx,
409
+ // `dragArmedId`/`startMove`). Así un click simple en un evento arrastrable no
410
+ // arranca drag (que pone `pointer-events:none` en los chips vía
411
+ // `cal-month--interacting`) y su popover abre normal.
412
+ this.dragArmedId = null;
413
+ this.dragStartPointer = null;
414
+ // Set right before coEventDrop so the trailing click no-ops (mismo patrón que
415
+ // co-calendar-timegrid.tsx#suppressNextClick): un drag COMPROMETIDO deja el
416
+ // chip con pointer-events restaurados (`setInteracting(false)`) ANTES de que
417
+ // el navegador dispare el `click` sintético que sigue al `pointerup` — sin
418
+ // este flag ese click reabriría el popover justo después de soltar.
419
+ this.suppressNextClick = false;
400
420
  // ── Selection / activation ──────────────────────────────────────────────
401
421
  /** Día seleccionado que PERSISTE resaltado mientras el host tiene abierto su
402
422
  * form/bubble de creación (referencia visual, paridad Google). */
@@ -441,9 +461,11 @@ const CoCalendarMonth = class {
441
461
  }
442
462
  connectedCallback() {
443
463
  window.addEventListener('pointerup', this.onPointerUp);
464
+ window.addEventListener('pointermove', this.onPointerMove);
444
465
  }
445
466
  disconnectedCallback() {
446
467
  window.removeEventListener('pointerup', this.onPointerUp);
468
+ window.removeEventListener('pointermove', this.onPointerMove);
447
469
  if (this.nowTimer)
448
470
  window.clearInterval(this.nowTimer);
449
471
  }
@@ -500,16 +522,43 @@ const CoCalendarMonth = class {
500
522
  return;
501
523
  // Ver la nota en co-calendar-timegrid#startMove: preventDefault en
502
524
  // pointerdown mata el click y el chip arrastrable no podía activarse.
525
+ // Tampoco se toca dragId/interacting acá: eso arrancaba
526
+ // `cal-month--interacting` (pointer-events:none en los chips, css:249) en el
527
+ // pointerdown mismo y se comía el click de todo evento FUTURO arrastrable —
528
+ // el chip nunca veía el click nativo. Se arma un candidato nada más; el
529
+ // commit real ocurre en `trackDrag` al cruzar DRAG_THRESHOLD_PX.
503
530
  e.stopPropagation();
504
- this.dragId = id;
531
+ this.dragArmedId = id;
532
+ this.dragStartPointer = { x: e.clientX, y: e.clientY };
533
+ }
534
+ /** Arma → activa el drag al cruzar el umbral (ver DRAG_THRESHOLD_PX). Antes de
535
+ * eso no toca dragId/interacting, así el click nativo del chip sigue vivo. */
536
+ trackDrag(e) {
537
+ if (!this.dragArmedId || this.dragId)
538
+ return;
539
+ const sp = this.dragStartPointer;
540
+ if (!sp)
541
+ return;
542
+ if (Math.hypot(e.clientX - sp.x, e.clientY - sp.y) < DRAG_THRESHOLD_PX$1)
543
+ return;
544
+ this.dragId = this.dragArmedId;
545
+ this.dragArmedId = null;
505
546
  this.dragOverDate = null;
506
547
  this.setInteracting(true);
507
548
  }
508
549
  finishDrag() {
550
+ // pointerup habiendo solo ARMADO (sin cruzar el umbral) = fue un click, no un
551
+ // drag: desarmar en silencio y dejar pasar el click nativo → abre el popover.
552
+ if (this.dragArmedId && !this.dragId) {
553
+ this.dragArmedId = null;
554
+ this.dragStartPointer = null;
555
+ return;
556
+ }
509
557
  const id = this.dragId;
510
558
  const target = this.dragOverDate;
511
559
  this.dragId = null;
512
560
  this.dragOverDate = null;
561
+ this.dragStartPointer = null;
513
562
  this.setInteracting(false);
514
563
  if (!id || !target)
515
564
  return;
@@ -524,6 +573,10 @@ const CoCalendarMonth = class {
524
573
  return;
525
574
  if (!this.isDayInteractable(target))
526
575
  return;
576
+ this.suppressNextClick = true;
577
+ // Clear on the next macrotask: a same-target synthetic click fires before this
578
+ // (and is suppressed); a later unrelated click is not.
579
+ setTimeout(() => { this.suppressNextClick = false; }, 0);
527
580
  const shifted = shiftEventByDays(ev, deltaDays, this.timeZone);
528
581
  this.coEventDrop.emit({
529
582
  id,
@@ -615,6 +668,10 @@ const CoCalendarMonth = class {
615
668
  'cal-chip--cancelled': ev.responseState === 'cancelled' || ev.responseState === 'declined',
616
669
  }, style: style, title: ev.title, "aria-label": ev.title, onClick: (e) => {
617
670
  e.stopPropagation();
671
+ if (this.suppressNextClick) {
672
+ this.suppressNextClick = false;
673
+ return;
674
+ }
618
675
  this.activateEvent(ev.id, e.currentTarget.getBoundingClientRect());
619
676
  }, onDblClick: (e) => {
620
677
  e.stopPropagation();
@@ -628,7 +685,7 @@ const CoCalendarMonth = class {
628
685
  const short = dates.getWeekdayLabels(this.locale, this.firstDayOfWeek, 'short');
629
686
  const long = dates.getWeekdayLabels(this.locale, this.firstDayOfWeek, 'long');
630
687
  const today = dates.todayYMD();
631
- return (index.h("div", { key: 'f8bcb53b7ef7c47a1ff59caee0305dfc1a3f1fc2', class: "cal-month", part: "grid", role: "grid", onKeyDown: this.handleKeyDown, ref: (el) => (this.rootEl = el) }, index.h("div", { key: '11acf9973a13ad661590a04dd934c86ceaa10f5d', class: "cal-month__dow", role: "row" }, short.map((lbl, i) => (index.h("span", { class: "cal-month__dow-cell", role: "columnheader", "aria-label": long[i] }, lbl)))), matrix.map((week, wi) => {
688
+ return (index.h("div", { key: '7cb63a84f7005ee7b5552a5d9b88c598f579b7be', class: "cal-month", part: "grid", role: "grid", onKeyDown: this.handleKeyDown, ref: (el) => (this.rootEl = el) }, index.h("div", { key: '70281a5799b9b95957d152e15a374001a2ec8fa2', class: "cal-month__dow", role: "row" }, short.map((lbl, i) => (index.h("span", { class: "cal-month__dow-cell", role: "columnheader", "aria-label": long[i] }, lbl)))), matrix.map((week, wi) => {
632
689
  var _a;
633
690
  return (index.h("div", { class: "cal-month__week", role: "row" }, index.h("div", { class: "cal-month__days" }, week.map((date) => {
634
691
  const ymd = dates.parseISO(date);
@@ -2,7 +2,7 @@
2
2
 
3
3
  var index = require('./index-DK-2Lzmf.js');
4
4
 
5
- const coCheckboxCss = () => `:host{display:inline-flex;font-family:var(--co-font-family-primary);font-size:var(--co-font-size-14);letter-spacing:var(--co-font-letter-spacing-body);line-height:1}.co-checkbox-row{display:flex;align-items:center;gap:var(--co-spacing-sm2);cursor:pointer}.co-checkbox-row--disabled{cursor:not-allowed}.co-checkbox__label{color:var(--co-semantic-text-secondary);font-size:var(--co-font-size-14);font-weight:400;line-height:1;white-space:nowrap;user-select:none}.co-checkbox-row--disabled .co-checkbox__label{color:var(--co-semantic-text-disabled)}.co-checkbox{position:relative;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;border:none;outline:none;padding:0;overflow:hidden;flex-shrink:0;box-sizing:border-box;transition:background var(--co-motion-duration-fast) var(--co-motion-ease-out), border-color var(--co-motion-duration-fast) var(--co-motion-ease-out)}.co-checkbox--small{width:16px;height:16px;border-radius:var(--co-border-radius-xxs);}.co-checkbox--medium{width:20px;height:20px;border-radius:var(--co-spacing-sm);}.co-checkbox--large{width:24px;height:24px;border-radius:var(--co-spacing-sm);}.co-checkbox:not(.co-checkbox--checked){background:color-mix(in srgb, var(--co-semantic-surface-secondary) 35%, transparent);-webkit-backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate));backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate));border:1px solid color-mix(in srgb, var(--co-semantic-border-default) 75%, transparent)}.co-checkbox--checked{background:var(--co-semantic-surface-primary);border:none}.co-checkbox--indeterminate{background:var(--co-semantic-surface-primary);border:none}.co-checkbox--disabled{opacity:0.4;cursor:not-allowed;pointer-events:none}.co-checkbox--overlay{border-radius:6px}.co-checkbox--overlay.co-checkbox--small{width:20px;height:20px;border-radius:6px}.co-checkbox--overlay.co-checkbox--medium,.co-checkbox--overlay.co-checkbox--large{width:22px;height:22px;border-radius:6px}.co-checkbox--overlay:not(.co-checkbox--checked):not(.co-checkbox--indeterminate){background:rgba(255, 255, 255, 0.9);box-shadow:inset 0 0 0 1px var(--co-color-opacity-negro-16, rgba(31, 28, 27, 0.16));border:none}.co-checkbox--overlay.co-checkbox--checked,.co-checkbox--overlay.co-checkbox--indeterminate{background:var(--co-color-primary-azul, #2563eb);border:none;box-shadow:none}.co-checkbox__glyph{display:block;pointer-events:none}.co-checkbox__glyph path{stroke:var(--co-semantic-on-primary);stroke-dasharray:1;stroke-dashoffset:1;opacity:0}.co-checkbox--checked .co-checkbox__check,.co-checkbox--indeterminate .co-checkbox__dash{stroke-dashoffset:0;opacity:1;transition:stroke-dashoffset var(--co-motion-duration-base) var(--co-motion-ease-out)}.co-checkbox--small .co-checkbox__glyph{width:12px;height:12px}.co-checkbox--medium .co-checkbox__glyph{width:14px;height:14px}.co-checkbox--large .co-checkbox__glyph{width:18px;height:18px}.co-checkbox--small .co-checkbox__check{stroke-width:2;}.co-checkbox--medium .co-checkbox__check{stroke-width:1.714;}.co-checkbox--large .co-checkbox__check{stroke-width:1.333;}.co-checkbox--small .co-checkbox__dash{stroke-width:2;}.co-checkbox--medium .co-checkbox__dash{stroke-width:2;}.co-checkbox--large .co-checkbox__dash{stroke-width:1.778;}.co-checkbox--overlay .co-checkbox__glyph{width:100%;height:100%}.co-checkbox--overlay .co-checkbox__glyph path{stroke:#fff;stroke-width:2.2}@supports not (background: color-mix(in srgb, red, transparent)){.co-checkbox:not(.co-checkbox--checked){background:transparent}}`;
5
+ const coCheckboxCss = () => `:host{display:inline-flex;font-family:var(--co-font-family-primary);font-size:var(--co-font-size-14);letter-spacing:var(--co-font-letter-spacing-body);line-height:1}.co-checkbox-row{display:flex;align-items:center;gap:var(--co-spacing-sm2);cursor:pointer}.co-checkbox-row--disabled{cursor:not-allowed}.co-checkbox__label{color:var(--co-semantic-text-secondary);font-size:var(--co-font-size-14);font-weight:400;line-height:1;white-space:nowrap;user-select:none}.co-checkbox-row--disabled .co-checkbox__label{color:var(--co-semantic-text-disabled)}.co-checkbox{position:relative;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;border:none;outline:none;padding:0;overflow:hidden;flex-shrink:0;box-sizing:border-box;transition:background var(--co-motion-duration-fast) var(--co-motion-ease-out), border-color var(--co-motion-duration-fast) var(--co-motion-ease-out)}.co-checkbox--small{width:16px;height:16px;border-radius:var(--co-border-radius-xxs);}.co-checkbox--medium{width:20px;height:20px;border-radius:var(--co-spacing-sm);}.co-checkbox--large{width:24px;height:24px;border-radius:var(--co-spacing-sm);}.co-checkbox:not(.co-checkbox--checked){background:color-mix(in srgb, var(--co-semantic-surface-secondary) 35%, transparent);-webkit-backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate));backdrop-filter:blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate));border:1px solid color-mix(in srgb, var(--co-semantic-border-default) 75%, transparent)}.co-checkbox--checked{background:var(--co-semantic-surface-primary);border:none}.co-checkbox--indeterminate{background:var(--co-semantic-surface-primary);border:none}.co-checkbox--disabled{opacity:0.4;cursor:not-allowed;pointer-events:none}.co-checkbox--overlay{border-radius:6px}.co-checkbox--overlay.co-checkbox--small{width:20px;height:20px;border-radius:6px}.co-checkbox--overlay.co-checkbox--medium,.co-checkbox--overlay.co-checkbox--large{width:22px;height:22px;border-radius:6px}.co-checkbox--overlay:not(.co-checkbox--checked):not(.co-checkbox--indeterminate){background:rgba(255, 255, 255, 0.9);box-shadow:inset 0 0 0 1px var(--co-color-opacity-negro-16, rgba(31, 28, 27, 0.16));border:none}.co-checkbox--overlay.co-checkbox--checked,.co-checkbox--overlay.co-checkbox--indeterminate{background:var(--co-color-primary-azul, #2563eb);border:none;box-shadow:none}.co-checkbox__glyph{display:block;pointer-events:none}.co-checkbox__glyph path{stroke:var(--co-semantic-on-primary);stroke-dasharray:1;stroke-dashoffset:1;opacity:0}.co-checkbox--checked .co-checkbox__check,.co-checkbox--indeterminate .co-checkbox__dash{stroke-dashoffset:0;opacity:1;transition:stroke-dashoffset var(--co-motion-duration-base) var(--co-motion-ease-out)}.co-checkbox--small .co-checkbox__glyph{width:12px;height:12px}.co-checkbox--medium .co-checkbox__glyph{width:14px;height:14px}.co-checkbox--large .co-checkbox__glyph{width:18px;height:18px}.co-checkbox--small .co-checkbox__check{stroke-width:2;}.co-checkbox--medium .co-checkbox__check{stroke-width:1.714;}.co-checkbox--large .co-checkbox__check{stroke-width:1.333;}.co-checkbox--small .co-checkbox__dash{stroke-width:2;}.co-checkbox--medium .co-checkbox__dash{stroke-width:2;}.co-checkbox--large .co-checkbox__dash{stroke-width:1.778;}.co-checkbox--overlay .co-checkbox__glyph{width:100%;height:100%}.co-checkbox--overlay .co-checkbox__glyph path{stroke:#fff;stroke-width:2.2}@supports not (background: color-mix(in srgb, red, transparent)){.co-checkbox:not(.co-checkbox--checked){background:transparent}}.co-checkbox.co-checkbox:focus-visible{outline:none;border-color:var(--co-semantic-border-focus);box-shadow:0 0 0 2px var(--co-semantic-border-focus)}`;
6
6
 
7
7
  const CoCheckbox = class {
8
8
  constructor(hostRef) {
@@ -37,6 +37,12 @@ const CoCheckbox = class {
37
37
  }
38
38
  }
39
39
  };
40
+ this.handleKeyDown = (e) => {
41
+ if (e.key === ' ') {
42
+ e.preventDefault(); // Space no debe scrollear la página
43
+ this.handleClick(); // ya guarda disabled y resuelve indeterminate
44
+ }
45
+ };
40
46
  }
41
47
  render() {
42
48
  const isOverlay = this.appearance === 'overlay';
@@ -44,17 +50,17 @@ const CoCheckbox = class {
44
50
  // Only override the fill when a custom color is provided AND the box is "on".
45
51
  // Leaving this undefined keeps the default appearance byte-identical to before.
46
52
  const boxStyle = this.onColor && isOn ? { background: this.onColor } : undefined;
47
- return (index.h("div", { key: '31690de633689da0b273e3c88cc200cabb4cee75', class: {
53
+ return (index.h("div", { key: 'caf200e3c53efa2a00d28db0e149da953e4432da', class: {
48
54
  'co-checkbox-row': true,
49
55
  'co-checkbox-row--disabled': this.disabled,
50
- }, onClick: this.handleClick }, index.h("span", { key: '2b0c4ebbe4c7a7a8046cf726e682a3d42ae3ebbe', role: "checkbox", "aria-checked": this.indeterminate ? 'mixed' : String(this.checked), "aria-label": this.label || '', class: {
56
+ }, onClick: this.handleClick }, index.h("span", { key: 'a8fe01958d81587129f304ce33f1f5fef882dd9f', role: "checkbox", "aria-checked": this.indeterminate ? 'mixed' : String(this.checked), "aria-label": this.label || '', "aria-disabled": this.disabled ? 'true' : undefined, tabIndex: this.disabled ? -1 : 0, onKeyDown: this.handleKeyDown, class: {
51
57
  'co-checkbox': true,
52
58
  [`co-checkbox--${this.size}`]: true,
53
59
  'co-checkbox--overlay': isOverlay,
54
60
  'co-checkbox--checked': this.checked && !this.indeterminate,
55
61
  'co-checkbox--indeterminate': this.indeterminate,
56
62
  'co-checkbox--disabled': this.disabled,
57
- }, style: boxStyle, part: "box" }, index.h("svg", { key: 'a127c176e0233460f14c4261d8d2157e657689a9', class: "co-checkbox__glyph", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true" }, index.h("path", { key: 'ad7dc0018cdae31156884cd04326bbcdba132b4f', class: "co-checkbox__check", d: "M3.5 8.5l3 3 6-6.5", pathLength: "1", "stroke-linecap": "round", "stroke-linejoin": "round" }), index.h("path", { key: 'dd665144b25aa51339cf9f6ce0e0edf65cfbe5a9', class: "co-checkbox__dash", d: "M3 8h10", pathLength: "1", "stroke-linecap": "round" }))), this.label && (index.h("span", { key: '08d6c695e2cbb8188564dc8bb5aab9b569c24838', class: "co-checkbox__label", part: "label" }, this.label))));
63
+ }, style: boxStyle, part: "box" }, index.h("svg", { key: 'd9ea60be2c2e58c227aeca8ae3b8e8f459f3522d', class: "co-checkbox__glyph", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true" }, index.h("path", { key: 'd25f835b95a2200d44b5e4afdeb727d758e0650f', class: "co-checkbox__check", d: "M3.5 8.5l3 3 6-6.5", pathLength: "1", "stroke-linecap": "round", "stroke-linejoin": "round" }), index.h("path", { key: 'b7a043b9910736a8bdd15720fd7857c01250086d', class: "co-checkbox__dash", d: "M3 8h10", pathLength: "1", "stroke-linecap": "round" }))), this.label && (index.h("span", { key: '2e256fb7fd1515bf9dbe3dc380a0d7d09d5347ac', class: "co-checkbox__label", part: "label" }, this.label))));
58
64
  }
59
65
  };
60
66
  CoCheckbox.style = coCheckboxCss();