@caribeng/ui 22.4.0 → 22.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +313 -313
  2. package/fesm2022/caribeng-ui-account-picker.mjs +533 -0
  3. package/fesm2022/caribeng-ui-aging.mjs +488 -0
  4. package/fesm2022/{caribeng-ui-caribe-alert.mjs → caribeng-ui-alert.mjs} +45 -45
  5. package/fesm2022/caribeng-ui-amount.mjs +249 -0
  6. package/fesm2022/caribeng-ui-anchor.mjs +2 -2
  7. package/fesm2022/{caribeng-ui-caribe-animation-lottie.mjs → caribeng-ui-animation-lottie.mjs} +41 -41
  8. package/fesm2022/caribeng-ui-audit-log.mjs +323 -0
  9. package/fesm2022/caribeng-ui-avatar.mjs +2 -2
  10. package/fesm2022/caribeng-ui-breadcrumb.mjs +13 -3
  11. package/fesm2022/{caribeng-ui-caribe-button-group.mjs → caribeng-ui-button-group.mjs} +15 -15
  12. package/fesm2022/caribeng-ui-button.mjs +2 -2
  13. package/fesm2022/{caribeng-ui-caribe-card-content.mjs → caribeng-ui-card-content.mjs} +39 -39
  14. package/fesm2022/{caribeng-ui-caribe-card-move.mjs → caribeng-ui-card-move.mjs} +65 -65
  15. package/fesm2022/{caribeng-ui-caribe-card-primary.mjs → caribeng-ui-card-primary.mjs} +31 -31
  16. package/fesm2022/{caribeng-ui-caribe-card-select.mjs → caribeng-ui-card-select.mjs} +67 -67
  17. package/fesm2022/caribeng-ui-carousel.mjs +2 -2
  18. package/fesm2022/caribeng-ui-cascadeselect.mjs +45 -9
  19. package/fesm2022/caribeng-ui-chat.mjs +2 -2
  20. package/fesm2022/{caribeng-ui-caribe-coachmark.mjs → caribeng-ui-coachmark.mjs} +85 -85
  21. package/fesm2022/caribeng-ui-command-palette.mjs +2 -2
  22. package/fesm2022/caribeng-ui-comments.mjs +864 -0
  23. package/fesm2022/caribeng-ui-datagrid.mjs +1635 -0
  24. package/fesm2022/caribeng-ui-dataview.mjs +2 -2
  25. package/fesm2022/caribeng-ui-datepicker.mjs +2 -2
  26. package/fesm2022/caribeng-ui-document.mjs +495 -0
  27. package/fesm2022/{caribeng-ui-caribe-dots-indicator.mjs → caribeng-ui-dots-indicator.mjs} +41 -41
  28. package/fesm2022/caribeng-ui-dynamic-form.mjs +1581 -0
  29. package/fesm2022/caribeng-ui-editor.mjs +2303 -1311
  30. package/fesm2022/{caribeng-ui-caribe-expansion-panel.mjs → caribeng-ui-expansion-panel.mjs} +39 -39
  31. package/fesm2022/{caribeng-ui-caribe-fab-menu.mjs → caribeng-ui-fab-menu.mjs} +75 -75
  32. package/fesm2022/caribeng-ui-file-card.mjs +2 -2
  33. package/fesm2022/{caribeng-ui-caribe-file-download.mjs → caribeng-ui-file-download.mjs} +63 -63
  34. package/fesm2022/caribeng-ui-financial-report.mjs +380 -0
  35. package/fesm2022/{caribeng-ui-caribe-float-menu.mjs → caribeng-ui-float-menu.mjs} +31 -31
  36. package/fesm2022/caribeng-ui-floatlabel.mjs +2 -2
  37. package/fesm2022/caribeng-ui-flow.mjs +1508 -0
  38. package/fesm2022/{caribeng-ui-caribe-footer.mjs → caribeng-ui-footer.mjs} +19 -19
  39. package/fesm2022/caribeng-ui-gantt.mjs +1094 -0
  40. package/fesm2022/{caribeng-ui-caribe-header.mjs → caribeng-ui-header.mjs} +49 -49
  41. package/fesm2022/{caribeng-ui-caribe-icon-button.mjs → caribeng-ui-icon-button.mjs} +23 -23
  42. package/fesm2022/caribeng-ui-image-cropper.mjs +671 -0
  43. package/fesm2022/caribeng-ui-import-wizard.mjs +746 -0
  44. package/fesm2022/caribeng-ui-infinite-scroll.mjs +226 -0
  45. package/fesm2022/caribeng-ui-input-number.mjs +22 -6
  46. package/fesm2022/{caribeng-ui-caribe-input-search.mjs → caribeng-ui-input-search.mjs} +65 -65
  47. package/fesm2022/{caribeng-ui-caribe-input-token.mjs → caribeng-ui-input-token.mjs} +59 -59
  48. package/fesm2022/caribeng-ui-inputotp.mjs +2 -2
  49. package/fesm2022/caribeng-ui-journal-entry.mjs +340 -0
  50. package/fesm2022/caribeng-ui-kanban.mjs +6 -6
  51. package/fesm2022/caribeng-ui-kpi.mjs +189 -0
  52. package/fesm2022/{caribeng-ui-caribe-link.mjs → caribeng-ui-link.mjs} +37 -37
  53. package/fesm2022/caribeng-ui-masonry.mjs +93 -0
  54. package/fesm2022/caribeng-ui-media-player.mjs +821 -0
  55. package/fesm2022/caribeng-ui-mentions.mjs +2 -2
  56. package/fesm2022/caribeng-ui-notification-center.mjs +636 -0
  57. package/fesm2022/{caribeng-ui-caribe-off-canvas.mjs → caribeng-ui-off-canvas.mjs} +55 -55
  58. package/fesm2022/{caribeng-ui-caribe-onboarding.mjs → caribeng-ui-onboarding.mjs} +105 -105
  59. package/fesm2022/caribeng-ui-orderlist.mjs +2 -2
  60. package/fesm2022/caribeng-ui-pdfviewer.mjs +1755 -25
  61. package/fesm2022/caribeng-ui-period-picker.mjs +637 -0
  62. package/fesm2022/caribeng-ui-phone-input.mjs +2 -2
  63. package/fesm2022/caribeng-ui-picklist.mjs +2 -2
  64. package/fesm2022/caribeng-ui-pivot.mjs +419 -0
  65. package/fesm2022/caribeng-ui-pricing.mjs +2 -2
  66. package/fesm2022/caribeng-ui-rating.mjs +14 -17
  67. package/fesm2022/caribeng-ui-reconciliation.mjs +386 -0
  68. package/fesm2022/caribeng-ui-scheduler.mjs +1027 -0
  69. package/fesm2022/caribeng-ui-select.mjs +2 -2
  70. package/fesm2022/{caribeng-ui-caribe-shortcut.mjs → caribeng-ui-shortcut.mjs} +29 -29
  71. package/fesm2022/caribeng-ui-sidebar.mjs +2 -2
  72. package/fesm2022/caribeng-ui-signature-pad.mjs +654 -0
  73. package/fesm2022/{caribeng-ui-caribe-status.mjs → caribeng-ui-status.mjs} +11 -11
  74. package/fesm2022/{caribeng-ui-caribe-step-indicator.mjs → caribeng-ui-step-indicator.mjs} +53 -53
  75. package/fesm2022/caribeng-ui-stepper.mjs +2 -2
  76. package/fesm2022/caribeng-ui-steps.mjs +2 -2
  77. package/fesm2022/caribeng-ui-table.mjs +323 -15
  78. package/fesm2022/caribeng-ui-tabmenu.mjs +2 -2
  79. package/fesm2022/caribeng-ui-tabs.mjs +2 -2
  80. package/fesm2022/{caribeng-ui-caribe-tag-button.mjs → caribeng-ui-tag-button.mjs} +25 -25
  81. package/fesm2022/caribeng-ui-tag.mjs +2 -2
  82. package/fesm2022/caribeng-ui-tieredmenu.mjs +6 -6
  83. package/fesm2022/{caribeng-ui-caribe-tracker.mjs → caribeng-ui-tracker.mjs} +29 -29
  84. package/fesm2022/{caribeng-ui-caribe-transaction-status.mjs → caribeng-ui-transaction-status.mjs} +11 -11
  85. package/fesm2022/caribeng-ui-treeselect.mjs +44 -9
  86. package/fesm2022/caribeng-ui-treetable.mjs +236 -17
  87. package/fesm2022/{caribeng-ui-caribe-voucher.mjs → caribeng-ui-voucher.mjs} +45 -45
  88. package/fesm2022/caribeng-ui-xlsx.mjs +486 -0
  89. package/fesm2022/caribeng-ui.mjs +1185 -5
  90. package/package.json +217 -177
  91. package/types/caribeng-ui-account-picker.d.ts +142 -0
  92. package/types/caribeng-ui-aging.d.ts +123 -0
  93. package/types/{caribeng-ui-caribe-alert.d.ts → caribeng-ui-alert.d.ts} +2 -2
  94. package/types/caribeng-ui-amount.d.ts +82 -0
  95. package/types/{caribeng-ui-caribe-animation-lottie.d.ts → caribeng-ui-animation-lottie.d.ts} +2 -2
  96. package/types/caribeng-ui-audit-log.d.ts +86 -0
  97. package/types/caribeng-ui-breadcrumb.d.ts +2 -2
  98. package/types/{caribeng-ui-caribe-button-group.d.ts → caribeng-ui-button-group.d.ts} +2 -2
  99. package/types/{caribeng-ui-caribe-card-content.d.ts → caribeng-ui-card-content.d.ts} +2 -2
  100. package/types/{caribeng-ui-caribe-card-move.d.ts → caribeng-ui-card-move.d.ts} +1 -1
  101. package/types/{caribeng-ui-caribe-card-primary.d.ts → caribeng-ui-card-primary.d.ts} +2 -2
  102. package/types/{caribeng-ui-caribe-card-select.d.ts → caribeng-ui-card-select.d.ts} +2 -2
  103. package/types/caribeng-ui-cascadeselect.d.ts +6 -0
  104. package/types/{caribeng-ui-caribe-coachmark.d.ts → caribeng-ui-coachmark.d.ts} +2 -2
  105. package/types/caribeng-ui-comments.d.ts +214 -0
  106. package/types/caribeng-ui-datagrid.d.ts +269 -0
  107. package/types/caribeng-ui-document.d.ts +138 -0
  108. package/types/{caribeng-ui-caribe-dots-indicator.d.ts → caribeng-ui-dots-indicator.d.ts} +2 -2
  109. package/types/caribeng-ui-dynamic-form.d.ts +409 -0
  110. package/types/caribeng-ui-editor.d.ts +110 -12
  111. package/types/{caribeng-ui-caribe-expansion-panel.d.ts → caribeng-ui-expansion-panel.d.ts} +1 -1
  112. package/types/{caribeng-ui-caribe-fab-menu.d.ts → caribeng-ui-fab-menu.d.ts} +2 -2
  113. package/types/{caribeng-ui-caribe-file-download.d.ts → caribeng-ui-file-download.d.ts} +1 -1
  114. package/types/caribeng-ui-financial-report.d.ts +102 -0
  115. package/types/{caribeng-ui-caribe-float-menu.d.ts → caribeng-ui-float-menu.d.ts} +2 -2
  116. package/types/caribeng-ui-flow.d.ts +228 -0
  117. package/types/{caribeng-ui-caribe-footer.d.ts → caribeng-ui-footer.d.ts} +2 -2
  118. package/types/caribeng-ui-gantt.d.ts +244 -0
  119. package/types/{caribeng-ui-caribe-header.d.ts → caribeng-ui-header.d.ts} +2 -2
  120. package/types/{caribeng-ui-caribe-icon-button.d.ts → caribeng-ui-icon-button.d.ts} +2 -2
  121. package/types/{caribeng-ui-caribe-illustration.d.ts → caribeng-ui-illustration.d.ts} +1 -1
  122. package/types/caribeng-ui-image-cropper.d.ts +169 -0
  123. package/types/caribeng-ui-import-wizard.d.ts +149 -0
  124. package/types/caribeng-ui-infinite-scroll.d.ts +75 -0
  125. package/types/caribeng-ui-input-number.d.ts +1 -1
  126. package/types/{caribeng-ui-caribe-input-search.d.ts → caribeng-ui-input-search.d.ts} +2 -2
  127. package/types/{caribeng-ui-caribe-input-token.d.ts → caribeng-ui-input-token.d.ts} +2 -2
  128. package/types/caribeng-ui-journal-entry.d.ts +110 -0
  129. package/types/caribeng-ui-kpi.d.ts +64 -0
  130. package/types/{caribeng-ui-caribe-link.d.ts → caribeng-ui-link.d.ts} +2 -2
  131. package/types/{caribeng-ui-caribe-logo.d.ts → caribeng-ui-logo.d.ts} +1 -1
  132. package/types/caribeng-ui-masonry.d.ts +32 -0
  133. package/types/caribeng-ui-media-player.d.ts +140 -0
  134. package/types/caribeng-ui-notification-center.d.ts +153 -0
  135. package/types/{caribeng-ui-caribe-off-canvas.d.ts → caribeng-ui-off-canvas.d.ts} +2 -2
  136. package/types/{caribeng-ui-caribe-onboarding.d.ts → caribeng-ui-onboarding.d.ts} +2 -2
  137. package/types/caribeng-ui-pdfviewer.d.ts +245 -5
  138. package/types/caribeng-ui-period-picker.d.ts +148 -0
  139. package/types/caribeng-ui-pivot.d.ts +116 -0
  140. package/types/caribeng-ui-reconciliation.d.ts +109 -0
  141. package/types/caribeng-ui-scheduler.d.ts +188 -0
  142. package/types/{caribeng-ui-caribe-shortcut.d.ts → caribeng-ui-shortcut.d.ts} +2 -2
  143. package/types/caribeng-ui-signature-pad.d.ts +151 -0
  144. package/types/{caribeng-ui-caribe-status.d.ts → caribeng-ui-status.d.ts} +2 -2
  145. package/types/{caribeng-ui-caribe-step-indicator.d.ts → caribeng-ui-step-indicator.d.ts} +2 -2
  146. package/types/caribeng-ui-table.d.ts +66 -2
  147. package/types/{caribeng-ui-caribe-tag-button.d.ts → caribeng-ui-tag-button.d.ts} +2 -2
  148. package/types/{caribeng-ui-caribe-tracker.d.ts → caribeng-ui-tracker.d.ts} +2 -2
  149. package/types/{caribeng-ui-caribe-transaction-status.d.ts → caribeng-ui-transaction-status.d.ts} +2 -2
  150. package/types/caribeng-ui-treeselect.d.ts +6 -0
  151. package/types/caribeng-ui-treetable.d.ts +67 -2
  152. package/types/{caribeng-ui-caribe-voucher.d.ts → caribeng-ui-voucher.d.ts} +2 -2
  153. package/types/caribeng-ui-xlsx.d.ts +79 -0
  154. package/types/caribeng-ui.d.ts +713 -4
  155. package/fesm2022/caribeng-ui-caribe-calendar.mjs +0 -92
  156. package/fesm2022/caribeng-ui-caribe-circle-loading.mjs +0 -130
  157. package/fesm2022/caribeng-ui-caribe-data-table.mjs +0 -94
  158. package/fesm2022/caribeng-ui-caribe-file-select.mjs +0 -88
  159. package/fesm2022/caribeng-ui-caribe-inline-alert.mjs +0 -100
  160. package/fesm2022/caribeng-ui-caribe-input-date.mjs +0 -138
  161. package/fesm2022/caribeng-ui-caribe-input-select.mjs +0 -154
  162. package/fesm2022/caribeng-ui-caribe-loader.mjs +0 -48
  163. package/fesm2022/caribeng-ui-caribe-modal.mjs +0 -119
  164. package/fesm2022/caribeng-ui-caribe-pictogram.mjs +0 -52
  165. package/fesm2022/caribeng-ui-caribe-pop-over.mjs +0 -104
  166. package/fesm2022/caribeng-ui-caribe-preloader.mjs +0 -57
  167. package/fesm2022/caribeng-ui-caribe-progress-bar.mjs +0 -84
  168. package/fesm2022/caribeng-ui-caribe-stroke.mjs +0 -69
  169. package/fesm2022/caribeng-ui-caribe-switch.mjs +0 -182
  170. package/types/caribeng-ui-caribe-calendar.d.ts +0 -27
  171. package/types/caribeng-ui-caribe-circle-loading.d.ts +0 -28
  172. package/types/caribeng-ui-caribe-data-table.d.ts +0 -26
  173. package/types/caribeng-ui-caribe-file-select.d.ts +0 -31
  174. package/types/caribeng-ui-caribe-inline-alert.d.ts +0 -28
  175. package/types/caribeng-ui-caribe-input-date.d.ts +0 -40
  176. package/types/caribeng-ui-caribe-input-select.d.ts +0 -47
  177. package/types/caribeng-ui-caribe-loader.d.ts +0 -22
  178. package/types/caribeng-ui-caribe-modal.d.ts +0 -21
  179. package/types/caribeng-ui-caribe-pictogram.d.ts +0 -15
  180. package/types/caribeng-ui-caribe-pop-over.d.ts +0 -17
  181. package/types/caribeng-ui-caribe-preloader.d.ts +0 -24
  182. package/types/caribeng-ui-caribe-progress-bar.d.ts +0 -28
  183. package/types/caribeng-ui-caribe-stroke.d.ts +0 -17
  184. package/types/caribeng-ui-caribe-switch.d.ts +0 -55
  185. /package/fesm2022/{caribeng-ui-caribe-illustration.mjs → caribeng-ui-illustration.mjs} +0 -0
  186. /package/fesm2022/{caribeng-ui-caribe-logo.mjs → caribeng-ui-logo.mjs} +0 -0
@@ -0,0 +1,637 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, Injector, model, input, booleanAttribute, output, signal, computed, viewChild, linkedSignal, afterNextRender, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
+ import * as i1 from '@angular/cdk/overlay';
5
+ import { OverlayModule } from '@angular/cdk/overlay';
6
+ import { injectCbTranslation, cbFieldState, cbFormat } from '@caribeng/ui';
7
+ import { CbIcon } from '@caribeng/ui/icon';
8
+
9
+ const pad = (n) => String(n).padStart(2, '0');
10
+ function isoDay(d) {
11
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
12
+ }
13
+ function lastDay(year, month) {
14
+ return new Date(year, month + 1, 0);
15
+ }
16
+ /** Mes: `2026-10`. */
17
+ function monthPeriod(year, month) {
18
+ return { kind: 'month', from: new Date(year, month, 1), to: lastDay(year, month), key: `${year}-${pad(month + 1)}` };
19
+ }
20
+ /**
21
+ * Año fiscal que empieza en `startMonth` (0 = enero). Se nombra por el año en
22
+ * que termina (con inicio en julio, el año fiscal 2026 va de jul 2025 a jun 2026).
23
+ */
24
+ function fiscalYear(year, startMonth = 0) {
25
+ const from = new Date(startMonth === 0 ? year : year - 1, startMonth, 1);
26
+ const to = lastDay(from.getFullYear() + 1, startMonth - 1);
27
+ return { kind: 'year', from, to, key: String(year) };
28
+ }
29
+ /** Trimestre `q` (1–4) del año fiscal `year`. */
30
+ function quarterPeriod(year, q, startMonth = 0) {
31
+ const fy = fiscalYear(year, startMonth);
32
+ const from = new Date(fy.from.getFullYear(), fy.from.getMonth() + (q - 1) * 3, 1);
33
+ const to = lastDay(from.getFullYear(), from.getMonth() + 2);
34
+ return { kind: 'quarter', from, to, key: `${year}-Q${q}` };
35
+ }
36
+ function rangePeriod(from, to) {
37
+ const a = new Date(from.getFullYear(), from.getMonth(), from.getDate());
38
+ const b = new Date(to.getFullYear(), to.getMonth(), to.getDate());
39
+ return { kind: 'range', from: a, to: b, key: `${isoDay(a)}_${isoDay(b)}` };
40
+ }
41
+ /** Año fiscal al que pertenece una fecha. */
42
+ function fiscalYearOf(date, startMonth = 0) {
43
+ return startMonth === 0 || date.getMonth() < startMonth ? date.getFullYear() : date.getFullYear() + 1;
44
+ }
45
+ /** Trimestre fiscal (1–4) de una fecha. */
46
+ function quarterOf(date, startMonth = 0) {
47
+ return Math.floor((((date.getMonth() - startMonth) % 12) + 12) % 12 / 3) + 1;
48
+ }
49
+ /** Periodo de un atajo respecto a `today`. */
50
+ function presetPeriod(preset, today, startMonth = 0) {
51
+ const y = today.getFullYear();
52
+ const m = today.getMonth();
53
+ const fy = fiscalYearOf(today, startMonth);
54
+ const q = quarterOf(today, startMonth);
55
+ switch (preset) {
56
+ case 'thisMonth':
57
+ return monthPeriod(y, m);
58
+ case 'lastMonth':
59
+ return m === 0 ? monthPeriod(y - 1, 11) : monthPeriod(y, m - 1);
60
+ case 'thisQuarter':
61
+ return quarterPeriod(fy, q, startMonth);
62
+ case 'lastQuarter':
63
+ return q === 1 ? quarterPeriod(fy - 1, 4, startMonth) : quarterPeriod(fy, q - 1, startMonth);
64
+ case 'yearToDate':
65
+ return rangePeriod(fiscalYear(fy, startMonth).from, today);
66
+ case 'thisYear':
67
+ return fiscalYear(fy, startMonth);
68
+ case 'lastYear':
69
+ return fiscalYear(fy - 1, startMonth);
70
+ }
71
+ }
72
+ /** Meses (`AAAA-MM`) que abarca un periodo. */
73
+ function monthsOf(period) {
74
+ const out = [];
75
+ const d = new Date(period.from.getFullYear(), period.from.getMonth(), 1);
76
+ while (d <= period.to) {
77
+ out.push(`${d.getFullYear()}-${pad(d.getMonth() + 1)}`);
78
+ d.setMonth(d.getMonth() + 1);
79
+ }
80
+ return out;
81
+ }
82
+ /** El periodo incluye algún mes cerrado. */
83
+ function touchesClosed(period, closed) {
84
+ return closed.size > 0 && monthsOf(period).some((m) => closed.has(m));
85
+ }
86
+ /** Periodo a partir de su clave (`2026-10`, `2026-Q3`, `2026`, `2026-01-01_2026-03-31`). */
87
+ function periodFromKey(key, startMonth = 0) {
88
+ let m = /^(\d{4})-(\d{2})$/.exec(key);
89
+ if (m)
90
+ return monthPeriod(+m[1], +m[2] - 1);
91
+ m = /^(\d{4})-Q([1-4])$/.exec(key);
92
+ if (m)
93
+ return quarterPeriod(+m[1], +m[2], startMonth);
94
+ m = /^(\d{4})$/.exec(key);
95
+ if (m)
96
+ return fiscalYear(+m[1], startMonth);
97
+ m = /^(\d{4})-(\d{2})-(\d{2})_(\d{4})-(\d{2})-(\d{2})$/.exec(key);
98
+ if (m)
99
+ return rangePeriod(new Date(+m[1], +m[2] - 1, +m[3]), new Date(+m[4], +m[5] - 1, +m[6]));
100
+ return null;
101
+ }
102
+
103
+ /** Columnas de la cuadrícula (meses, trimestres y años van de 4 en 4). */
104
+ const COLS = 4;
105
+ let nextUid = 0;
106
+ /**
107
+ * Selector de periodo contable de CaribeNG: mes, trimestre o año (fiscal), con
108
+ * atajos («Mes anterior», «Año a la fecha»…) y periodos cerrados marcados.
109
+ *
110
+ * - `fiscalYearStart` mueve el inicio del año fiscal (trimestres y años incluidos).
111
+ * - `closed` marca meses cerrados con un candado; con `disableClosed` no se eligen
112
+ * (útil al contabilizar), sin él se pueden consultar (útil en informes).
113
+ * - Funciona con Angular Forms o con `[(value)]`; el valor es un `CbPeriod` con
114
+ * `from`, `to`, `kind` y `key`.
115
+ *
116
+ * @example
117
+ * ```html
118
+ * <cb-period-picker label="Periodo" [(value)]="periodo" [closed]="cerrados" />
119
+ * ```
120
+ */
121
+ class CbPeriodPicker {
122
+ constructor() {
123
+ this.t = injectCbTranslation();
124
+ this.injector = inject(Injector);
125
+ this.uid = `cb-period-picker-${++nextUid}`;
126
+ this.value = model(null, /* @ts-ignore */
127
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
128
+ /** Vista de la cuadrícula: mes, trimestre o año. */
129
+ this.mode = model('month', /* @ts-ignore */
130
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
131
+ /** Vistas disponibles y su orden. */
132
+ this.modes = input(['month', 'quarter', 'year'], /* @ts-ignore */
133
+ ...(ngDevMode ? [{ debugName: "modes" }] : /* istanbul ignore next */ []));
134
+ /** Atajos del panel (lista vacía para quitarlos). */
135
+ this.presets = input(['thisMonth', 'lastMonth', 'thisQuarter', 'lastQuarter', 'yearToDate', 'thisYear', 'lastYear'], /* @ts-ignore */
136
+ ...(ngDevMode ? [{ debugName: "presets" }] : /* istanbul ignore next */ []));
137
+ /** Mes en que empieza el año fiscal (1 = enero). */
138
+ this.fiscalYearStart = input(1, /* @ts-ignore */
139
+ ...(ngDevMode ? [{ debugName: "fiscalYearStart" }] : /* istanbul ignore next */ []));
140
+ /** Meses cerrados (`AAAA-MM`): se marcan con un candado. */
141
+ this.closed = input([], /* @ts-ignore */
142
+ ...(ngDevMode ? [{ debugName: "closed" }] : /* istanbul ignore next */ []));
143
+ /** No deja elegir periodos que incluyan meses cerrados. */
144
+ this.disableClosed = input(false, { ...(ngDevMode ? { debugName: "disableClosed" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
145
+ /** Primer y último día que se pueden elegir. */
146
+ this.min = input(null, /* @ts-ignore */
147
+ ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
148
+ this.max = input(null, /* @ts-ignore */
149
+ ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
150
+ /** «Hoy» para los atajos y el periodo actual (por defecto, la fecha del sistema). */
151
+ this.today = input(new Date(), /* @ts-ignore */
152
+ ...(ngDevMode ? [{ debugName: "today" }] : /* istanbul ignore next */ []));
153
+ this.label = input('', /* @ts-ignore */
154
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
155
+ this.hint = input('', /* @ts-ignore */
156
+ ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
157
+ this.error = input('', /* @ts-ignore */
158
+ ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
159
+ this.placeholder = input(undefined, /* @ts-ignore */
160
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
161
+ this.size = input('md', /* @ts-ignore */
162
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
163
+ this.invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
164
+ this.required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
165
+ this.requiredIndicator = input(undefined, /* @ts-ignore */
166
+ ...(ngDevMode ? [{ debugName: "requiredIndicator" }] : /* istanbul ignore next */ []));
167
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
168
+ this.inputId = input(`cb-period-picker-input-${nextUid}`, /* @ts-ignore */
169
+ ...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
170
+ this.periodChange = output();
171
+ this.fieldState = cbFieldState({
172
+ invalid: () => this.invalid(),
173
+ required: () => this.required(),
174
+ requiredIndicator: () => this.requiredIndicator(),
175
+ });
176
+ this.positions = [
177
+ { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 4 },
178
+ { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -4 },
179
+ { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 4 },
180
+ ];
181
+ this.open = signal(false, /* @ts-ignore */
182
+ ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
183
+ this.cvaDisabled = signal(false, /* @ts-ignore */
184
+ ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : /* istanbul ignore next */ []));
185
+ this.isDisabled = computed(() => this.disabled() || this.cvaDisabled(), /* @ts-ignore */
186
+ ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
187
+ this.trigger = viewChild.required('trigger');
188
+ this.startMonth = computed(() => Math.min(12, Math.max(1, this.fiscalYearStart())) - 1, /* @ts-ignore */
189
+ ...(ngDevMode ? [{ debugName: "startMonth" }] : /* istanbul ignore next */ []));
190
+ this.closedSet = computed(() => new Set(this.closed()), /* @ts-ignore */
191
+ ...(ngDevMode ? [{ debugName: "closedSet" }] : /* istanbul ignore next */ []));
192
+ /** Año (o primer año de la docena, en la vista de años) que muestra la cuadrícula. */
193
+ this.year = linkedSignal(() => {
194
+ const ref = this.value()?.from ?? this.today();
195
+ return this.mode() === 'month' ? ref.getFullYear() : fiscalYearOf(ref, this.startMonth());
196
+ }, /* @ts-ignore */
197
+ ...(ngDevMode ? [{ debugName: "year" }] : /* istanbul ignore next */ []));
198
+ this.decadeStart = computed(() => this.year() - (((this.year() % 12) + 12) % 12), /* @ts-ignore */
199
+ ...(ngDevMode ? [{ debugName: "decadeStart" }] : /* istanbul ignore next */ []));
200
+ this.cells = computed(() => {
201
+ const t = this.t();
202
+ const locale = t.intlLocale;
203
+ const y = this.year();
204
+ const sm = this.startMonth();
205
+ const mk = (period, text) => {
206
+ const closed = touchesClosed(period, this.closedSet());
207
+ const outside = (!!this.min() && period.to < this.day(this.min())) || (!!this.max() && period.from > this.day(this.max()));
208
+ const label = this.labelOf(period) + (closed ? `, ${t.periodClosed}` : '');
209
+ return { period, text, label, closed, disabled: outside || (closed && this.disableClosed()) };
210
+ };
211
+ switch (this.mode()) {
212
+ case 'month': {
213
+ const fmt = new Intl.DateTimeFormat(locale, { month: 'short' });
214
+ return Array.from({ length: 12 }, (_, m) => mk(monthPeriod(y, m), fmt.format(new Date(y, m, 1)).replace('.', '')));
215
+ }
216
+ case 'quarter':
217
+ return [1, 2, 3, 4].map((q) => mk(quarterPeriod(y, q, sm), cbFormat(t.periodQuarterShort, q)));
218
+ case 'year': {
219
+ const start = this.decadeStart();
220
+ return Array.from({ length: 12 }, (_, i) => mk(fiscalYear(start + i, sm), String(start + i)));
221
+ }
222
+ }
223
+ }, /* @ts-ignore */
224
+ ...(ngDevMode ? [{ debugName: "cells" }] : /* istanbul ignore next */ []));
225
+ /** Celda con el foco (la elegida, la del periodo actual o la primera). */
226
+ this.focusIndex = linkedSignal(() => {
227
+ const cells = this.cells();
228
+ const selected = cells.findIndex((c) => c.period.key === this.value()?.key);
229
+ if (selected >= 0)
230
+ return selected;
231
+ const current = cells.findIndex((c) => this.isCurrent(c.period));
232
+ return current >= 0 ? current : 0;
233
+ }, /* @ts-ignore */
234
+ ...(ngDevMode ? [{ debugName: "focusIndex" }] : /* istanbul ignore next */ []));
235
+ this.navTitle = computed(() => {
236
+ if (this.mode() === 'year')
237
+ return `${this.decadeStart()} – ${this.decadeStart() + 11}`;
238
+ if (this.mode() === 'quarter' && this.startMonth() !== 0)
239
+ return cbFormat(this.t().periodFiscalYear, this.year());
240
+ return String(this.year());
241
+ }, /* @ts-ignore */
242
+ ...(ngDevMode ? [{ debugName: "navTitle" }] : /* istanbul ignore next */ []));
243
+ this.describedBy = computed(() => {
244
+ if (this.fieldState.invalid() && this.error())
245
+ return `${this.inputId()}-error`;
246
+ return this.hint() ? `${this.inputId()}-hint` : null;
247
+ }, /* @ts-ignore */
248
+ ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
249
+ this.onChange = () => { };
250
+ this.onTouched = () => { };
251
+ }
252
+ // --- ControlValueAccessor ----------------------------------------------------------------
253
+ writeValue(value) {
254
+ this.value.set(value ?? null);
255
+ if (value && value.kind !== 'range' && this.modes().includes(value.kind))
256
+ this.mode.set(value.kind);
257
+ }
258
+ registerOnChange(fn) {
259
+ this.onChange = fn;
260
+ }
261
+ registerOnTouched(fn) {
262
+ this.onTouched = fn;
263
+ }
264
+ setDisabledState(disabled) {
265
+ this.cvaDisabled.set(disabled);
266
+ }
267
+ // --- Textos ------------------------------------------------------------------------------
268
+ /** Nombre de un periodo: «Octubre de 2026», «T3 2026», «2026», «1 ene – 23 oct 2026». */
269
+ labelOf(period) {
270
+ const t = this.t();
271
+ const locale = t.intlLocale;
272
+ const cap = (s) => s.charAt(0).toLocaleUpperCase(locale) + s.slice(1);
273
+ switch (period.kind) {
274
+ case 'month':
275
+ return cap(new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(period.from));
276
+ case 'quarter': {
277
+ const [y, q] = period.key.split('-Q');
278
+ return cbFormat(this.startMonth() ? t.periodFiscalQuarter : t.periodQuarter, q, y);
279
+ }
280
+ case 'year':
281
+ return this.startMonth() ? cbFormat(t.periodFiscalYear, period.key) : period.key;
282
+ case 'range': {
283
+ const f = new Intl.DateTimeFormat(locale, { day: 'numeric', month: 'short', year: 'numeric' });
284
+ return `${f.format(period.from)} – ${f.format(period.to)}`.replace(/\./g, '');
285
+ }
286
+ }
287
+ }
288
+ modeLabel(mode) {
289
+ const t = this.t();
290
+ return mode === 'month' ? t.periodMonth : mode === 'quarter' ? t.periodQuarterTab : t.periodYear;
291
+ }
292
+ presetLabel(preset) {
293
+ const t = this.t();
294
+ const labels = {
295
+ thisMonth: t.periodThisMonth,
296
+ lastMonth: t.periodLastMonth,
297
+ thisQuarter: t.periodThisQuarter,
298
+ lastQuarter: t.periodLastQuarter,
299
+ yearToDate: t.periodYearToDate,
300
+ thisYear: t.periodThisYear,
301
+ lastYear: t.periodLastYear,
302
+ };
303
+ return labels[preset];
304
+ }
305
+ isClosed(period) {
306
+ return touchesClosed(period, this.closedSet());
307
+ }
308
+ isCurrent(period) {
309
+ const today = this.day(this.today());
310
+ return period.from <= today && today <= period.to;
311
+ }
312
+ isPresetActive(preset) {
313
+ return presetPeriod(preset, this.day(this.today()), this.startMonth()).key === this.value()?.key;
314
+ }
315
+ presetDisabled(preset) {
316
+ return this.disableClosed() && this.isClosed(presetPeriod(preset, this.day(this.today()), this.startMonth()));
317
+ }
318
+ // --- Interacción -------------------------------------------------------------------------
319
+ toggle() {
320
+ if (this.open())
321
+ this.close(false);
322
+ else
323
+ this.openPanel();
324
+ }
325
+ onTriggerKeydown(event) {
326
+ if ((event.key === 'ArrowDown' || event.key === 'ArrowUp') && !this.open()) {
327
+ event.preventDefault();
328
+ this.openPanel();
329
+ }
330
+ }
331
+ onOutsideClick(event) {
332
+ if (!this.trigger().nativeElement.contains(event.target))
333
+ this.close(false);
334
+ }
335
+ setMode(mode) {
336
+ this.mode.set(mode);
337
+ this.focusCell();
338
+ }
339
+ step(delta) {
340
+ this.year.update((y) => y + delta * (this.mode() === 'year' ? 12 : 1));
341
+ }
342
+ choose(cell) {
343
+ if (cell.disabled)
344
+ return;
345
+ this.setValue(cell.period);
346
+ this.close(true);
347
+ }
348
+ choosePreset(preset) {
349
+ this.setValue(presetPeriod(preset, this.day(this.today()), this.startMonth()));
350
+ this.close(true);
351
+ }
352
+ onGridKeydown(event) {
353
+ const cells = this.cells();
354
+ const i = this.focusIndex();
355
+ let next = null;
356
+ switch (event.key) {
357
+ case 'ArrowRight':
358
+ next = i + 1;
359
+ break;
360
+ case 'ArrowLeft':
361
+ next = i - 1;
362
+ break;
363
+ case 'ArrowDown':
364
+ next = i + COLS;
365
+ break;
366
+ case 'ArrowUp':
367
+ next = i - COLS;
368
+ break;
369
+ case 'Home':
370
+ next = 0;
371
+ break;
372
+ case 'End':
373
+ next = cells.length - 1;
374
+ break;
375
+ case 'PageUp':
376
+ case 'PageDown':
377
+ event.preventDefault();
378
+ this.step(event.key === 'PageUp' ? -1 : 1);
379
+ this.focusIndex.set(i);
380
+ this.focusCell();
381
+ return;
382
+ default:
383
+ return;
384
+ }
385
+ event.preventDefault();
386
+ // Al salir de la cuadrícula por un lado, pasa al año (o docena) vecino.
387
+ if (next < 0 || next >= cells.length) {
388
+ const dir = next < 0 ? -1 : 1;
389
+ this.step(dir);
390
+ this.focusIndex.set((next + cells.length) % cells.length);
391
+ }
392
+ else
393
+ this.focusIndex.set(next);
394
+ this.focusCell();
395
+ }
396
+ openPanel() {
397
+ if (this.isDisabled())
398
+ return;
399
+ this.open.set(true);
400
+ this.focusCell();
401
+ }
402
+ /** Cierra el panel (y devuelve el foco al botón si se cerró desde dentro). */
403
+ close(refocus) {
404
+ if (!this.open())
405
+ return;
406
+ this.open.set(false);
407
+ this.onTouched();
408
+ if (refocus)
409
+ this.trigger().nativeElement.focus();
410
+ }
411
+ focusCell() {
412
+ afterNextRender(() => {
413
+ const panel = this.trigger().nativeElement.ownerDocument.querySelector(`.cb-pp__panel [data-index="${this.focusIndex()}"]`);
414
+ panel?.focus();
415
+ }, { injector: this.injector });
416
+ }
417
+ setValue(period) {
418
+ this.value.set(period);
419
+ this.onChange(period);
420
+ this.periodChange.emit(period);
421
+ }
422
+ day(d) {
423
+ return new Date(d.getFullYear(), d.getMonth(), d.getDate());
424
+ }
425
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbPeriodPicker, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
426
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: CbPeriodPicker, isStandalone: true, selector: "cb-period-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, modes: { classPropertyName: "modes", publicName: "modes", isSignal: true, isRequired: false, transformFunction: null }, presets: { classPropertyName: "presets", publicName: "presets", isSignal: true, isRequired: false, transformFunction: null }, fiscalYearStart: { classPropertyName: "fiscalYearStart", publicName: "fiscalYearStart", isSignal: true, isRequired: false, transformFunction: null }, closed: { classPropertyName: "closed", publicName: "closed", isSignal: true, isRequired: false, transformFunction: null }, disableClosed: { classPropertyName: "disableClosed", publicName: "disableClosed", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, today: { classPropertyName: "today", publicName: "today", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, requiredIndicator: { classPropertyName: "requiredIndicator", publicName: "requiredIndicator", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", mode: "modeChange", periodChange: "periodChange" }, host: { classAttribute: "cb-period-picker-host" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CbPeriodPicker), multi: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, isSignal: true }], ngImport: i0, template: `
427
+ @if (label()) {
428
+ <label class="cb-pp__label" [attr.for]="inputId()">
429
+ {{ label() }}
430
+ @if (fieldState.indicator(); as mark) {
431
+ <span [class]="'cb-pp__required cb-pp__required--' + mark.kind" [attr.aria-hidden]="mark.kind === 'optional' ? null : 'true'">{{ mark.text }}</span>
432
+ }
433
+ </label>
434
+ }
435
+ <button
436
+ #trigger
437
+ type="button"
438
+ class="cb-pp"
439
+ [class]="'cb-pp--' + size()"
440
+ [class.cb-is-open]="open()"
441
+ [class.cb-is-invalid]="fieldState.invalid()"
442
+ [id]="inputId()"
443
+ [disabled]="isDisabled()"
444
+ aria-haspopup="dialog"
445
+ [attr.aria-expanded]="open()"
446
+ [attr.aria-invalid]="fieldState.invalid() ? 'true' : null"
447
+ [attr.aria-describedby]="describedBy()"
448
+ (click)="toggle()"
449
+ (keydown)="onTriggerKeydown($event)"
450
+ >
451
+ <cb-icon class="cb-pp__icon" name="calendar" [size]="16" aria-hidden="true" />
452
+ <span class="cb-pp__text" [class.cb-pp__text--empty]="!value()">{{ value() ? labelOf(value()!) : (placeholder() ?? t().periodPickerPlaceholder) }}</span>
453
+ @if (value() && isClosed(value()!)) {
454
+ <cb-icon class="cb-pp__lock" name="lock" [size]="14" aria-hidden="true" />
455
+ <span class="cb-pp__sr">{{ t().periodClosed }}</span>
456
+ }
457
+ <cb-icon class="cb-pp__caret" name="chevron-down" [size]="16" aria-hidden="true" />
458
+ </button>
459
+
460
+ <ng-template
461
+ cdkConnectedOverlay
462
+ [cdkConnectedOverlayOrigin]="trigger"
463
+ [cdkConnectedOverlayOpen]="open()"
464
+ [cdkConnectedOverlayPositions]="positions"
465
+ (overlayOutsideClick)="onOutsideClick($event)"
466
+ (detach)="close(false)"
467
+ >
468
+ <div class="cb-pp__panel" role="dialog" [attr.aria-label]="label() || t().periodPickerPlaceholder" (keydown.escape)="close(true)">
469
+ @if (presets().length) {
470
+ <div class="cb-pp__presets" role="group" [attr.aria-label]="t().periodPresets">
471
+ @for (p of presets(); track p) {
472
+ <button type="button" class="cb-pp__preset" [class.cb-is-active]="isPresetActive(p)" [disabled]="presetDisabled(p)" (click)="choosePreset(p)">{{ presetLabel(p) }}</button>
473
+ }
474
+ </div>
475
+ }
476
+ <div class="cb-pp__main">
477
+ @if (modes().length > 1) {
478
+ <div class="cb-pp__modes" role="group" [attr.aria-label]="t().periodKind">
479
+ @for (m of modes(); track m) {
480
+ <button type="button" class="cb-pp__mode" [attr.aria-pressed]="mode() === m" (click)="setMode(m)">{{ modeLabel(m) }}</button>
481
+ }
482
+ </div>
483
+ }
484
+ <div class="cb-pp__nav">
485
+ <button type="button" class="cb-pp__step" [attr.aria-label]="mode() === 'year' ? t().periodPrevYears : t().periodPrevYear" (click)="step(-1)">
486
+ <cb-icon name="chevron-left" [size]="16" aria-hidden="true" />
487
+ </button>
488
+ <span class="cb-pp__title" aria-live="polite">{{ navTitle() }}</span>
489
+ <button type="button" class="cb-pp__step" [attr.aria-label]="mode() === 'year' ? t().periodNextYears : t().periodNextYear" (click)="step(1)">
490
+ <cb-icon name="chevron-right" [size]="16" aria-hidden="true" />
491
+ </button>
492
+ </div>
493
+ <div class="cb-pp__grid" [class.cb-pp__grid--quarters]="mode() === 'quarter'" role="group" [attr.aria-label]="navTitle()" (keydown)="onGridKeydown($event)">
494
+ @for (cell of cells(); track cell.period.key; let i = $index) {
495
+ <button
496
+ type="button"
497
+ class="cb-pp__cell"
498
+ [attr.data-index]="i"
499
+ [class.cb-is-selected]="cell.period.key === value()?.key"
500
+ [class.cb-is-current]="isCurrent(cell.period)"
501
+ [class.cb-pp__cell--closed]="cell.closed"
502
+ [attr.tabindex]="i === focusIndex() ? 0 : -1"
503
+ [attr.aria-pressed]="cell.period.key === value()?.key"
504
+ [attr.aria-disabled]="cell.disabled || null"
505
+ [attr.aria-label]="cell.label"
506
+ (click)="choose(cell)"
507
+ >
508
+ {{ cell.text }}
509
+ @if (cell.closed) {
510
+ <cb-icon class="cb-pp__cell-lock" name="lock" [size]="11" aria-hidden="true" />
511
+ }
512
+ </button>
513
+ }
514
+ </div>
515
+ </div>
516
+ </div>
517
+ </ng-template>
518
+
519
+ @if (fieldState.invalid() && error()) {
520
+ <p class="cb-pp__message cb-pp__message--error" [id]="inputId() + '-error'" role="alert">{{ error() }}</p>
521
+ } @else if (hint()) {
522
+ <p class="cb-pp__message" [id]="inputId() + '-hint'">{{ hint() }}</p>
523
+ }
524
+ `, isInline: true, styles: [":host{display:block;font-family:var(--cb-font-sans)}.cb-pp__label{display:block;margin-bottom:var(--cb-space-1);color:var(--cb-color-text);font-size:var(--cb-text-sm);font-weight:var(--cb-font-weight-medium)}.cb-pp__required{margin-left:2px;color:var(--cb-color-danger)}.cb-pp{display:flex;align-items:center;gap:.5rem;box-sizing:border-box;width:100%;padding:0 var(--cb-space-3);border:var(--cb-border-width) solid var(--cb-color-border-strong);border-radius:var(--cb-radius-md);background:var(--cb-color-bg);color:var(--cb-color-text);font:inherit;font-size:var(--cb-text-base);text-align:start;cursor:pointer;transition:border-color var(--cb-duration-fast) var(--cb-ease),box-shadow var(--cb-duration-fast) var(--cb-ease)}.cb-pp--sm{min-height:2rem;font-size:var(--cb-text-sm)}.cb-pp--md{min-height:2.5rem}.cb-pp--lg{min-height:3rem;font-size:var(--cb-text-lg)}.cb-pp:hover:not(:disabled){border-color:var(--cb-color-text-muted)}.cb-pp:focus-visible,.cb-pp.cb-is-open{outline:none;border-color:var(--cb-color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--cb-color-primary-500) 25%,transparent)}.cb-pp.cb-is-invalid{border-color:var(--cb-color-danger)}.cb-pp:disabled{background:var(--cb-color-surface);opacity:.8;cursor:not-allowed}.cb-pp__icon,.cb-pp__caret,.cb-pp__lock{flex:none;color:var(--cb-color-text-muted)}.cb-pp__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cb-pp__text--empty{color:var(--cb-color-text-muted)}.cb-pp__panel{display:flex;gap:var(--cb-space-3);padding:var(--cb-space-3);border:1px solid var(--cb-color-border);border-radius:var(--cb-radius-md);background:var(--cb-color-surface-raised);box-shadow:var(--cb-shadow-md);color:var(--cb-color-text);font-family:var(--cb-font-sans);font-size:var(--cb-text-sm)}.cb-pp__presets{display:grid;align-content:start;gap:2px;min-width:9.5rem;padding-right:var(--cb-space-3);border-right:1px solid var(--cb-color-border)}.cb-pp__preset,.cb-pp__mode,.cb-pp__step,.cb-pp__cell{border:0;background:transparent;color:inherit;font:inherit;cursor:pointer}.cb-pp__preset{padding:.4rem .6rem;border-radius:var(--cb-radius-sm, 4px);text-align:start;white-space:nowrap}.cb-pp__preset:hover:not(:disabled),.cb-pp__step:hover,.cb-pp__cell:hover:not([aria-disabled=true]){background:var(--cb-color-surface-hover)}.cb-pp__preset.cb-is-active{color:var(--cb-color-primary-text, var(--cb-color-primary-700));font-weight:var(--cb-font-weight-semibold, 600)}.cb-pp__preset:disabled{opacity:.45;cursor:not-allowed}.cb-pp__main{display:grid;gap:var(--cb-space-2);min-width:15rem}.cb-pp__modes{display:flex;padding:2px;border-radius:var(--cb-radius-md);background:var(--cb-color-surface-subtle)}.cb-pp__mode{flex:1;padding:.3rem .5rem;border-radius:var(--cb-radius-sm, 4px);color:var(--cb-color-text-muted)}.cb-pp__mode[aria-pressed=true]{background:var(--cb-color-bg);box-shadow:var(--cb-shadow-sm, 0 1px 2px rgb(0 0 0 / .08));color:var(--cb-color-text);font-weight:var(--cb-font-weight-medium, 500)}.cb-pp__nav{display:flex;align-items:center;justify-content:space-between}.cb-pp__step{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:var(--cb-radius-sm, 4px)}.cb-pp__title{font-weight:var(--cb-font-weight-semibold, 600)}.cb-pp__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:4px}.cb-pp__cell{position:relative;min-height:2.25rem;padding:.35rem .25rem;border-radius:var(--cb-radius-sm, 4px);text-transform:capitalize}.cb-pp__cell.cb-is-current{box-shadow:inset 0 0 0 1px var(--cb-color-primary-500)}.cb-pp__cell.cb-is-selected{background:var(--cb-color-primary-500);color:var(--cb-color-primary-contrast, #fff);font-weight:var(--cb-font-weight-semibold, 600)}.cb-pp__cell--closed:not(.cb-is-selected){color:var(--cb-color-text-muted)}.cb-pp__cell[aria-disabled=true]{opacity:.4;cursor:not-allowed}.cb-pp__cell-lock{position:absolute;top:3px;right:3px}:is(.cb-pp__preset,.cb-pp__mode,.cb-pp__step,.cb-pp__cell):focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:1px}.cb-pp__message{margin:var(--cb-space-1) 0 0;color:var(--cb-color-text-muted);font-size:var(--cb-text-xs)}.cb-pp__message--error{color:var(--cb-color-danger)}.cb-pp__sr{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}@media(max-width:30rem){.cb-pp__panel{flex-direction:column}.cb-pp__presets{grid-template-columns:1fr 1fr;padding:0 0 var(--cb-space-3);border-right:0;border-bottom:1px solid var(--cb-color-border)}}\n"], dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "component", type: CbIcon, selector: "cb-icon", inputs: ["name", "size", "spin", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
525
+ }
526
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: CbPeriodPicker, decorators: [{
527
+ type: Component,
528
+ args: [{ selector: 'cb-period-picker', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, imports: [OverlayModule, CbIcon], host: { class: 'cb-period-picker-host' }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CbPeriodPicker), multi: true }], template: `
529
+ @if (label()) {
530
+ <label class="cb-pp__label" [attr.for]="inputId()">
531
+ {{ label() }}
532
+ @if (fieldState.indicator(); as mark) {
533
+ <span [class]="'cb-pp__required cb-pp__required--' + mark.kind" [attr.aria-hidden]="mark.kind === 'optional' ? null : 'true'">{{ mark.text }}</span>
534
+ }
535
+ </label>
536
+ }
537
+ <button
538
+ #trigger
539
+ type="button"
540
+ class="cb-pp"
541
+ [class]="'cb-pp--' + size()"
542
+ [class.cb-is-open]="open()"
543
+ [class.cb-is-invalid]="fieldState.invalid()"
544
+ [id]="inputId()"
545
+ [disabled]="isDisabled()"
546
+ aria-haspopup="dialog"
547
+ [attr.aria-expanded]="open()"
548
+ [attr.aria-invalid]="fieldState.invalid() ? 'true' : null"
549
+ [attr.aria-describedby]="describedBy()"
550
+ (click)="toggle()"
551
+ (keydown)="onTriggerKeydown($event)"
552
+ >
553
+ <cb-icon class="cb-pp__icon" name="calendar" [size]="16" aria-hidden="true" />
554
+ <span class="cb-pp__text" [class.cb-pp__text--empty]="!value()">{{ value() ? labelOf(value()!) : (placeholder() ?? t().periodPickerPlaceholder) }}</span>
555
+ @if (value() && isClosed(value()!)) {
556
+ <cb-icon class="cb-pp__lock" name="lock" [size]="14" aria-hidden="true" />
557
+ <span class="cb-pp__sr">{{ t().periodClosed }}</span>
558
+ }
559
+ <cb-icon class="cb-pp__caret" name="chevron-down" [size]="16" aria-hidden="true" />
560
+ </button>
561
+
562
+ <ng-template
563
+ cdkConnectedOverlay
564
+ [cdkConnectedOverlayOrigin]="trigger"
565
+ [cdkConnectedOverlayOpen]="open()"
566
+ [cdkConnectedOverlayPositions]="positions"
567
+ (overlayOutsideClick)="onOutsideClick($event)"
568
+ (detach)="close(false)"
569
+ >
570
+ <div class="cb-pp__panel" role="dialog" [attr.aria-label]="label() || t().periodPickerPlaceholder" (keydown.escape)="close(true)">
571
+ @if (presets().length) {
572
+ <div class="cb-pp__presets" role="group" [attr.aria-label]="t().periodPresets">
573
+ @for (p of presets(); track p) {
574
+ <button type="button" class="cb-pp__preset" [class.cb-is-active]="isPresetActive(p)" [disabled]="presetDisabled(p)" (click)="choosePreset(p)">{{ presetLabel(p) }}</button>
575
+ }
576
+ </div>
577
+ }
578
+ <div class="cb-pp__main">
579
+ @if (modes().length > 1) {
580
+ <div class="cb-pp__modes" role="group" [attr.aria-label]="t().periodKind">
581
+ @for (m of modes(); track m) {
582
+ <button type="button" class="cb-pp__mode" [attr.aria-pressed]="mode() === m" (click)="setMode(m)">{{ modeLabel(m) }}</button>
583
+ }
584
+ </div>
585
+ }
586
+ <div class="cb-pp__nav">
587
+ <button type="button" class="cb-pp__step" [attr.aria-label]="mode() === 'year' ? t().periodPrevYears : t().periodPrevYear" (click)="step(-1)">
588
+ <cb-icon name="chevron-left" [size]="16" aria-hidden="true" />
589
+ </button>
590
+ <span class="cb-pp__title" aria-live="polite">{{ navTitle() }}</span>
591
+ <button type="button" class="cb-pp__step" [attr.aria-label]="mode() === 'year' ? t().periodNextYears : t().periodNextYear" (click)="step(1)">
592
+ <cb-icon name="chevron-right" [size]="16" aria-hidden="true" />
593
+ </button>
594
+ </div>
595
+ <div class="cb-pp__grid" [class.cb-pp__grid--quarters]="mode() === 'quarter'" role="group" [attr.aria-label]="navTitle()" (keydown)="onGridKeydown($event)">
596
+ @for (cell of cells(); track cell.period.key; let i = $index) {
597
+ <button
598
+ type="button"
599
+ class="cb-pp__cell"
600
+ [attr.data-index]="i"
601
+ [class.cb-is-selected]="cell.period.key === value()?.key"
602
+ [class.cb-is-current]="isCurrent(cell.period)"
603
+ [class.cb-pp__cell--closed]="cell.closed"
604
+ [attr.tabindex]="i === focusIndex() ? 0 : -1"
605
+ [attr.aria-pressed]="cell.period.key === value()?.key"
606
+ [attr.aria-disabled]="cell.disabled || null"
607
+ [attr.aria-label]="cell.label"
608
+ (click)="choose(cell)"
609
+ >
610
+ {{ cell.text }}
611
+ @if (cell.closed) {
612
+ <cb-icon class="cb-pp__cell-lock" name="lock" [size]="11" aria-hidden="true" />
613
+ }
614
+ </button>
615
+ }
616
+ </div>
617
+ </div>
618
+ </div>
619
+ </ng-template>
620
+
621
+ @if (fieldState.invalid() && error()) {
622
+ <p class="cb-pp__message cb-pp__message--error" [id]="inputId() + '-error'" role="alert">{{ error() }}</p>
623
+ } @else if (hint()) {
624
+ <p class="cb-pp__message" [id]="inputId() + '-hint'">{{ hint() }}</p>
625
+ }
626
+ `, styles: [":host{display:block;font-family:var(--cb-font-sans)}.cb-pp__label{display:block;margin-bottom:var(--cb-space-1);color:var(--cb-color-text);font-size:var(--cb-text-sm);font-weight:var(--cb-font-weight-medium)}.cb-pp__required{margin-left:2px;color:var(--cb-color-danger)}.cb-pp{display:flex;align-items:center;gap:.5rem;box-sizing:border-box;width:100%;padding:0 var(--cb-space-3);border:var(--cb-border-width) solid var(--cb-color-border-strong);border-radius:var(--cb-radius-md);background:var(--cb-color-bg);color:var(--cb-color-text);font:inherit;font-size:var(--cb-text-base);text-align:start;cursor:pointer;transition:border-color var(--cb-duration-fast) var(--cb-ease),box-shadow var(--cb-duration-fast) var(--cb-ease)}.cb-pp--sm{min-height:2rem;font-size:var(--cb-text-sm)}.cb-pp--md{min-height:2.5rem}.cb-pp--lg{min-height:3rem;font-size:var(--cb-text-lg)}.cb-pp:hover:not(:disabled){border-color:var(--cb-color-text-muted)}.cb-pp:focus-visible,.cb-pp.cb-is-open{outline:none;border-color:var(--cb-color-primary-500);box-shadow:0 0 0 3px color-mix(in srgb,var(--cb-color-primary-500) 25%,transparent)}.cb-pp.cb-is-invalid{border-color:var(--cb-color-danger)}.cb-pp:disabled{background:var(--cb-color-surface);opacity:.8;cursor:not-allowed}.cb-pp__icon,.cb-pp__caret,.cb-pp__lock{flex:none;color:var(--cb-color-text-muted)}.cb-pp__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cb-pp__text--empty{color:var(--cb-color-text-muted)}.cb-pp__panel{display:flex;gap:var(--cb-space-3);padding:var(--cb-space-3);border:1px solid var(--cb-color-border);border-radius:var(--cb-radius-md);background:var(--cb-color-surface-raised);box-shadow:var(--cb-shadow-md);color:var(--cb-color-text);font-family:var(--cb-font-sans);font-size:var(--cb-text-sm)}.cb-pp__presets{display:grid;align-content:start;gap:2px;min-width:9.5rem;padding-right:var(--cb-space-3);border-right:1px solid var(--cb-color-border)}.cb-pp__preset,.cb-pp__mode,.cb-pp__step,.cb-pp__cell{border:0;background:transparent;color:inherit;font:inherit;cursor:pointer}.cb-pp__preset{padding:.4rem .6rem;border-radius:var(--cb-radius-sm, 4px);text-align:start;white-space:nowrap}.cb-pp__preset:hover:not(:disabled),.cb-pp__step:hover,.cb-pp__cell:hover:not([aria-disabled=true]){background:var(--cb-color-surface-hover)}.cb-pp__preset.cb-is-active{color:var(--cb-color-primary-text, var(--cb-color-primary-700));font-weight:var(--cb-font-weight-semibold, 600)}.cb-pp__preset:disabled{opacity:.45;cursor:not-allowed}.cb-pp__main{display:grid;gap:var(--cb-space-2);min-width:15rem}.cb-pp__modes{display:flex;padding:2px;border-radius:var(--cb-radius-md);background:var(--cb-color-surface-subtle)}.cb-pp__mode{flex:1;padding:.3rem .5rem;border-radius:var(--cb-radius-sm, 4px);color:var(--cb-color-text-muted)}.cb-pp__mode[aria-pressed=true]{background:var(--cb-color-bg);box-shadow:var(--cb-shadow-sm, 0 1px 2px rgb(0 0 0 / .08));color:var(--cb-color-text);font-weight:var(--cb-font-weight-medium, 500)}.cb-pp__nav{display:flex;align-items:center;justify-content:space-between}.cb-pp__step{display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;border-radius:var(--cb-radius-sm, 4px)}.cb-pp__title{font-weight:var(--cb-font-weight-semibold, 600)}.cb-pp__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:4px}.cb-pp__cell{position:relative;min-height:2.25rem;padding:.35rem .25rem;border-radius:var(--cb-radius-sm, 4px);text-transform:capitalize}.cb-pp__cell.cb-is-current{box-shadow:inset 0 0 0 1px var(--cb-color-primary-500)}.cb-pp__cell.cb-is-selected{background:var(--cb-color-primary-500);color:var(--cb-color-primary-contrast, #fff);font-weight:var(--cb-font-weight-semibold, 600)}.cb-pp__cell--closed:not(.cb-is-selected){color:var(--cb-color-text-muted)}.cb-pp__cell[aria-disabled=true]{opacity:.4;cursor:not-allowed}.cb-pp__cell-lock{position:absolute;top:3px;right:3px}:is(.cb-pp__preset,.cb-pp__mode,.cb-pp__step,.cb-pp__cell):focus-visible{outline:2px solid var(--cb-color-focus-ring);outline-offset:1px}.cb-pp__message{margin:var(--cb-space-1) 0 0;color:var(--cb-color-text-muted);font-size:var(--cb-text-xs)}.cb-pp__message--error{color:var(--cb-color-danger)}.cb-pp__sr{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}@media(max-width:30rem){.cb-pp__panel{flex-direction:column}.cb-pp__presets{grid-template-columns:1fr 1fr;padding:0 0 var(--cb-space-3);border-right:0;border-bottom:1px solid var(--cb-color-border)}}\n"] }]
627
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }, { type: i0.Output, args: ["modeChange"] }], modes: [{ type: i0.Input, args: [{ isSignal: true, alias: "modes", required: false }] }], presets: [{ type: i0.Input, args: [{ isSignal: true, alias: "presets", required: false }] }], fiscalYearStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "fiscalYearStart", required: false }] }], closed: [{ type: i0.Input, args: [{ isSignal: true, alias: "closed", required: false }] }], disableClosed: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableClosed", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], today: [{ type: i0.Input, args: [{ isSignal: true, alias: "today", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], requiredIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "requiredIndicator", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], periodChange: [{ type: i0.Output, args: ["periodChange"] }], trigger: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }] } });
628
+
629
+ /*
630
+ * Public API Surface de @caribeng/ui/period-picker
631
+ */
632
+
633
+ /**
634
+ * Generated bundle index. Do not edit.
635
+ */
636
+
637
+ export { CbPeriodPicker, fiscalYear, fiscalYearOf, monthPeriod, monthsOf, periodFromKey, presetPeriod, quarterOf, quarterPeriod, rangePeriod };