cerxos-ui 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, EventEmitter, Output, Input, ChangeDetectionStrategy, Attribute, forwardRef, Directive, ContentChildren, ViewChild, HostListener, ElementRef, ViewChildren } from '@angular/core';
2
+ import { Component, EventEmitter, ElementRef, HostListener, ViewChildren, ViewChild, Output, Input, ChangeDetectionStrategy, Attribute, forwardRef, Directive, ContentChildren, ContentChild } from '@angular/core';
3
3
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
- import { NgTemplateOutlet, NgIf } from '@angular/common';
4
+ import * as i1 from '@angular/common';
5
+ import { NgTemplateOutlet, CommonModule, NgIf } from '@angular/common';
5
6
 
6
7
  class CerxosUi {
7
8
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CerxosUi, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -20,9 +21,196 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
20
21
  ` }]
21
22
  }] });
22
23
 
24
+ const TRIGGER_BASE_CLASSES = 'inline-flex items-center justify-center rounded-[var(--cxs-radius-md)] p-1.5 ' +
25
+ 'text-[var(--cxs-color-on-surface-muted)] transition-colors ' +
26
+ 'hover:bg-[var(--cxs-color-surface-hover)] hover:text-[var(--cxs-color-on-surface)] ' +
27
+ 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
28
+ 'focus-visible:outline-[var(--cxs-color-focus)]';
29
+ const TRIGGER_DISABLED_CLASSES = 'pointer-events-none opacity-60';
30
+ const MENU_BASE_CLASSES = 'absolute z-40 mt-2 min-w-[10rem] rounded-[var(--cxs-radius-md)] ' +
31
+ 'border border-[var(--cxs-color-border)] bg-[var(--cxs-color-surface)] py-1 ' +
32
+ 'shadow-[var(--cxs-shadow-sm)]';
33
+ const MENU_ALIGN_CLASSES = {
34
+ start: 'left-0 origin-top-left',
35
+ end: 'right-0 origin-top-right'
36
+ };
37
+ const ITEM_BASE_CLASSES$1 = 'flex w-full items-center gap-2 rounded-[var(--cxs-radius-sm)] px-3 py-2 text-left text-sm ' +
38
+ 'transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
39
+ 'focus-visible:outline-[var(--cxs-color-focus)]';
40
+ const ITEM_DEFAULT_CLASSES = 'text-[var(--cxs-color-on-surface)] hover:bg-[var(--cxs-color-surface-hover)]';
41
+ const ITEM_DANGER_CLASSES = 'text-[var(--cxs-color-danger)] hover:bg-[var(--cxs-color-surface-hover)]';
42
+ const ITEM_DISABLED_CLASSES$1 = 'pointer-events-none opacity-60';
43
+ const EMPTY_STATE_CLASSES$1 = 'block px-3 py-2 text-sm text-[var(--cxs-color-on-surface-muted)]';
44
+ class CxsActionMenuComponent {
45
+ elementRef;
46
+ static nextId = 0;
47
+ items = [];
48
+ align = 'end';
49
+ ariaLabel = 'Open actions menu';
50
+ menuLabel = 'Actions';
51
+ disabled = false;
52
+ itemSelected = new EventEmitter();
53
+ trigger;
54
+ menuItems;
55
+ menuId = `cxs-action-menu-${CxsActionMenuComponent.nextId++}`;
56
+ isOpen = false;
57
+ constructor(elementRef) {
58
+ this.elementRef = elementRef;
59
+ }
60
+ get triggerClass() {
61
+ return [TRIGGER_BASE_CLASSES, this.disabled ? TRIGGER_DISABLED_CLASSES : ''].filter(Boolean).join(' ');
62
+ }
63
+ get menuClass() {
64
+ return [MENU_BASE_CLASSES, MENU_ALIGN_CLASSES[this.align]].join(' ');
65
+ }
66
+ get emptyStateClass() {
67
+ return EMPTY_STATE_CLASSES$1;
68
+ }
69
+ isItemDisabled(item) {
70
+ return this.disabled || !!item.disabled;
71
+ }
72
+ getItemClass(item) {
73
+ return [
74
+ ITEM_BASE_CLASSES$1,
75
+ item.tone === 'danger' ? ITEM_DANGER_CLASSES : ITEM_DEFAULT_CLASSES,
76
+ this.isItemDisabled(item) ? ITEM_DISABLED_CLASSES$1 : ''
77
+ ]
78
+ .filter(Boolean)
79
+ .join(' ');
80
+ }
81
+ toggle() {
82
+ if (this.isOpen) {
83
+ this.close();
84
+ }
85
+ else {
86
+ this.open();
87
+ }
88
+ }
89
+ open() {
90
+ if (this.disabled) {
91
+ return;
92
+ }
93
+ this.isOpen = true;
94
+ this.focusFirstItem();
95
+ }
96
+ close() {
97
+ this.isOpen = false;
98
+ }
99
+ onTriggerKeydown(event) {
100
+ if (this.disabled) {
101
+ return;
102
+ }
103
+ if (event.key === 'Enter' || event.key === ' ') {
104
+ event.preventDefault();
105
+ this.toggle();
106
+ return;
107
+ }
108
+ if (event.key === 'ArrowDown') {
109
+ event.preventDefault();
110
+ this.open();
111
+ }
112
+ }
113
+ onMenuKeydown(event) {
114
+ if (typeof document === 'undefined') {
115
+ return;
116
+ }
117
+ if (event.key === 'Escape') {
118
+ event.preventDefault();
119
+ this.close();
120
+ this.focusTrigger();
121
+ return;
122
+ }
123
+ const items = this.getFocusableItems();
124
+ if (!items.length) {
125
+ return;
126
+ }
127
+ const currentIndex = items.findIndex((item) => item === document.activeElement);
128
+ let nextIndex = currentIndex;
129
+ switch (event.key) {
130
+ case 'ArrowDown':
131
+ nextIndex = currentIndex >= 0 ? (currentIndex + 1) % items.length : 0;
132
+ break;
133
+ case 'ArrowUp':
134
+ nextIndex = currentIndex >= 0 ? (currentIndex - 1 + items.length) % items.length : items.length - 1;
135
+ break;
136
+ case 'Home':
137
+ nextIndex = 0;
138
+ break;
139
+ case 'End':
140
+ nextIndex = items.length - 1;
141
+ break;
142
+ default:
143
+ return;
144
+ }
145
+ event.preventDefault();
146
+ items[nextIndex]?.focus();
147
+ }
148
+ onItemClick(item) {
149
+ if (this.isItemDisabled(item)) {
150
+ return;
151
+ }
152
+ this.itemSelected.emit(item);
153
+ this.close();
154
+ this.focusTrigger();
155
+ }
156
+ onDocumentClick(event) {
157
+ if (!this.isOpen) {
158
+ return;
159
+ }
160
+ const target = event.target;
161
+ if (target && !this.elementRef.nativeElement.contains(target)) {
162
+ this.close();
163
+ }
164
+ }
165
+ focusFirstItem() {
166
+ if (typeof document === 'undefined') {
167
+ return;
168
+ }
169
+ setTimeout(() => {
170
+ const items = this.getFocusableItems();
171
+ items[0]?.focus();
172
+ }, 0);
173
+ }
174
+ focusTrigger() {
175
+ this.trigger?.nativeElement.focus();
176
+ }
177
+ getFocusableItems() {
178
+ return (this.menuItems?.toArray() ?? [])
179
+ .map((item) => item.nativeElement)
180
+ .filter((item) => !item.hasAttribute('disabled') && !item.hasAttribute('data-disabled'));
181
+ }
182
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsActionMenuComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
183
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsActionMenuComponent, isStandalone: true, selector: "cxs-action-menu", inputs: { items: "items", align: "align", ariaLabel: "ariaLabel", menuLabel: "menuLabel", disabled: "disabled" }, outputs: { itemSelected: "itemSelected" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true, read: ElementRef }, { propertyName: "menuItems", predicate: ["menuItem"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"relative inline-flex\">\n <button\n #trigger\n type=\"button\"\n [class]=\"triggerClass\"\n aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-controls]=\"menuId\"\n [attr.aria-label]=\"ariaLabel\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n <svg class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <circle cx=\"4\" cy=\"10\" r=\"1.5\"></circle>\n <circle cx=\"10\" cy=\"10\" r=\"1.5\"></circle>\n <circle cx=\"16\" cy=\"10\" r=\"1.5\"></circle>\n </svg>\n </button>\n\n @if (isOpen) {\n <div\n [class]=\"menuClass\"\n [attr.id]=\"menuId\"\n role=\"menu\"\n [attr.aria-label]=\"menuLabel\"\n (keydown)=\"onMenuKeydown($event)\"\n >\n @if (items.length) {\n @for (item of items; track item.value) {\n <button\n #menuItem\n type=\"button\"\n role=\"menuitem\"\n [class]=\"getItemClass(item)\"\n [attr.data-disabled]=\"isItemDisabled(item) ? '' : null\"\n [attr.aria-disabled]=\"isItemDisabled(item) ? 'true' : null\"\n [disabled]=\"isItemDisabled(item)\"\n (click)=\"onItemClick(item)\"\n >\n {{ item.label }}\n </button>\n }\n } @else {\n <span [class]=\"emptyStateClass\">No actions</span>\n }\n </div>\n }\n</div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
184
+ }
185
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsActionMenuComponent, decorators: [{
186
+ type: Component,
187
+ args: [{ selector: 'cxs-action-menu', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"relative inline-flex\">\n <button\n #trigger\n type=\"button\"\n [class]=\"triggerClass\"\n aria-haspopup=\"menu\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-controls]=\"menuId\"\n [attr.aria-label]=\"ariaLabel\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n >\n <svg class=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <circle cx=\"4\" cy=\"10\" r=\"1.5\"></circle>\n <circle cx=\"10\" cy=\"10\" r=\"1.5\"></circle>\n <circle cx=\"16\" cy=\"10\" r=\"1.5\"></circle>\n </svg>\n </button>\n\n @if (isOpen) {\n <div\n [class]=\"menuClass\"\n [attr.id]=\"menuId\"\n role=\"menu\"\n [attr.aria-label]=\"menuLabel\"\n (keydown)=\"onMenuKeydown($event)\"\n >\n @if (items.length) {\n @for (item of items; track item.value) {\n <button\n #menuItem\n type=\"button\"\n role=\"menuitem\"\n [class]=\"getItemClass(item)\"\n [attr.data-disabled]=\"isItemDisabled(item) ? '' : null\"\n [attr.aria-disabled]=\"isItemDisabled(item) ? 'true' : null\"\n [disabled]=\"isItemDisabled(item)\"\n (click)=\"onItemClick(item)\"\n >\n {{ item.label }}\n </button>\n }\n } @else {\n <span [class]=\"emptyStateClass\">No actions</span>\n }\n </div>\n }\n</div>\n" }]
188
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { items: [{
189
+ type: Input
190
+ }], align: [{
191
+ type: Input
192
+ }], ariaLabel: [{
193
+ type: Input
194
+ }], menuLabel: [{
195
+ type: Input
196
+ }], disabled: [{
197
+ type: Input
198
+ }], itemSelected: [{
199
+ type: Output
200
+ }], trigger: [{
201
+ type: ViewChild,
202
+ args: ['trigger', { read: ElementRef }]
203
+ }], menuItems: [{
204
+ type: ViewChildren,
205
+ args: ['menuItem', { read: ElementRef }]
206
+ }], onDocumentClick: [{
207
+ type: HostListener,
208
+ args: ['document:click', ['$event']]
209
+ }] } });
210
+
23
211
  const BASE_CLASSES$a = 'relative flex w-full gap-3 rounded-[var(--cxs-radius-md)] border border-l-4 px-4 py-3 text-sm ' +
24
212
  'text-[var(--cxs-color-on-surface)]';
25
- const VARIANT_CLASSES$7 = {
213
+ const VARIANT_CLASSES$8 = {
26
214
  info: 'border-[var(--cxs-color-primary)] border-l-[var(--cxs-color-primary)] ' +
27
215
  'bg-[var(--cxs-color-primary-ghost)]',
28
216
  neutral: 'border-[var(--cxs-color-border)] border-l-[var(--cxs-color-border)] ' +
@@ -47,7 +235,7 @@ class CxsAlertComponent {
47
235
  closed = new EventEmitter();
48
236
  isVisible = true;
49
237
  get alertClass() {
50
- return [BASE_CLASSES$a, VARIANT_CLASSES$7[this.variant]].join(' ');
238
+ return [BASE_CLASSES$a, VARIANT_CLASSES$8[this.variant]].join(' ');
51
239
  }
52
240
  get titleClass() {
53
241
  return [TITLE_BASE, TITLE_VARIANT[this.variant]].join(' ');
@@ -174,7 +362,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
174
362
 
175
363
  const BASE_CLASSES$8 = 'inline-flex items-center gap-1 rounded-[var(--cxs-radius-md)] border px-2.5 py-0.5 text-xs font-medium ' +
176
364
  'leading-none';
177
- const VARIANT_CLASSES$6 = {
365
+ const VARIANT_CLASSES$7 = {
178
366
  primary: 'border-[var(--cxs-color-primary)] bg-[var(--cxs-color-primary-ghost)] ' +
179
367
  'text-[var(--cxs-color-primary)]',
180
368
  neutral: 'border-[var(--cxs-color-border)] bg-[var(--cxs-color-surface)] ' +
@@ -190,7 +378,7 @@ class CxsBadgeComponent {
190
378
  variant = 'primary';
191
379
  size = 'md';
192
380
  get badgeClass() {
193
- return [BASE_CLASSES$8, VARIANT_CLASSES$6[this.variant], SIZE_CLASSES$7[this.size]].join(' ');
381
+ return [BASE_CLASSES$8, VARIANT_CLASSES$7[this.variant], SIZE_CLASSES$7[this.size]].join(' ');
194
382
  }
195
383
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
196
384
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: CxsBadgeComponent, isStandalone: true, selector: "cxs-badge", inputs: { variant: "variant", size: "size" }, ngImport: i0, template: "<span [class]=\"badgeClass\">\r\n <ng-content></ng-content>\r\n</span>\r\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
@@ -399,7 +587,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
399
587
  const BASE_CLASSES$5 = 'relative inline-flex items-center justify-center gap-2 whitespace-nowrap font-medium transition-colors ' +
400
588
  'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
401
589
  'focus-visible:outline-[var(--cxs-color-focus)] disabled:pointer-events-none disabled:opacity-50';
402
- const VARIANT_CLASSES$5 = {
590
+ const VARIANT_CLASSES$6 = {
403
591
  primary: 'bg-[var(--cxs-color-primary)] text-[var(--cxs-color-on-primary)] ' +
404
592
  'hover:bg-[var(--cxs-color-primary-hover)] shadow-[var(--cxs-shadow-sm)]',
405
593
  secondary: 'bg-[var(--cxs-color-surface)] text-[var(--cxs-color-on-surface)] ' +
@@ -425,7 +613,7 @@ class CxsButtonComponent {
425
613
  return this.disabled || this.loading;
426
614
  }
427
615
  get buttonClass() {
428
- return [BASE_CLASSES$5, SIZE_CLASSES$4[this.size], VARIANT_CLASSES$5[this.variant], this.hostClass]
616
+ return [BASE_CLASSES$5, SIZE_CLASSES$4[this.size], VARIANT_CLASSES$6[this.variant], this.hostClass]
429
617
  .filter(Boolean)
430
618
  .join(' ');
431
619
  }
@@ -452,7 +640,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
452
640
 
453
641
  const BASE_CLASSES$4 = 'rounded-[var(--cxs-radius-md)] border border-[var(--cxs-color-border)] ' +
454
642
  'bg-[var(--cxs-color-surface)] text-[var(--cxs-color-on-surface)]';
455
- const VARIANT_CLASSES$4 = {
643
+ const VARIANT_CLASSES$5 = {
456
644
  surface: 'bg-[var(--cxs-color-surface)]',
457
645
  muted: 'bg-[var(--cxs-color-surface-hover)]',
458
646
  outline: 'bg-transparent'
@@ -471,7 +659,7 @@ class CxsCardComponent {
471
659
  get cardClass() {
472
660
  return [
473
661
  BASE_CLASSES$4,
474
- VARIANT_CLASSES$4[this.variant],
662
+ VARIANT_CLASSES$5[this.variant],
475
663
  SIZE_CLASSES$3[this.size],
476
664
  this.elevated ? 'shadow-[var(--cxs-shadow-sm)]' : ''
477
665
  ]
@@ -501,7 +689,7 @@ const WRAPPER_ENABLED$1 = 'cursor-pointer';
501
689
  const WRAPPER_DISABLED$1 = 'cursor-not-allowed opacity-60';
502
690
  const LABEL_BASE$1 = 'text-[var(--cxs-color-on-surface)]';
503
691
  const LABEL_DISABLED$1 = 'text-[var(--cxs-color-on-surface-muted)]';
504
- const LABEL_SIZE_CLASSES$1 = {
692
+ const LABEL_SIZE_CLASSES$5 = {
505
693
  sm: 'text-sm',
506
694
  md: 'text-sm',
507
695
  lg: 'text-base'
@@ -517,7 +705,7 @@ const CONTROL_BASE$1 = "relative flex shrink-0 items-center justify-center round
517
705
  'peer-indeterminate:before:opacity-100 peer-indeterminate:after:opacity-0 ' +
518
706
  'peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 ' +
519
707
  'peer-focus-visible:outline-[var(--cxs-color-focus)]';
520
- const CONTROL_SIZE_CLASSES$1 = {
708
+ const CONTROL_SIZE_CLASSES$2 = {
521
709
  sm: 'h-4 w-4',
522
710
  md: 'h-5 w-5',
523
711
  lg: 'h-6 w-6'
@@ -555,7 +743,7 @@ class CxsCheckboxComponent {
555
743
  get labelClass() {
556
744
  return [
557
745
  LABEL_BASE$1,
558
- LABEL_SIZE_CLASSES$1[this.size],
746
+ LABEL_SIZE_CLASSES$5[this.size],
559
747
  this.isDisabled ? LABEL_DISABLED$1 : ''
560
748
  ]
561
749
  .filter(Boolean)
@@ -564,7 +752,7 @@ class CxsCheckboxComponent {
564
752
  get controlClass() {
565
753
  return [
566
754
  CONTROL_BASE$1,
567
- CONTROL_SIZE_CLASSES$1[this.size],
755
+ CONTROL_SIZE_CLASSES$2[this.size],
568
756
  MARK_SIZE_CLASSES[this.size]
569
757
  ].join(' ');
570
758
  }
@@ -837,8 +1025,15 @@ const TOOLBAR_INPUT_CLASSES = 'w-full rounded-[var(--cxs-radius-md)] border bord
837
1025
  'bg-[var(--cxs-color-surface)] px-3 py-2 text-sm text-[var(--cxs-color-on-surface)] ' +
838
1026
  'placeholder:text-[var(--cxs-color-on-surface-muted)] focus-visible:outline focus-visible:outline-2 ' +
839
1027
  'focus-visible:outline-offset-2 focus-visible:outline-[var(--cxs-color-focus)]';
1028
+ const TOOLBAR_INPUT_INLINE_CLASSES = 'w-full sm:w-64 rounded-[var(--cxs-radius-md)] border border-[var(--cxs-color-border)] ' +
1029
+ 'bg-[var(--cxs-color-surface)] px-3 py-2 text-sm text-[var(--cxs-color-on-surface)] ' +
1030
+ 'placeholder:text-[var(--cxs-color-on-surface-muted)] focus-visible:outline focus-visible:outline-2 ' +
1031
+ 'focus-visible:outline-offset-2 focus-visible:outline-[var(--cxs-color-focus)]';
840
1032
  const TOOLBAR_BUTTON_CLASSES = 'inline-flex items-center justify-center rounded-[var(--cxs-radius-md)] border border-[var(--cxs-color-border)] ' +
841
1033
  'px-3 py-2 text-sm transition-colors hover:bg-[var(--cxs-color-surface-hover)]';
1034
+ const TITLE_BAR_CLASSES = 'mb-3 flex flex-wrap items-start justify-between gap-3';
1035
+ const TITLE_TEXT_CLASSES = 'text-base font-semibold text-(--cxs-color-on-surface)';
1036
+ const SUBTITLE_TEXT_CLASSES = 'text-sm text-(--cxs-color-on-surface-muted)';
842
1037
  const BULK_BAR_CLASSES = 'mb-3 flex flex-wrap items-center justify-between gap-3 rounded-[var(--cxs-radius-md)] ' +
843
1038
  'border border-[var(--cxs-color-border)] bg-[var(--cxs-color-surface)] px-3 py-2 text-sm';
844
1039
  const RESIZE_HANDLE_CLASSES = 'absolute right-0 top-0 h-full w-2 cursor-col-resize touch-none';
@@ -847,6 +1042,8 @@ class CxsDataTableComponent {
847
1042
  columns = [];
848
1043
  data = [];
849
1044
  caption;
1045
+ title;
1046
+ subtitle;
850
1047
  ariaLabel = 'Data table';
851
1048
  striped = false;
852
1049
  bordered = false;
@@ -961,9 +1158,21 @@ class CxsDataTableComponent {
961
1158
  get toolbarInputClass() {
962
1159
  return TOOLBAR_INPUT_CLASSES;
963
1160
  }
1161
+ get toolbarInputInlineClass() {
1162
+ return TOOLBAR_INPUT_INLINE_CLASSES;
1163
+ }
964
1164
  get toolbarButtonClass() {
965
1165
  return TOOLBAR_BUTTON_CLASSES;
966
1166
  }
1167
+ get titleBarClass() {
1168
+ return TITLE_BAR_CLASSES;
1169
+ }
1170
+ get titleTextClass() {
1171
+ return TITLE_TEXT_CLASSES;
1172
+ }
1173
+ get subtitleTextClass() {
1174
+ return SUBTITLE_TEXT_CLASSES;
1175
+ }
967
1176
  get bulkBarClass() {
968
1177
  return BULK_BAR_CLASSES;
969
1178
  }
@@ -1000,6 +1209,9 @@ class CxsDataTableComponent {
1000
1209
  get selectedCount() {
1001
1210
  return this.selectedKeys.length;
1002
1211
  }
1212
+ get hasTitleBlock() {
1213
+ return Boolean(this.title || this.subtitle);
1214
+ }
1003
1215
  get allVisibleSelected() {
1004
1216
  if (!this.displayRows.length) {
1005
1217
  return false;
@@ -1310,11 +1522,11 @@ class CxsDataTableComponent {
1310
1522
  return value;
1311
1523
  }
1312
1524
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsDataTableComponent, deps: [{ token: 'class', attribute: true }], target: i0.ɵɵFactoryTarget.Component });
1313
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsDataTableComponent, isStandalone: true, selector: "cxs-data-table", inputs: { columns: "columns", data: "data", caption: "caption", ariaLabel: "ariaLabel", striped: "striped", bordered: "bordered", compact: "compact", loading: "loading", emptyMessage: "emptyMessage", emptyCell: "emptyCell", pageSize: "pageSize", pageIndex: "pageIndex", pageSizeOptions: "pageSizeOptions", showPagination: "showPagination", showPageSize: "showPageSize", manualPagination: "manualPagination", total: "total", sortKey: "sortKey", sortDirection: "sortDirection", manualSort: "manualSort", showToolbar: "showToolbar", showFilters: "showFilters", showColumnVisibility: "showColumnVisibility", showGlobalSearch: "showGlobalSearch", manualFilter: "manualFilter", selectable: "selectable", rowKey: "rowKey", selectedKeys: "selectedKeys", bulkActions: "bulkActions" }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange", filterChange: "filterChange", selectionChange: "selectionChange", bulkAction: "bulkAction" }, queries: [{ propertyName: "cellTemplates", predicate: CxsDataTableCellDirective }], usesOnChanges: true, ngImport: i0, template: "@if (showToolbar) {\n <div [class]=\"toolbarClass\">\n <div [class]=\"toolbarGroupClass\">\n @if (showGlobalSearch) {\n <input\n type=\"search\"\n [class]=\"toolbarInputClass\"\n placeholder=\"Search\"\n [value]=\"globalFilter\"\n (input)=\"onGlobalFilterChange($any($event.target).value)\"\n />\n }\n </div>\n <div [class]=\"toolbarGroupClass\">\n @if (showFilters) {\n <button type=\"button\" [class]=\"toolbarButtonClass\" (click)=\"filtersOpen = !filtersOpen\">\n Filters\n </button>\n }\n @if (showColumnVisibility) {\n <details class=\"relative\">\n <summary [class]=\"toolbarButtonClass\">Columns</summary>\n <div\n class=\"absolute right-0 mt-2 w-48 rounded-(--cxs-radius-md) border border-(--cxs-color-border) bg-(--cxs-color-surface) p-2 shadow-(--cxs-shadow-sm)\"\n >\n @for (column of columns; track column) {\n <label class=\"flex items-center gap-2 px-2 py-1 text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"columnVisibility[column.key]\"\n (change)=\"toggleColumnVisibility(column.key)\"\n />\n <span>{{ column.label }}</span>\n </label>\n }\n </div>\n </details>\n }\n </div>\n </div>\n}\n\n@if (selectable && selectedCount > 0 && bulkActions.length > 0) {\n <div [class]=\"bulkBarClass\">\n <span>{{ selectedCount }} selected</span>\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (action of bulkActions; track action) {\n <button type=\"button\" [class]=\"toolbarButtonClass\" (click)=\"runBulkAction(action.id)\">\n {{ action.label }}\n </button>\n }\n </div>\n </div>\n}\n\n<div [class]=\"wrapperClass\">\n <table [class]=\"tableClass\" [attr.aria-label]=\"ariaLabel\">\n @if (caption) {\n <caption class=\"sr-only\">{{ caption }}</caption>\n }\n <thead>\n <tr [class]=\"headerRowClass\">\n @if (selectable) {\n <th class=\"px-3 py-2\">\n <input\n type=\"checkbox\"\n [checked]=\"allVisibleSelected\"\n [indeterminate]=\"someVisibleSelected\"\n (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of visibleColumns; track column) {\n <th\n class=\"relative\"\n [class]=\"headerCellClass(column) + ' ' + pinnedClass(column)\"\n [style.width]=\"columnWidth(column)\"\n [style.minWidth]=\"columnMinWidth(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n scope=\"col\"\n [attr.aria-sort]=\"ariaSort(column)\"\n >\n @if (column.sortable) {\n <button\n type=\"button\"\n [class]=\"headerButtonClass()\"\n (click)=\"onSort(column)\"\n >\n <span>{{ column.label }}</span>\n @if (sortKey === column.key) {\n @if (sortDirection === 'asc') {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"h-4 w-4 text-(--cxs-color-on-surface-muted)\"\n aria-hidden=\"true\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18\"\n />\n </svg>\n } @else {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"h-4 w-4 text-(--cxs-color-on-surface-muted)\"\n aria-hidden=\"true\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M19.5 13.5 12 21m0 0-7.5-7.5M12 21V3\"\n />\n </svg>\n }\n }\n </button>\n } @else {\n {{ column.label }}\n }\n @if (column.resizable !== false) {\n <span\n [class]=\"resizeHandleClass\"\n (mousedown)=\"onResizeStart($event, column)\"\n ></span>\n }\n </th>\n }\n </tr>\n @if (showFilters && filtersOpen) {\n <tr [class]=\"headerRowClass\">\n @if (selectable) {\n <th class=\"px-3 py-2\"></th>\n }\n @for (column of visibleColumns; track column) {\n <th\n [class]=\"headerCellClass(column) + ' ' + pinnedClass(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n >\n @if (column.filterable) {\n @if (column.filterType === 'select') {\n <select\n [class]=\"headerFilterInputClass()\"\n [value]=\"columnFilterValue(column.key)\"\n (change)=\"onColumnFilterChange(column.key, $any($event.target).value)\"\n >\n <option value=\"\">All</option>\n @for (option of column.filterOptions ?? []; track option) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </select>\n } @else {\n <input\n [class]=\"headerFilterInputClass()\"\n [attr.type]=\"column.filterType === 'number' ? 'number' : 'text'\"\n placeholder=\"Filter\"\n [value]=\"columnFilterValue(column.key)\"\n (input)=\"onColumnFilterChange(column.key, $any($event.target).value)\"\n />\n }\n }\n </th>\n }\n </tr>\n }\n </thead>\n <tbody>\n @if (loading) {\n <tr [class]=\"bodyRowClass\">\n <td [class]=\"bodyCellClass({ key: '', label: '' })\" [attr.colspan]=\"colSpan\">\n <span [class]=\"emptyRowClass\">Loading...</span>\n </td>\n </tr>\n } @else if (displayRows.length === 0) {\n <tr [class]=\"bodyRowClass\">\n <td [class]=\"bodyCellClass({ key: '', label: '' })\" [attr.colspan]=\"colSpan\">\n <span [class]=\"emptyRowClass\">{{ emptyMessage }}</span>\n </td>\n </tr>\n } @else {\n @for (row of displayRows; track row) {\n <tr [class]=\"bodyRowClass\">\n @if (selectable) {\n <td class=\"px-3 py-2\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(row)\"\n (change)=\"toggleRowSelection(row)\"\n aria-label=\"Select row\"\n />\n </td>\n }\n @for (column of visibleColumns; track column) {\n <td\n [class]=\"bodyCellClass(column) + ' ' + pinnedClass(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n >\n @if (cellTemplate(column.key); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template\"\n [ngTemplateOutletContext]=\"{ $implicit: row, value: row[column.key], column }\"\n ></ng-container>\n } @else {\n {{ cellValue(row, column) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (showPagination) {\n <div [class]=\"paginationClass\">\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n [class]=\"pageButtonClass\"\n [disabled]=\"currentPage <= 1\"\n (click)=\"previousPage()\"\n >\n Previous\n </button>\n <button\n type=\"button\"\n [class]=\"pageButtonClass\"\n [disabled]=\"currentPage >= totalPages\"\n (click)=\"nextPage()\"\n >\n Next\n </button>\n <span class=\"text-(--cxs-color-on-surface-muted)\">{{ pageLabel }}</span>\n </div>\n @if (showPageSize) {\n <label class=\"flex items-center gap-2 text-(--cxs-color-on-surface-muted)\">\n <span>Rows</span>\n <select\n #pageSizeSelect\n [class]=\"pageSelectClass\"\n [value]=\"currentPageSize\"\n (change)=\"onPageSizeChange(pageSizeSelect.value)\"\n >\n @for (size of pageSizeOptions; track size) {\n <option [value]=\"size\">{{ size }}</option>\n }\n </select>\n </label>\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1525
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsDataTableComponent, isStandalone: true, selector: "cxs-data-table", inputs: { columns: "columns", data: "data", caption: "caption", title: "title", subtitle: "subtitle", ariaLabel: "ariaLabel", striped: "striped", bordered: "bordered", compact: "compact", loading: "loading", emptyMessage: "emptyMessage", emptyCell: "emptyCell", pageSize: "pageSize", pageIndex: "pageIndex", pageSizeOptions: "pageSizeOptions", showPagination: "showPagination", showPageSize: "showPageSize", manualPagination: "manualPagination", total: "total", sortKey: "sortKey", sortDirection: "sortDirection", manualSort: "manualSort", showToolbar: "showToolbar", showFilters: "showFilters", showColumnVisibility: "showColumnVisibility", showGlobalSearch: "showGlobalSearch", manualFilter: "manualFilter", selectable: "selectable", rowKey: "rowKey", selectedKeys: "selectedKeys", bulkActions: "bulkActions" }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange", filterChange: "filterChange", selectionChange: "selectionChange", bulkAction: "bulkAction" }, queries: [{ propertyName: "cellTemplates", predicate: CxsDataTableCellDirective }], usesOnChanges: true, ngImport: i0, template: "@if (hasTitleBlock) {\n <div [class]=\"titleBarClass\">\n <div class=\"min-w-0\">\n @if (title) {\n <div [class]=\"titleTextClass\">{{ title }}</div>\n }\n @if (subtitle) {\n <div [class]=\"subtitleTextClass\">{{ subtitle }}</div>\n }\n </div>\n @if (showToolbar) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @if (showGlobalSearch) {\n <input\n type=\"search\"\n [class]=\"toolbarInputInlineClass\"\n placeholder=\"Search\"\n [value]=\"globalFilter\"\n (input)=\"onGlobalFilterChange($any($event.target).value)\"\n />\n }\n @if (showFilters) {\n <button type=\"button\" [class]=\"toolbarButtonClass\" (click)=\"filtersOpen = !filtersOpen\">\n Filters\n </button>\n }\n @if (showColumnVisibility) {\n <details class=\"relative\">\n <summary [class]=\"toolbarButtonClass\">Columns</summary>\n <div\n class=\"absolute right-0 mt-2 w-48 rounded-(--cxs-radius-md) border border-(--cxs-color-border) bg-(--cxs-color-surface) p-2 shadow-(--cxs-shadow-sm)\"\n >\n @for (column of columns; track column) {\n <label class=\"flex items-center gap-2 px-2 py-1 text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"columnVisibility[column.key]\"\n (change)=\"toggleColumnVisibility(column.key)\"\n />\n <span>{{ column.label }}</span>\n </label>\n }\n </div>\n </details>\n }\n </div>\n }\n </div>\n} @else if (showToolbar) {\n <div [class]=\"toolbarClass\">\n <div [class]=\"toolbarGroupClass\">\n @if (showGlobalSearch) {\n <input\n type=\"search\"\n [class]=\"toolbarInputClass\"\n placeholder=\"Search\"\n [value]=\"globalFilter\"\n (input)=\"onGlobalFilterChange($any($event.target).value)\"\n />\n }\n </div>\n <div [class]=\"toolbarGroupClass\">\n @if (showFilters) {\n <button type=\"button\" [class]=\"toolbarButtonClass\" (click)=\"filtersOpen = !filtersOpen\">\n Filters\n </button>\n }\n @if (showColumnVisibility) {\n <details class=\"relative\">\n <summary [class]=\"toolbarButtonClass\">Columns</summary>\n <div\n class=\"absolute right-0 mt-2 w-48 rounded-(--cxs-radius-md) border border-(--cxs-color-border) bg-(--cxs-color-surface) p-2 shadow-(--cxs-shadow-sm)\"\n >\n @for (column of columns; track column) {\n <label class=\"flex items-center gap-2 px-2 py-1 text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"columnVisibility[column.key]\"\n (change)=\"toggleColumnVisibility(column.key)\"\n />\n <span>{{ column.label }}</span>\n </label>\n }\n </div>\n </details>\n }\n </div>\n </div>\n}\n\n@if (selectable && selectedCount > 0 && bulkActions.length > 0) {\n <div [class]=\"bulkBarClass\">\n <span>{{ selectedCount }} selected</span>\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (action of bulkActions; track action) {\n <button type=\"button\" [class]=\"toolbarButtonClass\" (click)=\"runBulkAction(action.id)\">\n {{ action.label }}\n </button>\n }\n </div>\n </div>\n}\n\n<div [class]=\"wrapperClass\">\n <table [class]=\"tableClass\" [attr.aria-label]=\"ariaLabel\">\n @if (caption) {\n <caption class=\"sr-only\">{{ caption }}</caption>\n }\n <thead>\n <tr [class]=\"headerRowClass\">\n @if (selectable) {\n <th class=\"px-3 py-2 text-left\">\n <input\n type=\"checkbox\"\n [checked]=\"allVisibleSelected\"\n [indeterminate]=\"someVisibleSelected\"\n (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of visibleColumns; track column) {\n <th\n class=\"relative\"\n [class]=\"headerCellClass(column) + ' ' + pinnedClass(column)\"\n [style.width]=\"columnWidth(column)\"\n [style.minWidth]=\"columnMinWidth(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n scope=\"col\"\n [attr.aria-sort]=\"ariaSort(column)\"\n >\n @if (column.sortable) {\n <button\n type=\"button\"\n [class]=\"headerButtonClass()\"\n (click)=\"onSort(column)\"\n >\n <span>{{ column.label }}</span>\n @if (sortKey === column.key) {\n @if (sortDirection === 'asc') {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"h-4 w-4 text-(--cxs-color-on-surface-muted)\"\n aria-hidden=\"true\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18\"\n />\n </svg>\n } @else {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"h-4 w-4 text-(--cxs-color-on-surface-muted)\"\n aria-hidden=\"true\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M19.5 13.5 12 21m0 0-7.5-7.5M12 21V3\"\n />\n </svg>\n }\n }\n </button>\n } @else {\n {{ column.label }}\n }\n @if (column.resizable !== false) {\n <span\n [class]=\"resizeHandleClass\"\n (mousedown)=\"onResizeStart($event, column)\"\n ></span>\n }\n </th>\n }\n </tr>\n @if (showFilters && filtersOpen) {\n <tr [class]=\"headerRowClass\">\n @if (selectable) {\n <th class=\"px-3 py-2 text-left\"></th>\n }\n @for (column of visibleColumns; track column) {\n <th\n [class]=\"headerCellClass(column) + ' ' + pinnedClass(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n >\n @if (column.filterable) {\n @if (column.filterType === 'select') {\n <select\n [class]=\"headerFilterInputClass()\"\n [value]=\"columnFilterValue(column.key)\"\n (change)=\"onColumnFilterChange(column.key, $any($event.target).value)\"\n >\n <option value=\"\">All</option>\n @for (option of column.filterOptions ?? []; track option) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </select>\n } @else {\n <input\n [class]=\"headerFilterInputClass()\"\n [attr.type]=\"column.filterType === 'number' ? 'number' : 'text'\"\n [value]=\"columnFilterValue(column.key)\"\n (input)=\"onColumnFilterChange(column.key, $any($event.target).value)\"\n />\n }\n }\n </th>\n }\n </tr>\n }\n </thead>\n <tbody>\n @if (loading) {\n <tr [class]=\"bodyRowClass\">\n <td [class]=\"bodyCellClass({ key: '', label: '' })\" [attr.colspan]=\"colSpan\">\n <span [class]=\"emptyRowClass\">Loading...</span>\n </td>\n </tr>\n } @else if (displayRows.length === 0) {\n <tr [class]=\"bodyRowClass\">\n <td [class]=\"bodyCellClass({ key: '', label: '' })\" [attr.colspan]=\"colSpan\">\n <span [class]=\"emptyRowClass\">{{ emptyMessage }}</span>\n </td>\n </tr>\n } @else {\n @for (row of displayRows; track row) {\n <tr [class]=\"bodyRowClass\">\n @if (selectable) {\n <td class=\"px-3 py-2\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(row)\"\n (change)=\"toggleRowSelection(row)\"\n aria-label=\"Select row\"\n />\n </td>\n }\n @for (column of visibleColumns; track column) {\n <td\n [class]=\"bodyCellClass(column) + ' ' + pinnedClass(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n >\n @if (cellTemplate(column.key); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template\"\n [ngTemplateOutletContext]=\"{ $implicit: row, value: row[column.key], column }\"\n ></ng-container>\n } @else {\n {{ cellValue(row, column) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (showPagination) {\n <div [class]=\"paginationClass\">\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n [class]=\"pageButtonClass\"\n [disabled]=\"currentPage <= 1\"\n (click)=\"previousPage()\"\n >\n Previous\n </button>\n <button\n type=\"button\"\n [class]=\"pageButtonClass\"\n [disabled]=\"currentPage >= totalPages\"\n (click)=\"nextPage()\"\n >\n Next\n </button>\n <span class=\"text-(--cxs-color-on-surface-muted)\">{{ pageLabel }}</span>\n </div>\n @if (showPageSize) {\n <label class=\"flex items-center gap-2 text-(--cxs-color-on-surface-muted)\">\n <span>Rows</span>\n <select\n #pageSizeSelect\n [class]=\"pageSelectClass\"\n [value]=\"currentPageSize\"\n (change)=\"onPageSizeChange(pageSizeSelect.value)\"\n >\n @for (size of pageSizeOptions; track size) {\n <option [value]=\"size\">{{ size }}</option>\n }\n </select>\n </label>\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1314
1526
  }
1315
1527
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsDataTableComponent, decorators: [{
1316
1528
  type: Component,
1317
- args: [{ selector: 'cxs-data-table', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (showToolbar) {\n <div [class]=\"toolbarClass\">\n <div [class]=\"toolbarGroupClass\">\n @if (showGlobalSearch) {\n <input\n type=\"search\"\n [class]=\"toolbarInputClass\"\n placeholder=\"Search\"\n [value]=\"globalFilter\"\n (input)=\"onGlobalFilterChange($any($event.target).value)\"\n />\n }\n </div>\n <div [class]=\"toolbarGroupClass\">\n @if (showFilters) {\n <button type=\"button\" [class]=\"toolbarButtonClass\" (click)=\"filtersOpen = !filtersOpen\">\n Filters\n </button>\n }\n @if (showColumnVisibility) {\n <details class=\"relative\">\n <summary [class]=\"toolbarButtonClass\">Columns</summary>\n <div\n class=\"absolute right-0 mt-2 w-48 rounded-(--cxs-radius-md) border border-(--cxs-color-border) bg-(--cxs-color-surface) p-2 shadow-(--cxs-shadow-sm)\"\n >\n @for (column of columns; track column) {\n <label class=\"flex items-center gap-2 px-2 py-1 text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"columnVisibility[column.key]\"\n (change)=\"toggleColumnVisibility(column.key)\"\n />\n <span>{{ column.label }}</span>\n </label>\n }\n </div>\n </details>\n }\n </div>\n </div>\n}\n\n@if (selectable && selectedCount > 0 && bulkActions.length > 0) {\n <div [class]=\"bulkBarClass\">\n <span>{{ selectedCount }} selected</span>\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (action of bulkActions; track action) {\n <button type=\"button\" [class]=\"toolbarButtonClass\" (click)=\"runBulkAction(action.id)\">\n {{ action.label }}\n </button>\n }\n </div>\n </div>\n}\n\n<div [class]=\"wrapperClass\">\n <table [class]=\"tableClass\" [attr.aria-label]=\"ariaLabel\">\n @if (caption) {\n <caption class=\"sr-only\">{{ caption }}</caption>\n }\n <thead>\n <tr [class]=\"headerRowClass\">\n @if (selectable) {\n <th class=\"px-3 py-2\">\n <input\n type=\"checkbox\"\n [checked]=\"allVisibleSelected\"\n [indeterminate]=\"someVisibleSelected\"\n (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of visibleColumns; track column) {\n <th\n class=\"relative\"\n [class]=\"headerCellClass(column) + ' ' + pinnedClass(column)\"\n [style.width]=\"columnWidth(column)\"\n [style.minWidth]=\"columnMinWidth(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n scope=\"col\"\n [attr.aria-sort]=\"ariaSort(column)\"\n >\n @if (column.sortable) {\n <button\n type=\"button\"\n [class]=\"headerButtonClass()\"\n (click)=\"onSort(column)\"\n >\n <span>{{ column.label }}</span>\n @if (sortKey === column.key) {\n @if (sortDirection === 'asc') {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"h-4 w-4 text-(--cxs-color-on-surface-muted)\"\n aria-hidden=\"true\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18\"\n />\n </svg>\n } @else {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"h-4 w-4 text-(--cxs-color-on-surface-muted)\"\n aria-hidden=\"true\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M19.5 13.5 12 21m0 0-7.5-7.5M12 21V3\"\n />\n </svg>\n }\n }\n </button>\n } @else {\n {{ column.label }}\n }\n @if (column.resizable !== false) {\n <span\n [class]=\"resizeHandleClass\"\n (mousedown)=\"onResizeStart($event, column)\"\n ></span>\n }\n </th>\n }\n </tr>\n @if (showFilters && filtersOpen) {\n <tr [class]=\"headerRowClass\">\n @if (selectable) {\n <th class=\"px-3 py-2\"></th>\n }\n @for (column of visibleColumns; track column) {\n <th\n [class]=\"headerCellClass(column) + ' ' + pinnedClass(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n >\n @if (column.filterable) {\n @if (column.filterType === 'select') {\n <select\n [class]=\"headerFilterInputClass()\"\n [value]=\"columnFilterValue(column.key)\"\n (change)=\"onColumnFilterChange(column.key, $any($event.target).value)\"\n >\n <option value=\"\">All</option>\n @for (option of column.filterOptions ?? []; track option) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </select>\n } @else {\n <input\n [class]=\"headerFilterInputClass()\"\n [attr.type]=\"column.filterType === 'number' ? 'number' : 'text'\"\n placeholder=\"Filter\"\n [value]=\"columnFilterValue(column.key)\"\n (input)=\"onColumnFilterChange(column.key, $any($event.target).value)\"\n />\n }\n }\n </th>\n }\n </tr>\n }\n </thead>\n <tbody>\n @if (loading) {\n <tr [class]=\"bodyRowClass\">\n <td [class]=\"bodyCellClass({ key: '', label: '' })\" [attr.colspan]=\"colSpan\">\n <span [class]=\"emptyRowClass\">Loading...</span>\n </td>\n </tr>\n } @else if (displayRows.length === 0) {\n <tr [class]=\"bodyRowClass\">\n <td [class]=\"bodyCellClass({ key: '', label: '' })\" [attr.colspan]=\"colSpan\">\n <span [class]=\"emptyRowClass\">{{ emptyMessage }}</span>\n </td>\n </tr>\n } @else {\n @for (row of displayRows; track row) {\n <tr [class]=\"bodyRowClass\">\n @if (selectable) {\n <td class=\"px-3 py-2\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(row)\"\n (change)=\"toggleRowSelection(row)\"\n aria-label=\"Select row\"\n />\n </td>\n }\n @for (column of visibleColumns; track column) {\n <td\n [class]=\"bodyCellClass(column) + ' ' + pinnedClass(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n >\n @if (cellTemplate(column.key); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template\"\n [ngTemplateOutletContext]=\"{ $implicit: row, value: row[column.key], column }\"\n ></ng-container>\n } @else {\n {{ cellValue(row, column) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (showPagination) {\n <div [class]=\"paginationClass\">\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n [class]=\"pageButtonClass\"\n [disabled]=\"currentPage <= 1\"\n (click)=\"previousPage()\"\n >\n Previous\n </button>\n <button\n type=\"button\"\n [class]=\"pageButtonClass\"\n [disabled]=\"currentPage >= totalPages\"\n (click)=\"nextPage()\"\n >\n Next\n </button>\n <span class=\"text-(--cxs-color-on-surface-muted)\">{{ pageLabel }}</span>\n </div>\n @if (showPageSize) {\n <label class=\"flex items-center gap-2 text-(--cxs-color-on-surface-muted)\">\n <span>Rows</span>\n <select\n #pageSizeSelect\n [class]=\"pageSelectClass\"\n [value]=\"currentPageSize\"\n (change)=\"onPageSizeChange(pageSizeSelect.value)\"\n >\n @for (size of pageSizeOptions; track size) {\n <option [value]=\"size\">{{ size }}</option>\n }\n </select>\n </label>\n }\n </div>\n}\n" }]
1529
+ args: [{ selector: 'cxs-data-table', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (hasTitleBlock) {\n <div [class]=\"titleBarClass\">\n <div class=\"min-w-0\">\n @if (title) {\n <div [class]=\"titleTextClass\">{{ title }}</div>\n }\n @if (subtitle) {\n <div [class]=\"subtitleTextClass\">{{ subtitle }}</div>\n }\n </div>\n @if (showToolbar) {\n <div class=\"flex flex-wrap items-center gap-2\">\n @if (showGlobalSearch) {\n <input\n type=\"search\"\n [class]=\"toolbarInputInlineClass\"\n placeholder=\"Search\"\n [value]=\"globalFilter\"\n (input)=\"onGlobalFilterChange($any($event.target).value)\"\n />\n }\n @if (showFilters) {\n <button type=\"button\" [class]=\"toolbarButtonClass\" (click)=\"filtersOpen = !filtersOpen\">\n Filters\n </button>\n }\n @if (showColumnVisibility) {\n <details class=\"relative\">\n <summary [class]=\"toolbarButtonClass\">Columns</summary>\n <div\n class=\"absolute right-0 mt-2 w-48 rounded-(--cxs-radius-md) border border-(--cxs-color-border) bg-(--cxs-color-surface) p-2 shadow-(--cxs-shadow-sm)\"\n >\n @for (column of columns; track column) {\n <label class=\"flex items-center gap-2 px-2 py-1 text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"columnVisibility[column.key]\"\n (change)=\"toggleColumnVisibility(column.key)\"\n />\n <span>{{ column.label }}</span>\n </label>\n }\n </div>\n </details>\n }\n </div>\n }\n </div>\n} @else if (showToolbar) {\n <div [class]=\"toolbarClass\">\n <div [class]=\"toolbarGroupClass\">\n @if (showGlobalSearch) {\n <input\n type=\"search\"\n [class]=\"toolbarInputClass\"\n placeholder=\"Search\"\n [value]=\"globalFilter\"\n (input)=\"onGlobalFilterChange($any($event.target).value)\"\n />\n }\n </div>\n <div [class]=\"toolbarGroupClass\">\n @if (showFilters) {\n <button type=\"button\" [class]=\"toolbarButtonClass\" (click)=\"filtersOpen = !filtersOpen\">\n Filters\n </button>\n }\n @if (showColumnVisibility) {\n <details class=\"relative\">\n <summary [class]=\"toolbarButtonClass\">Columns</summary>\n <div\n class=\"absolute right-0 mt-2 w-48 rounded-(--cxs-radius-md) border border-(--cxs-color-border) bg-(--cxs-color-surface) p-2 shadow-(--cxs-shadow-sm)\"\n >\n @for (column of columns; track column) {\n <label class=\"flex items-center gap-2 px-2 py-1 text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"columnVisibility[column.key]\"\n (change)=\"toggleColumnVisibility(column.key)\"\n />\n <span>{{ column.label }}</span>\n </label>\n }\n </div>\n </details>\n }\n </div>\n </div>\n}\n\n@if (selectable && selectedCount > 0 && bulkActions.length > 0) {\n <div [class]=\"bulkBarClass\">\n <span>{{ selectedCount }} selected</span>\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (action of bulkActions; track action) {\n <button type=\"button\" [class]=\"toolbarButtonClass\" (click)=\"runBulkAction(action.id)\">\n {{ action.label }}\n </button>\n }\n </div>\n </div>\n}\n\n<div [class]=\"wrapperClass\">\n <table [class]=\"tableClass\" [attr.aria-label]=\"ariaLabel\">\n @if (caption) {\n <caption class=\"sr-only\">{{ caption }}</caption>\n }\n <thead>\n <tr [class]=\"headerRowClass\">\n @if (selectable) {\n <th class=\"px-3 py-2 text-left\">\n <input\n type=\"checkbox\"\n [checked]=\"allVisibleSelected\"\n [indeterminate]=\"someVisibleSelected\"\n (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of visibleColumns; track column) {\n <th\n class=\"relative\"\n [class]=\"headerCellClass(column) + ' ' + pinnedClass(column)\"\n [style.width]=\"columnWidth(column)\"\n [style.minWidth]=\"columnMinWidth(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n scope=\"col\"\n [attr.aria-sort]=\"ariaSort(column)\"\n >\n @if (column.sortable) {\n <button\n type=\"button\"\n [class]=\"headerButtonClass()\"\n (click)=\"onSort(column)\"\n >\n <span>{{ column.label }}</span>\n @if (sortKey === column.key) {\n @if (sortDirection === 'asc') {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"h-4 w-4 text-(--cxs-color-on-surface-muted)\"\n aria-hidden=\"true\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18\"\n />\n </svg>\n } @else {\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"h-4 w-4 text-(--cxs-color-on-surface-muted)\"\n aria-hidden=\"true\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M19.5 13.5 12 21m0 0-7.5-7.5M12 21V3\"\n />\n </svg>\n }\n }\n </button>\n } @else {\n {{ column.label }}\n }\n @if (column.resizable !== false) {\n <span\n [class]=\"resizeHandleClass\"\n (mousedown)=\"onResizeStart($event, column)\"\n ></span>\n }\n </th>\n }\n </tr>\n @if (showFilters && filtersOpen) {\n <tr [class]=\"headerRowClass\">\n @if (selectable) {\n <th class=\"px-3 py-2 text-left\"></th>\n }\n @for (column of visibleColumns; track column) {\n <th\n [class]=\"headerCellClass(column) + ' ' + pinnedClass(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n >\n @if (column.filterable) {\n @if (column.filterType === 'select') {\n <select\n [class]=\"headerFilterInputClass()\"\n [value]=\"columnFilterValue(column.key)\"\n (change)=\"onColumnFilterChange(column.key, $any($event.target).value)\"\n >\n <option value=\"\">All</option>\n @for (option of column.filterOptions ?? []; track option) {\n <option [value]=\"option.value\">{{ option.label }}</option>\n }\n </select>\n } @else {\n <input\n [class]=\"headerFilterInputClass()\"\n [attr.type]=\"column.filterType === 'number' ? 'number' : 'text'\"\n [value]=\"columnFilterValue(column.key)\"\n (input)=\"onColumnFilterChange(column.key, $any($event.target).value)\"\n />\n }\n }\n </th>\n }\n </tr>\n }\n </thead>\n <tbody>\n @if (loading) {\n <tr [class]=\"bodyRowClass\">\n <td [class]=\"bodyCellClass({ key: '', label: '' })\" [attr.colspan]=\"colSpan\">\n <span [class]=\"emptyRowClass\">Loading...</span>\n </td>\n </tr>\n } @else if (displayRows.length === 0) {\n <tr [class]=\"bodyRowClass\">\n <td [class]=\"bodyCellClass({ key: '', label: '' })\" [attr.colspan]=\"colSpan\">\n <span [class]=\"emptyRowClass\">{{ emptyMessage }}</span>\n </td>\n </tr>\n } @else {\n @for (row of displayRows; track row) {\n <tr [class]=\"bodyRowClass\">\n @if (selectable) {\n <td class=\"px-3 py-2\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(row)\"\n (change)=\"toggleRowSelection(row)\"\n aria-label=\"Select row\"\n />\n </td>\n }\n @for (column of visibleColumns; track column) {\n <td\n [class]=\"bodyCellClass(column) + ' ' + pinnedClass(column)\"\n [style.left]=\"pinnedLeft(column)\"\n [style.right]=\"pinnedRight(column)\"\n >\n @if (cellTemplate(column.key); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template\"\n [ngTemplateOutletContext]=\"{ $implicit: row, value: row[column.key], column }\"\n ></ng-container>\n } @else {\n {{ cellValue(row, column) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n@if (showPagination) {\n <div [class]=\"paginationClass\">\n <div class=\"flex items-center gap-2\">\n <button\n type=\"button\"\n [class]=\"pageButtonClass\"\n [disabled]=\"currentPage <= 1\"\n (click)=\"previousPage()\"\n >\n Previous\n </button>\n <button\n type=\"button\"\n [class]=\"pageButtonClass\"\n [disabled]=\"currentPage >= totalPages\"\n (click)=\"nextPage()\"\n >\n Next\n </button>\n <span class=\"text-(--cxs-color-on-surface-muted)\">{{ pageLabel }}</span>\n </div>\n @if (showPageSize) {\n <label class=\"flex items-center gap-2 text-(--cxs-color-on-surface-muted)\">\n <span>Rows</span>\n <select\n #pageSizeSelect\n [class]=\"pageSelectClass\"\n [value]=\"currentPageSize\"\n (change)=\"onPageSizeChange(pageSizeSelect.value)\"\n >\n @for (size of pageSizeOptions; track size) {\n <option [value]=\"size\">{{ size }}</option>\n }\n </select>\n </label>\n }\n </div>\n}\n" }]
1318
1530
  }], ctorParameters: () => [{ type: undefined, decorators: [{
1319
1531
  type: Attribute,
1320
1532
  args: ['class']
@@ -1324,6 +1536,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
1324
1536
  type: Input
1325
1537
  }], caption: [{
1326
1538
  type: Input
1539
+ }], title: [{
1540
+ type: Input
1541
+ }], subtitle: [{
1542
+ type: Input
1327
1543
  }], ariaLabel: [{
1328
1544
  type: Input
1329
1545
  }], striped: [{
@@ -1496,11 +1712,11 @@ class CxsDialogComponent {
1496
1712
  });
1497
1713
  }
1498
1714
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsDialogComponent, deps: [{ token: 'class', attribute: true }], target: i0.ɵɵFactoryTarget.Component });
1499
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsDialogComponent, isStandalone: true, selector: "cxs-dialog", inputs: { open: "open", title: "title", description: "description", ariaLabel: "ariaLabel", size: "size", dismissible: "dismissible", closeOnBackdrop: "closeOnBackdrop", closeOnEscape: "closeOnEscape" }, outputs: { openChange: "openChange", closed: "closed" }, viewQueries: [{ propertyName: "dialogPanel", first: true, predicate: ["dialogPanel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (open) {\n <div [class]=\"overlayClass\" (click)=\"onBackdropClick($event)\">\n <div\n #dialogPanel\n [class]=\"panelClass\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"title ? titleId : null\"\n [attr.aria-describedby]=\"description ? descriptionId : null\"\n [attr.aria-label]=\"ariaLabelValue\"\n tabindex=\"-1\"\n (keydown)=\"onKeydown($event)\"\n >\n <div class=\"flex items-start gap-3\">\n <div class=\"flex-1\">\n @if (title) {\n <h2 [id]=\"titleId\" [class]=\"titleClass\">{{ title }}</h2>\n }\n @if (description) {\n <p [id]=\"descriptionId\" [class]=\"descriptionClass\">{{ description }}</p>\n }\n </div>\n @if (dismissible) {\n <button\n type=\"button\"\n [class]=\"closeButtonClass\"\n aria-label=\"Close dialog\"\n (click)=\"requestClose('dismiss')\"\n >\n X\n </button>\n }\n </div>\n\n <div [class]=\"bodyClass\">\n <ng-content></ng-content>\n </div>\n\n <div [class]=\"actionsClass\">\n <ng-content select=\"[cxsDialogActions]\"></ng-content>\n </div>\n </div>\n </div>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
1715
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsDialogComponent, isStandalone: true, selector: "cxs-dialog", inputs: { open: "open", title: "title", description: "description", ariaLabel: "ariaLabel", size: "size", dismissible: "dismissible", closeOnBackdrop: "closeOnBackdrop", closeOnEscape: "closeOnEscape" }, outputs: { openChange: "openChange", closed: "closed" }, viewQueries: [{ propertyName: "dialogPanel", first: true, predicate: ["dialogPanel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (open) {\n <div [class]=\"overlayClass\" (click)=\"onBackdropClick($event)\">\n <div\n #dialogPanel\n [class]=\"panelClass\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"title ? titleId : null\"\n [attr.aria-describedby]=\"description ? descriptionId : null\"\n [attr.aria-label]=\"ariaLabelValue\"\n tabindex=\"-1\"\n (keydown)=\"onKeydown($event)\"\n >\n <div class=\"flex items-start gap-3\">\n <div class=\"flex-1\">\n @if (title) {\n <h2 [id]=\"titleId\" [class]=\"titleClass\">{{ title }}</h2>\n }\n @if (description) {\n <p [id]=\"descriptionId\" [class]=\"descriptionClass\">{{ description }}</p>\n }\n </div>\n @if (dismissible) {\n <button\n type=\"button\"\n [class]=\"closeButtonClass\"\n aria-label=\"Close dialog\"\n (click)=\"requestClose('dismiss')\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-6\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\" />\n </svg>\n </button>\n }\n </div>\n\n <div [class]=\"bodyClass\">\n <ng-content></ng-content>\n </div>\n\n <div [class]=\"actionsClass\">\n <ng-content select=\"[cxsDialogActions]\"></ng-content>\n </div>\n </div>\n </div>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
1500
1716
  }
1501
1717
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsDialogComponent, decorators: [{
1502
1718
  type: Component,
1503
- args: [{ selector: 'cxs-dialog', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open) {\n <div [class]=\"overlayClass\" (click)=\"onBackdropClick($event)\">\n <div\n #dialogPanel\n [class]=\"panelClass\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"title ? titleId : null\"\n [attr.aria-describedby]=\"description ? descriptionId : null\"\n [attr.aria-label]=\"ariaLabelValue\"\n tabindex=\"-1\"\n (keydown)=\"onKeydown($event)\"\n >\n <div class=\"flex items-start gap-3\">\n <div class=\"flex-1\">\n @if (title) {\n <h2 [id]=\"titleId\" [class]=\"titleClass\">{{ title }}</h2>\n }\n @if (description) {\n <p [id]=\"descriptionId\" [class]=\"descriptionClass\">{{ description }}</p>\n }\n </div>\n @if (dismissible) {\n <button\n type=\"button\"\n [class]=\"closeButtonClass\"\n aria-label=\"Close dialog\"\n (click)=\"requestClose('dismiss')\"\n >\n X\n </button>\n }\n </div>\n\n <div [class]=\"bodyClass\">\n <ng-content></ng-content>\n </div>\n\n <div [class]=\"actionsClass\">\n <ng-content select=\"[cxsDialogActions]\"></ng-content>\n </div>\n </div>\n </div>\n}\n" }]
1719
+ args: [{ selector: 'cxs-dialog', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open) {\n <div [class]=\"overlayClass\" (click)=\"onBackdropClick($event)\">\n <div\n #dialogPanel\n [class]=\"panelClass\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"title ? titleId : null\"\n [attr.aria-describedby]=\"description ? descriptionId : null\"\n [attr.aria-label]=\"ariaLabelValue\"\n tabindex=\"-1\"\n (keydown)=\"onKeydown($event)\"\n >\n <div class=\"flex items-start gap-3\">\n <div class=\"flex-1\">\n @if (title) {\n <h2 [id]=\"titleId\" [class]=\"titleClass\">{{ title }}</h2>\n }\n @if (description) {\n <p [id]=\"descriptionId\" [class]=\"descriptionClass\">{{ description }}</p>\n }\n </div>\n @if (dismissible) {\n <button\n type=\"button\"\n [class]=\"closeButtonClass\"\n aria-label=\"Close dialog\"\n (click)=\"requestClose('dismiss')\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-6\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\" />\n </svg>\n </button>\n }\n </div>\n\n <div [class]=\"bodyClass\">\n <ng-content></ng-content>\n </div>\n\n <div [class]=\"actionsClass\">\n <ng-content select=\"[cxsDialogActions]\"></ng-content>\n </div>\n </div>\n </div>\n}\n" }]
1504
1720
  }], ctorParameters: () => [{ type: undefined, decorators: [{
1505
1721
  type: Attribute,
1506
1722
  args: ['class']
@@ -1535,7 +1751,10 @@ const BASE_CLASSES$3 = 'w-full rounded-[var(--cxs-radius-md)] border border-[var
1535
1751
  'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
1536
1752
  'focus-visible:outline-[var(--cxs-color-focus)] focus-visible:border-[var(--cxs-color-focus)] ' +
1537
1753
  'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-60';
1538
- const VARIANT_CLASSES$3 = {
1754
+ const WRAPPER_CLASSES$6 = 'flex w-full flex-col gap-1';
1755
+ const LABEL_BASE_CLASSES$4 = 'font-medium text-(--cxs-color-on-surface)';
1756
+ const LABEL_DISABLED_CLASSES$4 = 'text-[var(--cxs-color-on-surface-muted)]';
1757
+ const VARIANT_CLASSES$4 = {
1539
1758
  outline: 'bg-[var(--cxs-color-surface)]',
1540
1759
  filled: 'bg-[var(--cxs-color-surface-hover)]'
1541
1760
  };
@@ -1544,7 +1763,12 @@ const SIZE_CLASSES$2 = {
1544
1763
  md: 'h-10 px-3 text-sm',
1545
1764
  lg: 'h-12 px-4 text-base'
1546
1765
  };
1547
- const INVALID_CLASSES$3 = 'border-[var(--cxs-color-danger)] focus-visible:border-[var(--cxs-color-danger)] ' +
1766
+ const LABEL_SIZE_CLASSES$4 = {
1767
+ sm: 'text-sm',
1768
+ md: 'text-sm',
1769
+ lg: 'text-base'
1770
+ };
1771
+ const INVALID_CLASSES$4 = 'border-[var(--cxs-color-danger)] focus-visible:border-[var(--cxs-color-danger)] ' +
1548
1772
  'focus-visible:outline-[var(--cxs-color-danger)]';
1549
1773
  const POPOVER_CLASSES = 'absolute left-0 top-full z-10 mt-2 w-full rounded-[var(--cxs-radius-md)] border ' +
1550
1774
  'border-[var(--cxs-color-border)] bg-[var(--cxs-color-surface)] p-3 shadow-[var(--cxs-shadow-sm)]';
@@ -1564,6 +1788,7 @@ const DAY_TODAY = 'border border-[var(--cxs-color-primary)]';
1564
1788
  const DAY_SELECTED = 'bg-[var(--cxs-color-primary)] text-[var(--cxs-color-on-primary)]';
1565
1789
  const DAY_HOVER = 'hover:bg-[var(--cxs-color-surface-hover)]';
1566
1790
  class CxsDatepickerComponent {
1791
+ static nextId = 0;
1567
1792
  value = '';
1568
1793
  variant = 'outline';
1569
1794
  size = 'md';
@@ -1573,6 +1798,7 @@ class CxsDatepickerComponent {
1573
1798
  required = false;
1574
1799
  invalid = false;
1575
1800
  autofocus = false;
1801
+ label;
1576
1802
  id;
1577
1803
  name;
1578
1804
  min;
@@ -1581,8 +1807,7 @@ class CxsDatepickerComponent {
1581
1807
  ariaLabel;
1582
1808
  ariaDescribedby;
1583
1809
  valueChange = new EventEmitter();
1584
- static nextId = 0;
1585
- fallbackId = `cxs-datepicker-panel-${CxsDatepickerComponent.nextId++}`;
1810
+ instanceId = `cxs-datepicker-${CxsDatepickerComponent.nextId++}`;
1586
1811
  disabledFromControl = false;
1587
1812
  onChange = () => { };
1588
1813
  onTouched = () => { };
@@ -1598,18 +1823,48 @@ class CxsDatepickerComponent {
1598
1823
  return this.disabled || this.disabledFromControl;
1599
1824
  }
1600
1825
  get panelId() {
1601
- return this.id ? `${this.id}-panel` : this.fallbackId;
1826
+ return `${this.inputId ?? this.instanceId}-panel`;
1602
1827
  }
1603
1828
  get inputClass() {
1604
1829
  return [
1605
1830
  BASE_CLASSES$3,
1606
1831
  SIZE_CLASSES$2[this.size],
1607
- VARIANT_CLASSES$3[this.variant],
1608
- this.invalid ? INVALID_CLASSES$3 : ''
1832
+ VARIANT_CLASSES$4[this.variant],
1833
+ this.invalid ? INVALID_CLASSES$4 : ''
1609
1834
  ]
1610
1835
  .filter(Boolean)
1611
1836
  .join(' ');
1612
1837
  }
1838
+ get wrapperClass() {
1839
+ return WRAPPER_CLASSES$6;
1840
+ }
1841
+ get labelClass() {
1842
+ return [
1843
+ LABEL_BASE_CLASSES$4,
1844
+ LABEL_SIZE_CLASSES$4[this.size],
1845
+ this.isDisabled ? LABEL_DISABLED_CLASSES$4 : ''
1846
+ ]
1847
+ .filter(Boolean)
1848
+ .join(' ');
1849
+ }
1850
+ get inputId() {
1851
+ if (this.id) {
1852
+ return this.id;
1853
+ }
1854
+ return this.label ? this.instanceId : null;
1855
+ }
1856
+ get labelId() {
1857
+ if (!this.label) {
1858
+ return null;
1859
+ }
1860
+ return `${this.inputId}-label`;
1861
+ }
1862
+ get ariaLabelValue() {
1863
+ if (this.label) {
1864
+ return null;
1865
+ }
1866
+ return this.ariaLabel ?? null;
1867
+ }
1613
1868
  get popoverClass() {
1614
1869
  return POPOVER_CLASSES;
1615
1870
  }
@@ -1785,13 +2040,13 @@ class CxsDatepickerComponent {
1785
2040
  return new Date(date.getFullYear(), date.getMonth(), date.getDate());
1786
2041
  }
1787
2042
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsDatepickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1788
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsDatepickerComponent, isStandalone: true, selector: "cxs-datepicker", inputs: { value: "value", variant: "variant", size: "size", useNative: "useNative", disabled: "disabled", readonly: "readonly", required: "required", invalid: "invalid", autofocus: "autofocus", id: "id", name: "name", min: "min", max: "max", placeholder: "placeholder", ariaLabel: "ariaLabel", ariaDescribedby: "ariaDescribedby" }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()" } }, providers: [
2043
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsDatepickerComponent, isStandalone: true, selector: "cxs-datepicker", inputs: { value: "value", variant: "variant", size: "size", useNative: "useNative", disabled: "disabled", readonly: "readonly", required: "required", invalid: "invalid", autofocus: "autofocus", label: "label", id: "id", name: "name", min: "min", max: "max", placeholder: "placeholder", ariaLabel: "ariaLabel", ariaDescribedby: "ariaDescribedby" }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()" } }, providers: [
1789
2044
  {
1790
2045
  provide: NG_VALUE_ACCESSOR,
1791
2046
  useExisting: forwardRef(() => CxsDatepickerComponent),
1792
2047
  multi: true
1793
2048
  }
1794
- ], ngImport: i0, template: "@if (useNative) {\r\n <input\r\n type=\"date\"\r\n [class]=\"inputClass\"\r\n [attr.id]=\"id\"\r\n [attr.name]=\"name\"\r\n [attr.min]=\"min\"\r\n [attr.max]=\"max\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"ariaDescribedby\"\r\n [attr.autofocus]=\"autofocus ? true : null\"\r\n [value]=\"value\"\r\n [disabled]=\"isDisabled\"\r\n [readonly]=\"readonly\"\r\n [required]=\"required\"\r\n (input)=\"onInput($event)\"\r\n (blur)=\"onBlur()\"\r\n />\r\n} @else {\r\n <div class=\"relative w-full\">\r\n <input\r\n type=\"text\"\r\n [class]=\"inputClass\"\r\n [attr.id]=\"id\"\r\n [attr.name]=\"name\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"ariaDescribedby\"\r\n [attr.aria-expanded]=\"isOpen ? 'true' : 'false'\"\r\n [attr.aria-controls]=\"panelId\"\r\n [attr.autofocus]=\"autofocus ? true : null\"\r\n [attr.data-cxs-datepicker]=\"panelId\"\r\n [value]=\"value\"\r\n [disabled]=\"isDisabled\"\r\n [readonly]=\"true\"\r\n [required]=\"required\"\r\n (click)=\"open()\"\r\n (focus)=\"open()\"\r\n (blur)=\"onBlur()\"\r\n />\r\n @if (isOpen) {\r\n <div [class]=\"popoverClass\" [attr.id]=\"panelId\" role=\"dialog\" aria-label=\"Choose date\">\r\n <div class=\"flex items-center justify-between\">\r\n <button type=\"button\" [class]=\"navButtonClass\" aria-label=\"Previous month\" (click)=\"prevMonth()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-3\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15.75 19.5 8.25 12l7.5-7.5\" />\r\n </svg>\r\n </button>\r\n <div class=\"flex items-center gap-2\">\r\n <select\r\n [class]=\"selectClass\"\r\n [disabled]=\"isDisabled\"\r\n [value]=\"displayMonth.getMonth()\"\r\n aria-label=\"Month\"\r\n (change)=\"onMonthChange($event)\"\r\n >\r\n @for (month of monthOptions; track month.value) {\r\n <option [value]=\"month.value\">{{ month.label }}</option>\r\n }\r\n </select>\r\n <select\r\n [class]=\"selectClass\"\r\n [disabled]=\"isDisabled\"\r\n [value]=\"displayMonth.getFullYear()\"\r\n aria-label=\"Year\"\r\n (change)=\"onYearChange($event)\"\r\n >\r\n @for (year of yearOptions; track year) {\r\n <option [value]=\"year\">{{ year }}</option>\r\n }\r\n </select>\r\n </div>\r\n <button type=\"button\" [class]=\"navButtonClass\" aria-label=\"Next month\" (click)=\"nextMonth()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-3\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m8.25 4.5 7.5 7.5-7.5 7.5\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"mt-3 grid grid-cols-7 gap-1 text-center text-xs text-(--cxs-color-on-surface-muted)\">\r\n @for (label of weekDayLabels; track label) {\r\n <div>{{ label }}</div>\r\n }\r\n </div>\r\n\r\n <div class=\"mt-2 grid grid-cols-7 gap-1\" role=\"grid\">\r\n @for (day of calendarDays; track day.key) {\r\n <button\r\n type=\"button\"\r\n [class]=\"dayButtonClass(day)\"\r\n [disabled]=\"day.disabled\"\r\n [attr.data-date]=\"day.key\"\r\n [attr.aria-selected]=\"day.key === value ? 'true' : 'false'\"\r\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\r\n (click)=\"onDateSelect(day)\"\r\n >\r\n {{ day.label }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n}\r\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
2049
+ ], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n @if (label) {\n <label [class]=\"labelClass\" [attr.id]=\"labelId\" [attr.for]=\"inputId\">\n {{ label }}\n </label>\n }\n @if (useNative) {\n <input\n type=\"date\"\n [class]=\"inputClass\"\n [attr.id]=\"inputId\"\n [attr.name]=\"name\"\n [attr.min]=\"min\"\n [attr.max]=\"max\"\n [attr.placeholder]=\"placeholder\"\n [attr.aria-label]=\"ariaLabelValue\"\n [attr.aria-labelledby]=\"labelId\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [value]=\"value\"\n [disabled]=\"isDisabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n />\n } @else {\n <div class=\"relative w-full\">\n <input\n type=\"text\"\n [class]=\"inputClass\"\n [attr.id]=\"inputId\"\n [attr.name]=\"name\"\n [attr.placeholder]=\"placeholder\"\n [attr.aria-label]=\"ariaLabelValue\"\n [attr.aria-labelledby]=\"labelId\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.aria-expanded]=\"isOpen ? 'true' : 'false'\"\n [attr.aria-controls]=\"panelId\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [attr.data-cxs-datepicker]=\"panelId\"\n [value]=\"value\"\n [disabled]=\"isDisabled\"\n [readonly]=\"true\"\n [required]=\"required\"\n (click)=\"open()\"\n (focus)=\"open()\"\n (blur)=\"onBlur()\"\n />\n @if (isOpen) {\n <div [class]=\"popoverClass\" [attr.id]=\"panelId\" role=\"dialog\" aria-label=\"Choose date\">\n <div class=\"flex items-center justify-between\">\n <button type=\"button\" [class]=\"navButtonClass\" aria-label=\"Previous month\" (click)=\"prevMonth()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-3\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15.75 19.5 8.25 12l7.5-7.5\" />\n </svg>\n </button>\n <div class=\"flex items-center gap-2\">\n <select\n [class]=\"selectClass\"\n [disabled]=\"isDisabled\"\n [value]=\"displayMonth.getMonth()\"\n aria-label=\"Month\"\n (change)=\"onMonthChange($event)\"\n >\n @for (month of monthOptions; track month.value) {\n <option [value]=\"month.value\">{{ month.label }}</option>\n }\n </select>\n <select\n [class]=\"selectClass\"\n [disabled]=\"isDisabled\"\n [value]=\"displayMonth.getFullYear()\"\n aria-label=\"Year\"\n (change)=\"onYearChange($event)\"\n >\n @for (year of yearOptions; track year) {\n <option [value]=\"year\">{{ year }}</option>\n }\n </select>\n </div>\n <button type=\"button\" [class]=\"navButtonClass\" aria-label=\"Next month\" (click)=\"nextMonth()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-3\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m8.25 4.5 7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n </div>\n\n <div class=\"mt-3 grid grid-cols-7 gap-1 text-center text-xs text-(--cxs-color-on-surface-muted)\">\n @for (label of weekDayLabels; track label) {\n <div>{{ label }}</div>\n }\n </div>\n\n <div class=\"mt-2 grid grid-cols-7 gap-1\" role=\"grid\">\n @for (day of calendarDays; track day.key) {\n <button\n type=\"button\"\n [class]=\"dayButtonClass(day)\"\n [disabled]=\"day.disabled\"\n [attr.data-date]=\"day.key\"\n [attr.aria-selected]=\"day.key === value ? 'true' : 'false'\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n (click)=\"onDateSelect(day)\"\n >\n {{ day.label }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n</div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
1795
2050
  }
1796
2051
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsDatepickerComponent, decorators: [{
1797
2052
  type: Component,
@@ -1801,7 +2056,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
1801
2056
  useExisting: forwardRef(() => CxsDatepickerComponent),
1802
2057
  multi: true
1803
2058
  }
1804
- ], template: "@if (useNative) {\r\n <input\r\n type=\"date\"\r\n [class]=\"inputClass\"\r\n [attr.id]=\"id\"\r\n [attr.name]=\"name\"\r\n [attr.min]=\"min\"\r\n [attr.max]=\"max\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"ariaDescribedby\"\r\n [attr.autofocus]=\"autofocus ? true : null\"\r\n [value]=\"value\"\r\n [disabled]=\"isDisabled\"\r\n [readonly]=\"readonly\"\r\n [required]=\"required\"\r\n (input)=\"onInput($event)\"\r\n (blur)=\"onBlur()\"\r\n />\r\n} @else {\r\n <div class=\"relative w-full\">\r\n <input\r\n type=\"text\"\r\n [class]=\"inputClass\"\r\n [attr.id]=\"id\"\r\n [attr.name]=\"name\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"ariaDescribedby\"\r\n [attr.aria-expanded]=\"isOpen ? 'true' : 'false'\"\r\n [attr.aria-controls]=\"panelId\"\r\n [attr.autofocus]=\"autofocus ? true : null\"\r\n [attr.data-cxs-datepicker]=\"panelId\"\r\n [value]=\"value\"\r\n [disabled]=\"isDisabled\"\r\n [readonly]=\"true\"\r\n [required]=\"required\"\r\n (click)=\"open()\"\r\n (focus)=\"open()\"\r\n (blur)=\"onBlur()\"\r\n />\r\n @if (isOpen) {\r\n <div [class]=\"popoverClass\" [attr.id]=\"panelId\" role=\"dialog\" aria-label=\"Choose date\">\r\n <div class=\"flex items-center justify-between\">\r\n <button type=\"button\" [class]=\"navButtonClass\" aria-label=\"Previous month\" (click)=\"prevMonth()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-3\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15.75 19.5 8.25 12l7.5-7.5\" />\r\n </svg>\r\n </button>\r\n <div class=\"flex items-center gap-2\">\r\n <select\r\n [class]=\"selectClass\"\r\n [disabled]=\"isDisabled\"\r\n [value]=\"displayMonth.getMonth()\"\r\n aria-label=\"Month\"\r\n (change)=\"onMonthChange($event)\"\r\n >\r\n @for (month of monthOptions; track month.value) {\r\n <option [value]=\"month.value\">{{ month.label }}</option>\r\n }\r\n </select>\r\n <select\r\n [class]=\"selectClass\"\r\n [disabled]=\"isDisabled\"\r\n [value]=\"displayMonth.getFullYear()\"\r\n aria-label=\"Year\"\r\n (change)=\"onYearChange($event)\"\r\n >\r\n @for (year of yearOptions; track year) {\r\n <option [value]=\"year\">{{ year }}</option>\r\n }\r\n </select>\r\n </div>\r\n <button type=\"button\" [class]=\"navButtonClass\" aria-label=\"Next month\" (click)=\"nextMonth()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-3\">\r\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m8.25 4.5 7.5 7.5-7.5 7.5\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"mt-3 grid grid-cols-7 gap-1 text-center text-xs text-(--cxs-color-on-surface-muted)\">\r\n @for (label of weekDayLabels; track label) {\r\n <div>{{ label }}</div>\r\n }\r\n </div>\r\n\r\n <div class=\"mt-2 grid grid-cols-7 gap-1\" role=\"grid\">\r\n @for (day of calendarDays; track day.key) {\r\n <button\r\n type=\"button\"\r\n [class]=\"dayButtonClass(day)\"\r\n [disabled]=\"day.disabled\"\r\n [attr.data-date]=\"day.key\"\r\n [attr.aria-selected]=\"day.key === value ? 'true' : 'false'\"\r\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\r\n (click)=\"onDateSelect(day)\"\r\n >\r\n {{ day.label }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n}\r\n" }]
2059
+ ], template: "<div [class]=\"wrapperClass\">\n @if (label) {\n <label [class]=\"labelClass\" [attr.id]=\"labelId\" [attr.for]=\"inputId\">\n {{ label }}\n </label>\n }\n @if (useNative) {\n <input\n type=\"date\"\n [class]=\"inputClass\"\n [attr.id]=\"inputId\"\n [attr.name]=\"name\"\n [attr.min]=\"min\"\n [attr.max]=\"max\"\n [attr.placeholder]=\"placeholder\"\n [attr.aria-label]=\"ariaLabelValue\"\n [attr.aria-labelledby]=\"labelId\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [value]=\"value\"\n [disabled]=\"isDisabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n />\n } @else {\n <div class=\"relative w-full\">\n <input\n type=\"text\"\n [class]=\"inputClass\"\n [attr.id]=\"inputId\"\n [attr.name]=\"name\"\n [attr.placeholder]=\"placeholder\"\n [attr.aria-label]=\"ariaLabelValue\"\n [attr.aria-labelledby]=\"labelId\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.aria-expanded]=\"isOpen ? 'true' : 'false'\"\n [attr.aria-controls]=\"panelId\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [attr.data-cxs-datepicker]=\"panelId\"\n [value]=\"value\"\n [disabled]=\"isDisabled\"\n [readonly]=\"true\"\n [required]=\"required\"\n (click)=\"open()\"\n (focus)=\"open()\"\n (blur)=\"onBlur()\"\n />\n @if (isOpen) {\n <div [class]=\"popoverClass\" [attr.id]=\"panelId\" role=\"dialog\" aria-label=\"Choose date\">\n <div class=\"flex items-center justify-between\">\n <button type=\"button\" [class]=\"navButtonClass\" aria-label=\"Previous month\" (click)=\"prevMonth()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-3\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15.75 19.5 8.25 12l7.5-7.5\" />\n </svg>\n </button>\n <div class=\"flex items-center gap-2\">\n <select\n [class]=\"selectClass\"\n [disabled]=\"isDisabled\"\n [value]=\"displayMonth.getMonth()\"\n aria-label=\"Month\"\n (change)=\"onMonthChange($event)\"\n >\n @for (month of monthOptions; track month.value) {\n <option [value]=\"month.value\">{{ month.label }}</option>\n }\n </select>\n <select\n [class]=\"selectClass\"\n [disabled]=\"isDisabled\"\n [value]=\"displayMonth.getFullYear()\"\n aria-label=\"Year\"\n (change)=\"onYearChange($event)\"\n >\n @for (year of yearOptions; track year) {\n <option [value]=\"year\">{{ year }}</option>\n }\n </select>\n </div>\n <button type=\"button\" [class]=\"navButtonClass\" aria-label=\"Next month\" (click)=\"nextMonth()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-3\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m8.25 4.5 7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n </div>\n\n <div class=\"mt-3 grid grid-cols-7 gap-1 text-center text-xs text-(--cxs-color-on-surface-muted)\">\n @for (label of weekDayLabels; track label) {\n <div>{{ label }}</div>\n }\n </div>\n\n <div class=\"mt-2 grid grid-cols-7 gap-1\" role=\"grid\">\n @for (day of calendarDays; track day.key) {\n <button\n type=\"button\"\n [class]=\"dayButtonClass(day)\"\n [disabled]=\"day.disabled\"\n [attr.data-date]=\"day.key\"\n [attr.aria-selected]=\"day.key === value ? 'true' : 'false'\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n (click)=\"onDateSelect(day)\"\n >\n {{ day.label }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n</div>\n" }]
1805
2060
  }], propDecorators: { value: [{
1806
2061
  type: Input
1807
2062
  }], variant: [{
@@ -1820,6 +2075,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
1820
2075
  type: Input
1821
2076
  }], autofocus: [{
1822
2077
  type: Input
2078
+ }], label: [{
2079
+ type: Input
1823
2080
  }], id: [{
1824
2081
  type: Input
1825
2082
  }], name: [{
@@ -1850,7 +2107,11 @@ const BASE_CLASSES$2 = 'w-full rounded-[var(--cxs-radius-md)] border border-[var
1850
2107
  'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
1851
2108
  'focus-visible:outline-[var(--cxs-color-focus)] focus-visible:border-[var(--cxs-color-focus)] ' +
1852
2109
  'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-60';
1853
- const VARIANT_CLASSES$2 = {
2110
+ const WRAPPER_CLASSES$5 = 'flex w-full flex-col gap-1';
2111
+ const LABEL_BASE_CLASSES$3 = 'font-medium text-(--cxs-color-on-surface)';
2112
+ const LABEL_DISABLED_CLASSES$3 = 'text-[var(--cxs-color-on-surface-muted)]';
2113
+ const ERROR_BASE_CLASSES = 'text-[var(--cxs-color-danger)]';
2114
+ const VARIANT_CLASSES$3 = {
1854
2115
  outline: 'bg-[var(--cxs-color-surface)]',
1855
2116
  filled: 'bg-[var(--cxs-color-surface-hover)]'
1856
2117
  };
@@ -1859,9 +2120,20 @@ const SIZE_CLASSES$1 = {
1859
2120
  md: 'h-10 px-3 text-sm',
1860
2121
  lg: 'h-12 px-4 text-base'
1861
2122
  };
1862
- const INVALID_CLASSES$2 = 'border-[var(--cxs-color-danger)] focus-visible:border-[var(--cxs-color-danger)] ' +
2123
+ const LABEL_SIZE_CLASSES$3 = {
2124
+ sm: 'text-sm',
2125
+ md: 'text-sm',
2126
+ lg: 'text-base'
2127
+ };
2128
+ const ERROR_SIZE_CLASSES = {
2129
+ sm: 'text-xs',
2130
+ md: 'text-xs',
2131
+ lg: 'text-sm'
2132
+ };
2133
+ const INVALID_CLASSES$3 = 'border-[var(--cxs-color-danger)] focus-visible:border-[var(--cxs-color-danger)] ' +
1863
2134
  'focus-visible:outline-[var(--cxs-color-danger)]';
1864
2135
  class CxsInputComponent {
2136
+ static nextId = 0;
1865
2137
  value = '';
1866
2138
  type = 'text';
1867
2139
  variant = 'outline';
@@ -1871,6 +2143,7 @@ class CxsInputComponent {
1871
2143
  required = false;
1872
2144
  invalid = false;
1873
2145
  autofocus = false;
2146
+ label;
1874
2147
  id;
1875
2148
  name;
1876
2149
  placeholder;
@@ -1880,6 +2153,7 @@ class CxsInputComponent {
1880
2153
  ariaLabel;
1881
2154
  ariaDescribedby;
1882
2155
  valueChange = new EventEmitter();
2156
+ instanceId = `cxs-input-${CxsInputComponent.nextId++}`;
1883
2157
  disabledFromControl = false;
1884
2158
  onChange = () => { };
1885
2159
  onTouched = () => { };
@@ -1890,12 +2164,55 @@ class CxsInputComponent {
1890
2164
  return [
1891
2165
  BASE_CLASSES$2,
1892
2166
  SIZE_CLASSES$1[this.size],
1893
- VARIANT_CLASSES$2[this.variant],
1894
- this.invalid ? INVALID_CLASSES$2 : ''
2167
+ VARIANT_CLASSES$3[this.variant],
2168
+ this.invalid ? INVALID_CLASSES$3 : ''
2169
+ ]
2170
+ .filter(Boolean)
2171
+ .join(' ');
2172
+ }
2173
+ get wrapperClass() {
2174
+ return WRAPPER_CLASSES$5;
2175
+ }
2176
+ get labelClass() {
2177
+ return [
2178
+ LABEL_BASE_CLASSES$3,
2179
+ LABEL_SIZE_CLASSES$3[this.size],
2180
+ this.isDisabled ? LABEL_DISABLED_CLASSES$3 : ''
1895
2181
  ]
1896
2182
  .filter(Boolean)
1897
2183
  .join(' ');
1898
2184
  }
2185
+ get inputId() {
2186
+ if (this.id) {
2187
+ return this.id;
2188
+ }
2189
+ return this.label ? this.instanceId : null;
2190
+ }
2191
+ get labelId() {
2192
+ if (!this.label) {
2193
+ return null;
2194
+ }
2195
+ return `${this.inputId}-label`;
2196
+ }
2197
+ get errorId() {
2198
+ return `${this.instanceId}-error`;
2199
+ }
2200
+ get ariaLabelValue() {
2201
+ if (this.label) {
2202
+ return null;
2203
+ }
2204
+ return this.ariaLabel ?? null;
2205
+ }
2206
+ get ariaDescribedbyValue() {
2207
+ const tokens = [this.ariaDescribedby].filter(Boolean);
2208
+ if (this.invalid) {
2209
+ tokens.push(this.errorId);
2210
+ }
2211
+ return tokens.length > 0 ? tokens.join(' ') : null;
2212
+ }
2213
+ get errorClass() {
2214
+ return [ERROR_BASE_CLASSES, ERROR_SIZE_CLASSES[this.size]].join(' ');
2215
+ }
1899
2216
  writeValue(value) {
1900
2217
  this.value = value ?? '';
1901
2218
  }
@@ -1919,23 +2236,23 @@ class CxsInputComponent {
1919
2236
  this.onTouched();
1920
2237
  }
1921
2238
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1922
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: CxsInputComponent, isStandalone: true, selector: "cxs-input", inputs: { value: "value", type: "type", variant: "variant", size: "size", disabled: "disabled", readonly: "readonly", required: "required", invalid: "invalid", autofocus: "autofocus", id: "id", name: "name", placeholder: "placeholder", autocomplete: "autocomplete", inputmode: "inputmode", spellcheck: "spellcheck", ariaLabel: "ariaLabel", ariaDescribedby: "ariaDescribedby" }, outputs: { valueChange: "valueChange" }, providers: [
2239
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsInputComponent, isStandalone: true, selector: "cxs-input", inputs: { value: "value", type: "type", variant: "variant", size: "size", disabled: "disabled", readonly: "readonly", required: "required", invalid: "invalid", autofocus: "autofocus", label: "label", id: "id", name: "name", placeholder: "placeholder", autocomplete: "autocomplete", inputmode: "inputmode", spellcheck: "spellcheck", ariaLabel: "ariaLabel", ariaDescribedby: "ariaDescribedby" }, outputs: { valueChange: "valueChange" }, providers: [
1923
2240
  {
1924
2241
  provide: NG_VALUE_ACCESSOR,
1925
2242
  useExisting: forwardRef(() => CxsInputComponent),
1926
2243
  multi: true
1927
2244
  }
1928
- ], ngImport: i0, template: "<input\r\n [class]=\"inputClass\"\r\n [attr.id]=\"id\"\r\n [attr.name]=\"name\"\r\n [attr.type]=\"type\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.autocomplete]=\"autocomplete\"\r\n [attr.inputmode]=\"inputmode\"\r\n [attr.spellcheck]=\"spellcheck === null ? null : spellcheck\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"ariaDescribedby\"\r\n [attr.aria-invalid]=\"invalid ? 'true' : null\"\r\n [attr.autofocus]=\"autofocus ? true : null\"\r\n [disabled]=\"isDisabled\"\r\n [readonly]=\"readonly\"\r\n [required]=\"required\"\r\n [value]=\"value\"\r\n (input)=\"onInput($event)\"\r\n (blur)=\"onBlur()\"\r\n/>\r\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
2245
+ ], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n @if (label) {\n <label [class]=\"labelClass\" [attr.id]=\"labelId\" [attr.for]=\"inputId\">\n {{ label }}\n </label>\n }\n <input\n [class]=\"inputClass\"\n [attr.id]=\"inputId\"\n [attr.name]=\"name\"\n [attr.type]=\"type\"\n [attr.placeholder]=\"placeholder\"\n [attr.autocomplete]=\"autocomplete\"\n [attr.inputmode]=\"inputmode\"\n [attr.spellcheck]=\"spellcheck === null ? null : spellcheck\"\n [attr.aria-label]=\"ariaLabelValue\"\n [attr.aria-labelledby]=\"labelId\"\n [attr.aria-describedby]=\"ariaDescribedbyValue\"\n [attr.aria-invalid]=\"invalid ? 'true' : null\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [disabled]=\"isDisabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n />\n @if (invalid) {\n <div [class]=\"errorClass\" [attr.id]=\"errorId\" aria-live=\"polite\">\n <ng-content select=\"[cxsInputError]\"></ng-content>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1929
2246
  }
1930
2247
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsInputComponent, decorators: [{
1931
2248
  type: Component,
1932
- args: [{ selector: 'cxs-input', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
2249
+ args: [{ selector: 'cxs-input', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
1933
2250
  {
1934
2251
  provide: NG_VALUE_ACCESSOR,
1935
2252
  useExisting: forwardRef(() => CxsInputComponent),
1936
2253
  multi: true
1937
2254
  }
1938
- ], template: "<input\r\n [class]=\"inputClass\"\r\n [attr.id]=\"id\"\r\n [attr.name]=\"name\"\r\n [attr.type]=\"type\"\r\n [attr.placeholder]=\"placeholder\"\r\n [attr.autocomplete]=\"autocomplete\"\r\n [attr.inputmode]=\"inputmode\"\r\n [attr.spellcheck]=\"spellcheck === null ? null : spellcheck\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"ariaDescribedby\"\r\n [attr.aria-invalid]=\"invalid ? 'true' : null\"\r\n [attr.autofocus]=\"autofocus ? true : null\"\r\n [disabled]=\"isDisabled\"\r\n [readonly]=\"readonly\"\r\n [required]=\"required\"\r\n [value]=\"value\"\r\n (input)=\"onInput($event)\"\r\n (blur)=\"onBlur()\"\r\n/>\r\n" }]
2255
+ ], template: "<div [class]=\"wrapperClass\">\n @if (label) {\n <label [class]=\"labelClass\" [attr.id]=\"labelId\" [attr.for]=\"inputId\">\n {{ label }}\n </label>\n }\n <input\n [class]=\"inputClass\"\n [attr.id]=\"inputId\"\n [attr.name]=\"name\"\n [attr.type]=\"type\"\n [attr.placeholder]=\"placeholder\"\n [attr.autocomplete]=\"autocomplete\"\n [attr.inputmode]=\"inputmode\"\n [attr.spellcheck]=\"spellcheck === null ? null : spellcheck\"\n [attr.aria-label]=\"ariaLabelValue\"\n [attr.aria-labelledby]=\"labelId\"\n [attr.aria-describedby]=\"ariaDescribedbyValue\"\n [attr.aria-invalid]=\"invalid ? 'true' : null\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [disabled]=\"isDisabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n />\n @if (invalid) {\n <div [class]=\"errorClass\" [attr.id]=\"errorId\" aria-live=\"polite\">\n <ng-content select=\"[cxsInputError]\"></ng-content>\n </div>\n }\n</div>\n" }]
1939
2256
  }], propDecorators: { value: [{
1940
2257
  type: Input
1941
2258
  }], type: [{
@@ -1954,6 +2271,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
1954
2271
  type: Input
1955
2272
  }], autofocus: [{
1956
2273
  type: Input
2274
+ }], label: [{
2275
+ type: Input
1957
2276
  }], id: [{
1958
2277
  type: Input
1959
2278
  }], name: [{
@@ -2115,12 +2434,467 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2115
2434
  args: ['menuItem', { read: ElementRef }]
2116
2435
  }] } });
2117
2436
 
2437
+ const WRAPPER_CLASSES$4 = 'flex w-full flex-col gap-1';
2438
+ const LABEL_BASE_CLASSES$2 = 'font-medium text-(--cxs-color-on-surface)';
2439
+ const LABEL_DISABLED_CLASSES$2 = 'text-[var(--cxs-color-on-surface-muted)]';
2440
+ const CONTROL_BASE_CLASSES = 'flex w-full flex-wrap items-center gap-2 rounded-[var(--cxs-radius-md)] border ' +
2441
+ 'border-[var(--cxs-color-border)] transition-colors ' +
2442
+ 'focus-within:outline focus-within:outline-2 focus-within:outline-offset-2 ' +
2443
+ 'focus-within:outline-[var(--cxs-color-focus)] focus-within:border-[var(--cxs-color-focus)]';
2444
+ const CONTROL_DISABLED_CLASSES = 'pointer-events-none cursor-not-allowed opacity-60';
2445
+ const VARIANT_CLASSES$2 = {
2446
+ outline: 'bg-[var(--cxs-color-surface)]',
2447
+ filled: 'bg-[var(--cxs-color-surface-hover)]'
2448
+ };
2449
+ const CONTROL_SIZE_CLASSES$1 = {
2450
+ sm: 'min-h-8 px-2 py-1 text-sm',
2451
+ md: 'min-h-10 px-3 py-1.5 text-sm',
2452
+ lg: 'min-h-12 px-4 py-2 text-base'
2453
+ };
2454
+ const LABEL_SIZE_CLASSES$2 = {
2455
+ sm: 'text-sm',
2456
+ md: 'text-sm',
2457
+ lg: 'text-base'
2458
+ };
2459
+ const INPUT_CLASSES = 'flex-1 min-w-[6rem] bg-transparent outline-none placeholder:text-[var(--cxs-color-on-surface-muted)]';
2460
+ const CHIP_BASE_CLASSES = 'inline-flex items-center gap-1 rounded-[var(--cxs-radius-sm)] ' +
2461
+ 'bg-[var(--cxs-color-surface-hover)] text-[var(--cxs-color-on-surface)]';
2462
+ const CHIP_SIZE_CLASSES = {
2463
+ sm: 'px-2 py-0.5 text-xs',
2464
+ md: 'px-2 py-0.5 text-xs',
2465
+ lg: 'px-2.5 py-1 text-sm'
2466
+ };
2467
+ const CHIP_REMOVE_CLASSES = 'inline-flex h-4 w-4 items-center justify-center rounded-full ' +
2468
+ 'text-[var(--cxs-color-on-surface-muted)] hover:text-[var(--cxs-color-on-surface)]';
2469
+ const PANEL_CLASSES$1 = 'absolute left-0 top-full z-10 mt-2 w-full rounded-[var(--cxs-radius-md)] border ' +
2470
+ 'border-[var(--cxs-color-border)] bg-[var(--cxs-color-surface)] p-1 shadow-[var(--cxs-shadow-sm)]';
2471
+ const OPTION_BASE_CLASSES = 'flex w-full items-center justify-between rounded-[var(--cxs-radius-sm)] px-3 py-2 text-left ' +
2472
+ 'text-sm text-[var(--cxs-color-on-surface)] transition-colors hover:bg-[var(--cxs-color-surface-hover)]';
2473
+ const OPTION_DISABLED_CLASSES = 'cursor-not-allowed opacity-50 hover:bg-transparent';
2474
+ const EMPTY_STATE_CLASSES = 'px-3 py-2 text-sm text-[var(--cxs-color-on-surface-muted)]';
2475
+ const INVALID_CLASSES$2 = 'border-[var(--cxs-color-danger)] focus-within:border-[var(--cxs-color-danger)] ' +
2476
+ 'focus-within:outline-[var(--cxs-color-danger)]';
2477
+ class CxsMultiSelectComponent {
2478
+ elementRef;
2479
+ static nextId = 0;
2480
+ options = [];
2481
+ value = [];
2482
+ variant = 'outline';
2483
+ size = 'md';
2484
+ disabled = false;
2485
+ readonly = false;
2486
+ invalid = false;
2487
+ placeholder;
2488
+ label;
2489
+ maxSelections;
2490
+ id;
2491
+ name;
2492
+ ariaLabel;
2493
+ ariaDescribedby;
2494
+ valueChange = new EventEmitter();
2495
+ inputEl;
2496
+ instanceId = `cxs-multi-select-${CxsMultiSelectComponent.nextId++}`;
2497
+ listId = `${this.instanceId}-list`;
2498
+ query = '';
2499
+ isOpen = false;
2500
+ disabledFromControl = false;
2501
+ onChange = () => { };
2502
+ onTouched = () => { };
2503
+ constructor(elementRef) {
2504
+ this.elementRef = elementRef;
2505
+ }
2506
+ get isDisabled() {
2507
+ return this.disabled || this.disabledFromControl;
2508
+ }
2509
+ get isAtMax() {
2510
+ return this.maxSelections !== undefined &&
2511
+ this.maxSelections !== null &&
2512
+ this.value.length >= this.maxSelections;
2513
+ }
2514
+ get wrapperClass() {
2515
+ return WRAPPER_CLASSES$4;
2516
+ }
2517
+ get labelClass() {
2518
+ return [
2519
+ LABEL_BASE_CLASSES$2,
2520
+ LABEL_SIZE_CLASSES$2[this.size],
2521
+ this.isDisabled ? LABEL_DISABLED_CLASSES$2 : ''
2522
+ ]
2523
+ .filter(Boolean)
2524
+ .join(' ');
2525
+ }
2526
+ get controlClass() {
2527
+ return [
2528
+ CONTROL_BASE_CLASSES,
2529
+ CONTROL_SIZE_CLASSES$1[this.size],
2530
+ VARIANT_CLASSES$2[this.variant],
2531
+ this.invalid ? INVALID_CLASSES$2 : '',
2532
+ this.isDisabled ? CONTROL_DISABLED_CLASSES : ''
2533
+ ]
2534
+ .filter(Boolean)
2535
+ .join(' ');
2536
+ }
2537
+ get inputClass() {
2538
+ return INPUT_CLASSES;
2539
+ }
2540
+ get chipClass() {
2541
+ return [CHIP_BASE_CLASSES, CHIP_SIZE_CLASSES[this.size]].join(' ');
2542
+ }
2543
+ get chipRemoveClass() {
2544
+ return CHIP_REMOVE_CLASSES;
2545
+ }
2546
+ get panelClass() {
2547
+ return PANEL_CLASSES$1;
2548
+ }
2549
+ get optionClass() {
2550
+ return OPTION_BASE_CLASSES;
2551
+ }
2552
+ get optionDisabledClass() {
2553
+ return OPTION_DISABLED_CLASSES;
2554
+ }
2555
+ get emptyStateClass() {
2556
+ return EMPTY_STATE_CLASSES;
2557
+ }
2558
+ get inputId() {
2559
+ if (this.id) {
2560
+ return this.id;
2561
+ }
2562
+ return this.label ? this.instanceId : null;
2563
+ }
2564
+ get labelId() {
2565
+ if (!this.label) {
2566
+ return null;
2567
+ }
2568
+ return `${this.inputId}-label`;
2569
+ }
2570
+ get ariaLabelValue() {
2571
+ if (this.label) {
2572
+ return null;
2573
+ }
2574
+ return this.ariaLabel ?? null;
2575
+ }
2576
+ get selectedOptions() {
2577
+ const optionsByValue = new Map(this.options.map((option) => [option.value, option]));
2578
+ return this.value.map((val) => optionsByValue.get(val) ?? { label: val, value: val });
2579
+ }
2580
+ get filteredOptions() {
2581
+ const selected = new Set(this.value);
2582
+ const query = this.query.trim().toLowerCase();
2583
+ return this.options.filter((option) => {
2584
+ if (selected.has(option.value)) {
2585
+ return false;
2586
+ }
2587
+ if (!query) {
2588
+ return true;
2589
+ }
2590
+ return option.label.toLowerCase().includes(query) || option.value.toLowerCase().includes(query);
2591
+ });
2592
+ }
2593
+ writeValue(value) {
2594
+ this.value = value ? [...value] : [];
2595
+ }
2596
+ registerOnChange(fn) {
2597
+ this.onChange = fn;
2598
+ }
2599
+ registerOnTouched(fn) {
2600
+ this.onTouched = fn;
2601
+ }
2602
+ setDisabledState(isDisabled) {
2603
+ this.disabledFromControl = isDisabled;
2604
+ }
2605
+ focusInput() {
2606
+ if (this.isDisabled || this.readonly) {
2607
+ return;
2608
+ }
2609
+ this.inputEl?.nativeElement.focus();
2610
+ }
2611
+ open() {
2612
+ if (this.isDisabled || this.readonly) {
2613
+ return;
2614
+ }
2615
+ this.isOpen = true;
2616
+ }
2617
+ close() {
2618
+ this.isOpen = false;
2619
+ }
2620
+ onQueryInput(event) {
2621
+ const target = event.target;
2622
+ this.query = target.value;
2623
+ this.open();
2624
+ }
2625
+ onKeydown(event) {
2626
+ if (event.key === 'Backspace' && !this.query && this.value.length > 0) {
2627
+ this.removeValue(this.value[this.value.length - 1]);
2628
+ }
2629
+ }
2630
+ selectOption(option) {
2631
+ if (this.isDisabled || this.readonly || this.isAtMax) {
2632
+ return;
2633
+ }
2634
+ if (this.value.includes(option.value)) {
2635
+ return;
2636
+ }
2637
+ const nextValue = [...this.value, option.value];
2638
+ this.updateValue(nextValue);
2639
+ this.query = '';
2640
+ this.open();
2641
+ this.focusInput();
2642
+ }
2643
+ removeValue(value) {
2644
+ if (this.isDisabled || this.readonly) {
2645
+ return;
2646
+ }
2647
+ const nextValue = this.value.filter((item) => item !== value);
2648
+ this.updateValue(nextValue);
2649
+ }
2650
+ onOptionMouseDown(event) {
2651
+ event.preventDefault();
2652
+ }
2653
+ onChipMouseDown(event) {
2654
+ event.preventDefault();
2655
+ }
2656
+ onBlur() {
2657
+ this.onTouched();
2658
+ }
2659
+ updateValue(nextValue) {
2660
+ this.value = [...nextValue];
2661
+ this.onChange(this.value);
2662
+ this.valueChange.emit(this.value);
2663
+ }
2664
+ onDocumentClick(event) {
2665
+ if (!this.isOpen) {
2666
+ return;
2667
+ }
2668
+ const target = event.target;
2669
+ if (target && !this.elementRef.nativeElement.contains(target)) {
2670
+ this.close();
2671
+ }
2672
+ }
2673
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsMultiSelectComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
2674
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsMultiSelectComponent, isStandalone: true, selector: "cxs-multi-select", inputs: { options: "options", value: "value", variant: "variant", size: "size", disabled: "disabled", readonly: "readonly", invalid: "invalid", placeholder: "placeholder", label: "label", maxSelections: "maxSelections", id: "id", name: "name", ariaLabel: "ariaLabel", ariaDescribedby: "ariaDescribedby" }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
2675
+ {
2676
+ provide: NG_VALUE_ACCESSOR,
2677
+ useExisting: forwardRef(() => CxsMultiSelectComponent),
2678
+ multi: true
2679
+ }
2680
+ ], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true }], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n @if (label) {\n <label [class]=\"labelClass\" [attr.id]=\"labelId\" [attr.for]=\"inputId\">\n {{ label }}\n </label>\n }\n <div class=\"relative\">\n <div [class]=\"controlClass\" (click)=\"focusInput()\">\n @for (chip of selectedOptions; track chip.value) {\n <span [class]=\"chipClass\">\n <span>{{ chip.label }}</span>\n <button\n type=\"button\"\n [class]=\"chipRemoveClass\"\n [attr.aria-label]=\"'Remove ' + chip.label\"\n (mousedown)=\"onChipMouseDown($event)\"\n (click)=\"removeValue(chip.value)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\"\n stroke=\"currentColor\" class=\"size-3\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\"/>\n</svg>\n </button>\n </span>\n }\n <input\n #inputEl\n type=\"text\"\n [class]=\"inputClass\"\n [attr.id]=\"inputId\"\n [attr.name]=\"name\"\n [attr.placeholder]=\"placeholder\"\n [attr.aria-label]=\"ariaLabelValue\"\n [attr.aria-labelledby]=\"labelId\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.aria-expanded]=\"isOpen ? 'true' : 'false'\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-invalid]=\"invalid ? 'true' : null\"\n [disabled]=\"isDisabled\"\n [readonly]=\"readonly || isAtMax\"\n [value]=\"query\"\n (input)=\"onQueryInput($event)\"\n (focus)=\"open()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n </div>\n @if (isOpen) {\n <div [class]=\"panelClass\" [attr.id]=\"listId\" role=\"listbox\">\n @if (filteredOptions.length === 0) {\n <div [class]=\"emptyStateClass\">\n No matches\n </div>\n } @else {\n @for (option of filteredOptions; track option.value) {\n <button\n type=\"button\"\n [class]=\"optionClass + (isAtMax || readonly ? ' ' + optionDisabledClass : '')\"\n [disabled]=\"isAtMax || readonly\"\n role=\"option\"\n (mousedown)=\"onOptionMouseDown($event)\"\n (click)=\"selectOption(option)\"\n >\n <span>{{ option.label }}</span>\n </button>\n }\n }\n </div>\n }\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2681
+ }
2682
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsMultiSelectComponent, decorators: [{
2683
+ type: Component,
2684
+ args: [{ selector: 'cxs-multi-select', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
2685
+ {
2686
+ provide: NG_VALUE_ACCESSOR,
2687
+ useExisting: forwardRef(() => CxsMultiSelectComponent),
2688
+ multi: true
2689
+ }
2690
+ ], template: "<div [class]=\"wrapperClass\">\n @if (label) {\n <label [class]=\"labelClass\" [attr.id]=\"labelId\" [attr.for]=\"inputId\">\n {{ label }}\n </label>\n }\n <div class=\"relative\">\n <div [class]=\"controlClass\" (click)=\"focusInput()\">\n @for (chip of selectedOptions; track chip.value) {\n <span [class]=\"chipClass\">\n <span>{{ chip.label }}</span>\n <button\n type=\"button\"\n [class]=\"chipRemoveClass\"\n [attr.aria-label]=\"'Remove ' + chip.label\"\n (mousedown)=\"onChipMouseDown($event)\"\n (click)=\"removeValue(chip.value)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\"\n stroke=\"currentColor\" class=\"size-3\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\"/>\n</svg>\n </button>\n </span>\n }\n <input\n #inputEl\n type=\"text\"\n [class]=\"inputClass\"\n [attr.id]=\"inputId\"\n [attr.name]=\"name\"\n [attr.placeholder]=\"placeholder\"\n [attr.aria-label]=\"ariaLabelValue\"\n [attr.aria-labelledby]=\"labelId\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.aria-expanded]=\"isOpen ? 'true' : 'false'\"\n [attr.aria-controls]=\"listId\"\n [attr.aria-invalid]=\"invalid ? 'true' : null\"\n [disabled]=\"isDisabled\"\n [readonly]=\"readonly || isAtMax\"\n [value]=\"query\"\n (input)=\"onQueryInput($event)\"\n (focus)=\"open()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n </div>\n @if (isOpen) {\n <div [class]=\"panelClass\" [attr.id]=\"listId\" role=\"listbox\">\n @if (filteredOptions.length === 0) {\n <div [class]=\"emptyStateClass\">\n No matches\n </div>\n } @else {\n @for (option of filteredOptions; track option.value) {\n <button\n type=\"button\"\n [class]=\"optionClass + (isAtMax || readonly ? ' ' + optionDisabledClass : '')\"\n [disabled]=\"isAtMax || readonly\"\n role=\"option\"\n (mousedown)=\"onOptionMouseDown($event)\"\n (click)=\"selectOption(option)\"\n >\n <span>{{ option.label }}</span>\n </button>\n }\n }\n </div>\n }\n </div>\n</div>\n" }]
2691
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { options: [{
2692
+ type: Input
2693
+ }], value: [{
2694
+ type: Input
2695
+ }], variant: [{
2696
+ type: Input
2697
+ }], size: [{
2698
+ type: Input
2699
+ }], disabled: [{
2700
+ type: Input
2701
+ }], readonly: [{
2702
+ type: Input
2703
+ }], invalid: [{
2704
+ type: Input
2705
+ }], placeholder: [{
2706
+ type: Input
2707
+ }], label: [{
2708
+ type: Input
2709
+ }], maxSelections: [{
2710
+ type: Input
2711
+ }], id: [{
2712
+ type: Input
2713
+ }], name: [{
2714
+ type: Input
2715
+ }], ariaLabel: [{
2716
+ type: Input
2717
+ }], ariaDescribedby: [{
2718
+ type: Input
2719
+ }], valueChange: [{
2720
+ type: Output
2721
+ }], inputEl: [{
2722
+ type: ViewChild,
2723
+ args: ['inputEl']
2724
+ }], onDocumentClick: [{
2725
+ type: HostListener,
2726
+ args: ['document:click', ['$event']]
2727
+ }] } });
2728
+
2729
+ class CxsTabLabelDirective {
2730
+ templateRef;
2731
+ constructor(templateRef) {
2732
+ this.templateRef = templateRef;
2733
+ }
2734
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsTabLabelDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
2735
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.16", type: CxsTabLabelDirective, isStandalone: true, selector: "[cxsTabLabel]", ngImport: i0 });
2736
+ }
2737
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsTabLabelDirective, decorators: [{
2738
+ type: Directive,
2739
+ args: [{
2740
+ selector: '[cxsTabLabel]',
2741
+ standalone: true
2742
+ }]
2743
+ }], ctorParameters: () => [{ type: i0.TemplateRef }] });
2744
+
2745
+ class CxsTabPanelComponent {
2746
+ static nextId = 0;
2747
+ id;
2748
+ label;
2749
+ disabled = false;
2750
+ labelTemplate;
2751
+ templateRef;
2752
+ instanceId = `cxs-tab-${CxsTabPanelComponent.nextId++}`;
2753
+ get resolvedId() {
2754
+ return this.id ?? this.instanceId;
2755
+ }
2756
+ get tabId() {
2757
+ return `${this.resolvedId}-tab`;
2758
+ }
2759
+ get panelId() {
2760
+ return `${this.resolvedId}-panel`;
2761
+ }
2762
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsTabPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2763
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: CxsTabPanelComponent, isStandalone: true, selector: "cxs-tab-panel", inputs: { id: "id", label: "label", disabled: "disabled" }, queries: [{ propertyName: "labelTemplate", first: true, predicate: CxsTabLabelDirective, descendants: true }], viewQueries: [{ propertyName: "templateRef", first: true, predicate: ["content"], descendants: true, static: true }], ngImport: i0, template: "<ng-template #content>\n <ng-content></ng-content>\n</ng-template>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
2764
+ }
2765
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsTabPanelComponent, decorators: [{
2766
+ type: Component,
2767
+ args: [{ selector: 'cxs-tab-panel', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #content>\n <ng-content></ng-content>\n</ng-template>\n" }]
2768
+ }], propDecorators: { id: [{
2769
+ type: Input
2770
+ }], label: [{
2771
+ type: Input
2772
+ }], disabled: [{
2773
+ type: Input
2774
+ }], labelTemplate: [{
2775
+ type: ContentChild,
2776
+ args: [CxsTabLabelDirective]
2777
+ }], templateRef: [{
2778
+ type: ViewChild,
2779
+ args: ['content', { static: true }]
2780
+ }] } });
2781
+
2782
+ const WRAPPER_CLASSES$3 = 'w-full';
2783
+ const TAB_LIST_CLASSES = 'flex flex-wrap items-center gap-6 border-b border-[var(--cxs-color-border)]';
2784
+ const TAB_BUTTON_BASE_CLASSES = 'inline-flex items-center gap-2 border-b-2 pb-3 text-sm font-medium transition-colors';
2785
+ const TAB_BUTTON_INACTIVE_CLASSES = 'border-transparent text-[var(--cxs-color-on-surface-muted)] hover:text-[var(--cxs-color-on-surface)]';
2786
+ const TAB_BUTTON_ACTIVE_CLASSES = 'border-[var(--cxs-color-primary)] text-[var(--cxs-color-primary)]';
2787
+ const TAB_BUTTON_DISABLED_CLASSES = 'cursor-not-allowed opacity-50';
2788
+ const PANEL_WRAPPER_CLASSES = 'pt-4';
2789
+ const PANEL_CLASSES = 'rounded-[var(--cxs-radius-md)] border border-[var(--cxs-color-border)] ' +
2790
+ 'bg-[var(--cxs-color-surface)] p-4 text-sm text-[var(--cxs-color-on-surface)]';
2791
+ class CxsTabsComponent {
2792
+ ariaLabel = 'Tabs';
2793
+ activeId;
2794
+ activeIdChange = new EventEmitter();
2795
+ panels;
2796
+ get wrapperClass() {
2797
+ return WRAPPER_CLASSES$3;
2798
+ }
2799
+ get tabListClass() {
2800
+ return TAB_LIST_CLASSES;
2801
+ }
2802
+ get tabButtonBaseClass() {
2803
+ return TAB_BUTTON_BASE_CLASSES;
2804
+ }
2805
+ get tabButtonInactiveClass() {
2806
+ return TAB_BUTTON_INACTIVE_CLASSES;
2807
+ }
2808
+ get tabButtonActiveClass() {
2809
+ return TAB_BUTTON_ACTIVE_CLASSES;
2810
+ }
2811
+ get tabButtonDisabledClass() {
2812
+ return TAB_BUTTON_DISABLED_CLASSES;
2813
+ }
2814
+ get panelWrapperClass() {
2815
+ return PANEL_WRAPPER_CLASSES;
2816
+ }
2817
+ get panelClass() {
2818
+ return PANEL_CLASSES;
2819
+ }
2820
+ get panelList() {
2821
+ return this.panels?.toArray() ?? [];
2822
+ }
2823
+ get activePanel() {
2824
+ return this.resolveActivePanel();
2825
+ }
2826
+ ngAfterContentInit() {
2827
+ this.ensureActiveTab();
2828
+ this.panels?.changes.subscribe(() => this.ensureActiveTab());
2829
+ }
2830
+ isActive(panel) {
2831
+ return this.activeId === panel.resolvedId;
2832
+ }
2833
+ tabButtonClass(panel) {
2834
+ return [
2835
+ TAB_BUTTON_BASE_CLASSES,
2836
+ this.isActive(panel) ? TAB_BUTTON_ACTIVE_CLASSES : TAB_BUTTON_INACTIVE_CLASSES,
2837
+ panel.disabled ? TAB_BUTTON_DISABLED_CLASSES : ''
2838
+ ]
2839
+ .filter(Boolean)
2840
+ .join(' ');
2841
+ }
2842
+ selectTab(panel) {
2843
+ if (panel.disabled) {
2844
+ return;
2845
+ }
2846
+ this.activeId = panel.resolvedId;
2847
+ this.activeIdChange.emit(panel.resolvedId);
2848
+ }
2849
+ panelLabel(panel) {
2850
+ return panel.label ?? panel.resolvedId;
2851
+ }
2852
+ ensureActiveTab() {
2853
+ const nextActive = this.resolveActivePanel();
2854
+ if (!nextActive) {
2855
+ return;
2856
+ }
2857
+ if (this.activeId !== nextActive.resolvedId) {
2858
+ this.activeId = nextActive.resolvedId;
2859
+ this.activeIdChange.emit(nextActive.resolvedId);
2860
+ }
2861
+ }
2862
+ resolveActivePanel() {
2863
+ const panels = this.panelList;
2864
+ if (!panels.length) {
2865
+ return null;
2866
+ }
2867
+ if (this.activeId) {
2868
+ const active = panels.find((panel) => panel.resolvedId === this.activeId);
2869
+ if (active && !active.disabled) {
2870
+ return active;
2871
+ }
2872
+ }
2873
+ return panels.find((panel) => !panel.disabled) ?? panels[0];
2874
+ }
2875
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsTabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2876
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsTabsComponent, isStandalone: true, selector: "cxs-tabs", inputs: { ariaLabel: "ariaLabel", activeId: "activeId" }, outputs: { activeIdChange: "activeIdChange" }, queries: [{ propertyName: "panels", predicate: CxsTabPanelComponent }], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n <div [class]=\"tabListClass\" role=\"tablist\" [attr.aria-label]=\"ariaLabel\">\n @for (panel of panelList; track panel.resolvedId) {\n <button\n type=\"button\"\n [class]=\"tabButtonClass(panel)\"\n role=\"tab\"\n [attr.id]=\"panel.tabId\"\n [attr.aria-controls]=\"panel.panelId\"\n [attr.aria-selected]=\"isActive(panel) ? 'true' : 'false'\"\n [disabled]=\"panel.disabled\"\n (click)=\"selectTab(panel)\"\n >\n @if (panel.labelTemplate) {\n <ng-container [ngTemplateOutlet]=\"panel.labelTemplate.templateRef\"></ng-container>\n } @else {\n <span>{{ panelLabel(panel) }}</span>\n }\n </button>\n }\n </div>\n\n @if (activePanel) {\n <div [class]=\"panelWrapperClass\">\n <div\n [class]=\"panelClass\"\n role=\"tabpanel\"\n [attr.id]=\"activePanel.panelId\"\n [attr.aria-labelledby]=\"activePanel.tabId\"\n >\n <ng-container [ngTemplateOutlet]=\"activePanel.templateRef\"></ng-container>\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2877
+ }
2878
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsTabsComponent, decorators: [{
2879
+ type: Component,
2880
+ args: [{ selector: 'cxs-tabs', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"wrapperClass\">\n <div [class]=\"tabListClass\" role=\"tablist\" [attr.aria-label]=\"ariaLabel\">\n @for (panel of panelList; track panel.resolvedId) {\n <button\n type=\"button\"\n [class]=\"tabButtonClass(panel)\"\n role=\"tab\"\n [attr.id]=\"panel.tabId\"\n [attr.aria-controls]=\"panel.panelId\"\n [attr.aria-selected]=\"isActive(panel) ? 'true' : 'false'\"\n [disabled]=\"panel.disabled\"\n (click)=\"selectTab(panel)\"\n >\n @if (panel.labelTemplate) {\n <ng-container [ngTemplateOutlet]=\"panel.labelTemplate.templateRef\"></ng-container>\n } @else {\n <span>{{ panelLabel(panel) }}</span>\n }\n </button>\n }\n </div>\n\n @if (activePanel) {\n <div [class]=\"panelWrapperClass\">\n <div\n [class]=\"panelClass\"\n role=\"tabpanel\"\n [attr.id]=\"activePanel.panelId\"\n [attr.aria-labelledby]=\"activePanel.tabId\"\n >\n <ng-container [ngTemplateOutlet]=\"activePanel.templateRef\"></ng-container>\n </div>\n </div>\n }\n</div>\n" }]
2881
+ }], propDecorators: { ariaLabel: [{
2882
+ type: Input
2883
+ }], activeId: [{
2884
+ type: Input
2885
+ }], activeIdChange: [{
2886
+ type: Output
2887
+ }], panels: [{
2888
+ type: ContentChildren,
2889
+ args: [CxsTabPanelComponent]
2890
+ }] } });
2891
+
2118
2892
  const WRAPPER_BASE = 'inline-flex items-center gap-2 select-none';
2119
2893
  const WRAPPER_ENABLED = 'cursor-pointer';
2120
2894
  const WRAPPER_DISABLED = 'cursor-not-allowed opacity-60';
2121
2895
  const LABEL_BASE = 'text-[var(--cxs-color-on-surface)]';
2122
2896
  const LABEL_DISABLED = 'text-[var(--cxs-color-on-surface-muted)]';
2123
- const LABEL_SIZE_CLASSES = {
2897
+ const LABEL_SIZE_CLASSES$1 = {
2124
2898
  sm: 'text-sm',
2125
2899
  md: 'text-sm',
2126
2900
  lg: 'text-base'
@@ -2179,7 +2953,7 @@ class CxsRadioComponent {
2179
2953
  get labelClass() {
2180
2954
  return [
2181
2955
  LABEL_BASE,
2182
- LABEL_SIZE_CLASSES[this.size],
2956
+ LABEL_SIZE_CLASSES$1[this.size],
2183
2957
  this.isDisabled ? LABEL_DISABLED : ''
2184
2958
  ]
2185
2959
  .filter(Boolean)
@@ -2270,6 +3044,9 @@ const BASE_CLASSES$1 = 'w-full appearance-none rounded-[var(--cxs-radius-md)] bo
2270
3044
  'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
2271
3045
  'focus-visible:outline-[var(--cxs-color-focus)] focus-visible:border-[var(--cxs-color-focus)] ' +
2272
3046
  'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-60';
3047
+ const WRAPPER_CLASSES$2 = 'flex w-full flex-col gap-1';
3048
+ const LABEL_BASE_CLASSES$1 = 'font-medium text-(--cxs-color-on-surface)';
3049
+ const LABEL_DISABLED_CLASSES$1 = 'text-[var(--cxs-color-on-surface-muted)]';
2273
3050
  const VARIANT_CLASSES$1 = {
2274
3051
  outline: 'bg-[var(--cxs-color-surface)]',
2275
3052
  filled: 'bg-[var(--cxs-color-surface-hover)]'
@@ -2279,15 +3056,22 @@ const SIZE_CLASSES = {
2279
3056
  md: 'h-10 pl-3 pr-9 text-sm',
2280
3057
  lg: 'h-12 pl-4 pr-10 text-base'
2281
3058
  };
3059
+ const LABEL_SIZE_CLASSES = {
3060
+ sm: 'text-sm',
3061
+ md: 'text-sm',
3062
+ lg: 'text-base'
3063
+ };
2282
3064
  const INVALID_CLASSES = 'border-[var(--cxs-color-danger)] focus-visible:border-[var(--cxs-color-danger)] ' +
2283
3065
  'focus-visible:outline-[var(--cxs-color-danger)]';
2284
3066
  class CxsSelectComponent {
3067
+ static nextId = 0;
2285
3068
  value = '';
2286
3069
  variant = 'outline';
2287
3070
  size = 'md';
2288
3071
  disabled = false;
2289
3072
  required = false;
2290
3073
  invalid = false;
3074
+ label;
2291
3075
  placeholder;
2292
3076
  placeholderValue = '';
2293
3077
  id;
@@ -2295,6 +3079,7 @@ class CxsSelectComponent {
2295
3079
  ariaLabel;
2296
3080
  ariaDescribedby;
2297
3081
  valueChange = new EventEmitter();
3082
+ instanceId = `cxs-select-${CxsSelectComponent.nextId++}`;
2298
3083
  disabledFromControl = false;
2299
3084
  onChange = () => { };
2300
3085
  onTouched = () => { };
@@ -2311,6 +3096,36 @@ class CxsSelectComponent {
2311
3096
  .filter(Boolean)
2312
3097
  .join(' ');
2313
3098
  }
3099
+ get wrapperClass() {
3100
+ return WRAPPER_CLASSES$2;
3101
+ }
3102
+ get labelClass() {
3103
+ return [
3104
+ LABEL_BASE_CLASSES$1,
3105
+ LABEL_SIZE_CLASSES[this.size],
3106
+ this.isDisabled ? LABEL_DISABLED_CLASSES$1 : ''
3107
+ ]
3108
+ .filter(Boolean)
3109
+ .join(' ');
3110
+ }
3111
+ get selectId() {
3112
+ if (this.id) {
3113
+ return this.id;
3114
+ }
3115
+ return this.label ? this.instanceId : null;
3116
+ }
3117
+ get labelId() {
3118
+ if (!this.label) {
3119
+ return null;
3120
+ }
3121
+ return `${this.selectId}-label`;
3122
+ }
3123
+ get ariaLabelValue() {
3124
+ if (this.label) {
3125
+ return null;
3126
+ }
3127
+ return this.ariaLabel ?? null;
3128
+ }
2314
3129
  get selectValue() {
2315
3130
  if (this.placeholder && this.value === '') {
2316
3131
  return this.placeholderValue;
@@ -2340,13 +3155,13 @@ class CxsSelectComponent {
2340
3155
  this.onTouched();
2341
3156
  }
2342
3157
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2343
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: CxsSelectComponent, isStandalone: true, selector: "cxs-select", inputs: { value: "value", variant: "variant", size: "size", disabled: "disabled", required: "required", invalid: "invalid", placeholder: "placeholder", placeholderValue: "placeholderValue", id: "id", name: "name", ariaLabel: "ariaLabel", ariaDescribedby: "ariaDescribedby" }, outputs: { valueChange: "valueChange" }, providers: [
3158
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: CxsSelectComponent, isStandalone: true, selector: "cxs-select", inputs: { value: "value", variant: "variant", size: "size", disabled: "disabled", required: "required", invalid: "invalid", label: "label", placeholder: "placeholder", placeholderValue: "placeholderValue", id: "id", name: "name", ariaLabel: "ariaLabel", ariaDescribedby: "ariaDescribedby" }, outputs: { valueChange: "valueChange" }, providers: [
2344
3159
  {
2345
3160
  provide: NG_VALUE_ACCESSOR,
2346
3161
  useExisting: forwardRef(() => CxsSelectComponent),
2347
3162
  multi: true
2348
3163
  }
2349
- ], ngImport: i0, template: "<div class=\"relative\">\r\n <select\r\n [class]=\"selectClass\"\r\n [attr.id]=\"id\"\r\n [attr.name]=\"name\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"ariaDescribedby\"\r\n [attr.aria-invalid]=\"invalid ? 'true' : null\"\r\n [disabled]=\"isDisabled\"\r\n [required]=\"required\"\r\n [value]=\"selectValue\"\r\n (change)=\"onSelectChange($event)\"\r\n (blur)=\"onBlur()\"\r\n >\r\n <option *ngIf=\"placeholder\" [value]=\"placeholderValue\" disabled>\r\n {{ placeholder }}\r\n </option>\r\n <ng-content></ng-content>\r\n </select>\r\n <span\r\n class=\"pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-[var(--cxs-color-on-surface-muted)]\"\r\n aria-hidden=\"true\"\r\n >\r\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"h-4 w-4\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n d=\"M5.23 7.21a.75.75 0 0 1 1.06.02L10 10.94l3.71-3.71a.75.75 0 1 1 1.06 1.06l-4.24 4.25a.75.75 0 0 1-1.06 0L5.21 8.29a.75.75 0 0 1 .02-1.08Z\"\r\n clip-rule=\"evenodd\"\r\n />\r\n </svg>\r\n </span>\r\n</div>\r\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3164
+ ], ngImport: i0, template: "<div [class]=\"wrapperClass\">\n <label *ngIf=\"label\" [class]=\"labelClass\" [attr.id]=\"labelId\" [attr.for]=\"selectId\">\n {{ label }}\n </label>\n <div class=\"relative\">\n <select\n [class]=\"selectClass\"\n [attr.id]=\"selectId\"\n [attr.name]=\"name\"\n [attr.aria-label]=\"ariaLabelValue\"\n [attr.aria-labelledby]=\"labelId\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.aria-invalid]=\"invalid ? 'true' : null\"\n [disabled]=\"isDisabled\"\n [required]=\"required\"\n [value]=\"selectValue\"\n (change)=\"onSelectChange($event)\"\n (blur)=\"onBlur()\"\n >\n <option *ngIf=\"placeholder\" [value]=\"placeholderValue\" disabled>\n {{ placeholder }}\n </option>\n <ng-content></ng-content>\n </select>\n <span\n class=\"pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-[var(--cxs-color-on-surface-muted)]\"\n aria-hidden=\"true\"\n >\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"h-4 w-4\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 0 1 1.06.02L10 10.94l3.71-3.71a.75.75 0 1 1 1.06 1.06l-4.24 4.25a.75.75 0 0 1-1.06 0L5.21 8.29a.75.75 0 0 1 .02-1.08Z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </span>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2350
3165
  }
2351
3166
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsSelectComponent, decorators: [{
2352
3167
  type: Component,
@@ -2356,7 +3171,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2356
3171
  useExisting: forwardRef(() => CxsSelectComponent),
2357
3172
  multi: true
2358
3173
  }
2359
- ], template: "<div class=\"relative\">\r\n <select\r\n [class]=\"selectClass\"\r\n [attr.id]=\"id\"\r\n [attr.name]=\"name\"\r\n [attr.aria-label]=\"ariaLabel\"\r\n [attr.aria-describedby]=\"ariaDescribedby\"\r\n [attr.aria-invalid]=\"invalid ? 'true' : null\"\r\n [disabled]=\"isDisabled\"\r\n [required]=\"required\"\r\n [value]=\"selectValue\"\r\n (change)=\"onSelectChange($event)\"\r\n (blur)=\"onBlur()\"\r\n >\r\n <option *ngIf=\"placeholder\" [value]=\"placeholderValue\" disabled>\r\n {{ placeholder }}\r\n </option>\r\n <ng-content></ng-content>\r\n </select>\r\n <span\r\n class=\"pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-[var(--cxs-color-on-surface-muted)]\"\r\n aria-hidden=\"true\"\r\n >\r\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"h-4 w-4\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n d=\"M5.23 7.21a.75.75 0 0 1 1.06.02L10 10.94l3.71-3.71a.75.75 0 1 1 1.06 1.06l-4.24 4.25a.75.75 0 0 1-1.06 0L5.21 8.29a.75.75 0 0 1 .02-1.08Z\"\r\n clip-rule=\"evenodd\"\r\n />\r\n </svg>\r\n </span>\r\n</div>\r\n" }]
3174
+ ], template: "<div [class]=\"wrapperClass\">\n <label *ngIf=\"label\" [class]=\"labelClass\" [attr.id]=\"labelId\" [attr.for]=\"selectId\">\n {{ label }}\n </label>\n <div class=\"relative\">\n <select\n [class]=\"selectClass\"\n [attr.id]=\"selectId\"\n [attr.name]=\"name\"\n [attr.aria-label]=\"ariaLabelValue\"\n [attr.aria-labelledby]=\"labelId\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.aria-invalid]=\"invalid ? 'true' : null\"\n [disabled]=\"isDisabled\"\n [required]=\"required\"\n [value]=\"selectValue\"\n (change)=\"onSelectChange($event)\"\n (blur)=\"onBlur()\"\n >\n <option *ngIf=\"placeholder\" [value]=\"placeholderValue\" disabled>\n {{ placeholder }}\n </option>\n <ng-content></ng-content>\n </select>\n <span\n class=\"pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-[var(--cxs-color-on-surface-muted)]\"\n aria-hidden=\"true\"\n >\n <svg viewBox=\"0 0 20 20\" fill=\"currentColor\" class=\"h-4 w-4\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 0 1 1.06.02L10 10.94l3.71-3.71a.75.75 0 1 1 1.06 1.06l-4.24 4.25a.75.75 0 0 1-1.06 0L5.21 8.29a.75.75 0 0 1 .02-1.08Z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </span>\n </div>\n</div>\n" }]
2360
3175
  }], propDecorators: { value: [{
2361
3176
  type: Input
2362
3177
  }], variant: [{
@@ -2369,6 +3184,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2369
3184
  type: Input
2370
3185
  }], invalid: [{
2371
3186
  type: Input
3187
+ }], label: [{
3188
+ type: Input
2372
3189
  }], placeholder: [{
2373
3190
  type: Input
2374
3191
  }], placeholderValue: [{
@@ -2509,25 +3326,25 @@ const TRACK_BASE_CLASSES = 'relative inline-flex items-center rounded-full borde
2509
3326
  'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
2510
3327
  'focus-visible:outline-[var(--cxs-color-focus)] disabled:pointer-events-none disabled:opacity-60';
2511
3328
  const TRACK_SIZE_CLASSES = {
2512
- sm: 'h-5 w-9 p-0.5',
3329
+ sm: 'h-6 w-11 p-0.5',
2513
3330
  md: 'h-6 w-11 p-0.5',
2514
- lg: 'h-8 w-14 p-0.5'
3331
+ lg: 'h-6 w-11 p-0.5'
2515
3332
  };
2516
3333
  const TRACK_STATE_CLASSES = {
2517
3334
  on: 'bg-[var(--cxs-color-primary)] border-[var(--cxs-color-primary)]',
2518
- off: 'bg-[var(--cxs-color-surface)] border-[var(--cxs-color-border)]'
3335
+ off: 'bg-[var(--cxs-color-surface-hover)] border-[var(--cxs-color-border)]'
2519
3336
  };
2520
- const THUMB_BASE_CLASSES = 'absolute left-0.5 top-0.5 rounded-full transition-transform duration-200 ease-out';
3337
+ const THUMB_BASE_CLASSES = 'absolute left-0.5 top-1/2 -translate-y-1/2 rounded-full transition-transform duration-200 ease-out';
2521
3338
  const THUMB_SIZE_CLASSES = {
2522
- sm: 'h-4 w-4',
3339
+ sm: 'h-5 w-5',
2523
3340
  md: 'h-5 w-5',
2524
- lg: 'h-7 w-7'
3341
+ lg: 'h-5 w-5'
2525
3342
  };
2526
3343
  const THUMB_STATE_CLASSES = {
2527
3344
  on: {
2528
- sm: 'translate-x-[18px] bg-[var(--cxs-color-on-primary)]',
2529
- md: 'translate-x-[22px] bg-[var(--cxs-color-on-primary)]',
2530
- lg: 'translate-x-[26px] bg-[var(--cxs-color-on-primary)]'
3345
+ sm: 'translate-x-[20px] bg-[var(--cxs-color-on-primary)]',
3346
+ md: 'translate-x-[20px] bg-[var(--cxs-color-on-primary)]',
3347
+ lg: 'translate-x-[20px] bg-[var(--cxs-color-on-primary)]'
2531
3348
  },
2532
3349
  off: 'translate-x-0 bg-[var(--cxs-color-surface)]'
2533
3350
  };
@@ -2710,11 +3527,11 @@ class CxsToastComponent {
2710
3527
  }
2711
3528
  }
2712
3529
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsToastComponent, deps: [{ token: 'class', attribute: true }], target: i0.ɵɵFactoryTarget.Component });
2713
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsToastComponent, isStandalone: true, selector: "cxs-toast", inputs: { open: "open", title: "title", message: "message", ariaLabel: "ariaLabel", variant: "variant", dismissible: "dismissible", duration: "duration", position: "position", maxWidth: "maxWidth" }, outputs: { openChange: "openChange", dismissed: "dismissed" }, usesOnChanges: true, ngImport: i0, template: "@if (open) {\n <div [class]=\"hostClassName\">\n <div\n [class]=\"toastClass\"\n [attr.role]=\"role\"\n [attr.aria-live]=\"ariaLive\"\n [attr.aria-label]=\"ariaLabelValue\"\n >\n <div class=\"flex-1\">\n @if (title) {\n <p [class]=\"titleClass\">{{ title }}</p>\n }\n @if (message) {\n <p [class]=\"messageClass\">{{ message }}</p>\n }\n <ng-content></ng-content>\n <div [class]=\"actionsClass\">\n <ng-content select=\"[cxsToastAction]\"></ng-content>\n </div>\n </div>\n @if (dismissible) {\n <button\n type=\"button\"\n [class]=\"closeButtonClass\"\n aria-label=\"Dismiss notification\"\n (click)=\"requestClose('dismiss')\"\n >\n X\n </button>\n }\n </div>\n </div>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
3530
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsToastComponent, isStandalone: true, selector: "cxs-toast", inputs: { open: "open", title: "title", message: "message", ariaLabel: "ariaLabel", variant: "variant", dismissible: "dismissible", duration: "duration", position: "position", maxWidth: "maxWidth" }, outputs: { openChange: "openChange", dismissed: "dismissed" }, usesOnChanges: true, ngImport: i0, template: "@if (open) {\n <div [class]=\"hostClassName\">\n <div\n [class]=\"toastClass\"\n [attr.role]=\"role\"\n [attr.aria-live]=\"ariaLive\"\n [attr.aria-label]=\"ariaLabelValue\"\n >\n <div class=\"flex-1\">\n @if (title) {\n <p [class]=\"titleClass\">{{ title }}</p>\n }\n @if (message) {\n <p [class]=\"messageClass\">{{ message }}</p>\n }\n <ng-content></ng-content>\n <div [class]=\"actionsClass\">\n <ng-content select=\"[cxsToastAction]\"></ng-content>\n </div>\n </div>\n @if (dismissible) {\n <button\n type=\"button\"\n [class]=\"closeButtonClass\"\n aria-label=\"Dismiss notification\"\n (click)=\"requestClose('dismiss')\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-6\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\" />\n </svg>\n\n </button>\n }\n </div>\n </div>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
2714
3531
  }
2715
3532
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsToastComponent, decorators: [{
2716
3533
  type: Component,
2717
- args: [{ selector: 'cxs-toast', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open) {\n <div [class]=\"hostClassName\">\n <div\n [class]=\"toastClass\"\n [attr.role]=\"role\"\n [attr.aria-live]=\"ariaLive\"\n [attr.aria-label]=\"ariaLabelValue\"\n >\n <div class=\"flex-1\">\n @if (title) {\n <p [class]=\"titleClass\">{{ title }}</p>\n }\n @if (message) {\n <p [class]=\"messageClass\">{{ message }}</p>\n }\n <ng-content></ng-content>\n <div [class]=\"actionsClass\">\n <ng-content select=\"[cxsToastAction]\"></ng-content>\n </div>\n </div>\n @if (dismissible) {\n <button\n type=\"button\"\n [class]=\"closeButtonClass\"\n aria-label=\"Dismiss notification\"\n (click)=\"requestClose('dismiss')\"\n >\n X\n </button>\n }\n </div>\n </div>\n}\n" }]
3534
+ args: [{ selector: 'cxs-toast', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open) {\n <div [class]=\"hostClassName\">\n <div\n [class]=\"toastClass\"\n [attr.role]=\"role\"\n [attr.aria-live]=\"ariaLive\"\n [attr.aria-label]=\"ariaLabelValue\"\n >\n <div class=\"flex-1\">\n @if (title) {\n <p [class]=\"titleClass\">{{ title }}</p>\n }\n @if (message) {\n <p [class]=\"messageClass\">{{ message }}</p>\n }\n <ng-content></ng-content>\n <div [class]=\"actionsClass\">\n <ng-content select=\"[cxsToastAction]\"></ng-content>\n </div>\n </div>\n @if (dismissible) {\n <button\n type=\"button\"\n [class]=\"closeButtonClass\"\n aria-label=\"Dismiss notification\"\n (click)=\"requestClose('dismiss')\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"size-6\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\" />\n </svg>\n\n </button>\n }\n </div>\n </div>\n}\n" }]
2718
3535
  }], ctorParameters: () => [{ type: undefined, decorators: [{
2719
3536
  type: Attribute,
2720
3537
  args: ['class']
@@ -2932,5 +3749,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2932
3749
  * Generated bundle index. Do not edit.
2933
3750
  */
2934
3751
 
2935
- export { CerxosUi, CxsAccordionComponent, CxsAccordionItemComponent, CxsAlertComponent, CxsAvatarComponent, CxsBadgeComponent, CxsBreadcrumbComponent, CxsButtonComponent, CxsCardComponent, CxsCarouselComponent, CxsCheckboxComponent, CxsDataTableCellDirective, CxsDataTableComponent, CxsDatepickerComponent, CxsDialogComponent, CxsInputComponent, CxsMenubarComponent, CxsRadioComponent, CxsSelectComponent, CxsTableComponent, CxsThemeDirective, CxsToastComponent, CxsToggleComponent, CxsTooltipComponent };
3752
+ export { CerxosUi, CxsAccordionComponent, CxsAccordionItemComponent, CxsActionMenuComponent, CxsAlertComponent, CxsAvatarComponent, CxsBadgeComponent, CxsBreadcrumbComponent, CxsButtonComponent, CxsCardComponent, CxsCarouselComponent, CxsCheckboxComponent, CxsDataTableCellDirective, CxsDataTableComponent, CxsDatepickerComponent, CxsDialogComponent, CxsInputComponent, CxsMenubarComponent, CxsMultiSelectComponent, CxsRadioComponent, CxsSelectComponent, CxsTabLabelDirective, CxsTabPanelComponent, CxsTableComponent, CxsTabsComponent, CxsThemeDirective, CxsToastComponent, CxsToggleComponent, CxsTooltipComponent };
2936
3753
  //# sourceMappingURL=cerxos-ui.mjs.map