cerxos-ui 0.0.1 → 0.0.3

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,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, Input, ChangeDetectionStrategy, EventEmitter, forwardRef, Output } from '@angular/core';
3
- import { NgIf } from '@angular/common';
2
+ import { Component, EventEmitter, Output, Input, ChangeDetectionStrategy, Attribute, forwardRef, HostListener, Directive } from '@angular/core';
4
3
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
+ import { NgIf } from '@angular/common';
5
5
 
6
6
  class CerxosUi {
7
7
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CerxosUi, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -20,40 +20,225 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
20
20
  ` }]
21
21
  }] });
22
22
 
23
- const BASE_CLASSES$2 = 'relative inline-flex items-center justify-center gap-2 whitespace-nowrap font-medium transition-colors ' +
23
+ const BASE_CLASSES$7 = 'relative flex w-full gap-3 rounded-[var(--cxs-radius-md)] border border-l-4 px-4 py-3 text-sm ' +
24
+ 'text-[var(--cxs-color-on-surface)]';
25
+ const VARIANT_CLASSES$6 = {
26
+ info: 'border-[var(--cxs-color-primary)] border-l-[var(--cxs-color-primary)] ' +
27
+ 'bg-[var(--cxs-color-primary-ghost)]',
28
+ neutral: 'border-[var(--cxs-color-border)] border-l-[var(--cxs-color-border)] ' +
29
+ 'bg-[var(--cxs-color-surface)]',
30
+ danger: 'border-[var(--cxs-color-danger)] border-l-[var(--cxs-color-danger)] ' +
31
+ 'bg-[var(--cxs-color-surface)]'
32
+ };
33
+ const TITLE_BASE = 'font-semibold';
34
+ const TITLE_VARIANT = {
35
+ info: 'text-[var(--cxs-color-primary)]',
36
+ neutral: 'text-[var(--cxs-color-on-surface)]',
37
+ danger: 'text-[var(--cxs-color-danger)]'
38
+ };
39
+ const CLOSE_BUTTON_CLASSES = 'ml-auto inline-flex h-8 w-8 items-center justify-center rounded-[var(--cxs-radius-md)] ' +
40
+ 'text-[var(--cxs-color-on-surface)] transition-colors hover:bg-[var(--cxs-color-surface-hover)] ' +
41
+ 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
42
+ 'focus-visible:outline-[var(--cxs-color-focus)]';
43
+ class CxsAlertComponent {
44
+ variant = 'info';
45
+ title;
46
+ dismissible = false;
47
+ closed = new EventEmitter();
48
+ isVisible = true;
49
+ get alertClass() {
50
+ return [BASE_CLASSES$7, VARIANT_CLASSES$6[this.variant]].join(' ');
51
+ }
52
+ get titleClass() {
53
+ return [TITLE_BASE, TITLE_VARIANT[this.variant]].join(' ');
54
+ }
55
+ get closeButtonClass() {
56
+ return CLOSE_BUTTON_CLASSES;
57
+ }
58
+ onClose() {
59
+ this.isVisible = false;
60
+ this.closed.emit();
61
+ }
62
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsAlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
63
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsAlertComponent, isStandalone: true, selector: "cxs-alert", inputs: { variant: "variant", title: "title", dismissible: "dismissible" }, outputs: { closed: "closed" }, ngImport: i0, template: "@if (isVisible) {\n <div [class]=\"alertClass\" role=\"status\" aria-live=\"polite\">\n <div class=\"flex flex-col gap-1\">\n @if (title) {\n <div [class]=\"titleClass\">{{ title }}</div>\n }\n <div class=\"text-[var(--cxs-color-on-surface)]\">\n <ng-content></ng-content>\n </div>\n </div>\n @if (dismissible) {\n <button\n type=\"button\"\n [class]=\"closeButtonClass\"\n aria-label=\"Dismiss alert\"\n (click)=\"onClose()\"\n >\n x\n </button>\n }\n </div>\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
64
+ }
65
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsAlertComponent, decorators: [{
66
+ type: Component,
67
+ args: [{ selector: 'cxs-alert', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (isVisible) {\n <div [class]=\"alertClass\" role=\"status\" aria-live=\"polite\">\n <div class=\"flex flex-col gap-1\">\n @if (title) {\n <div [class]=\"titleClass\">{{ title }}</div>\n }\n <div class=\"text-[var(--cxs-color-on-surface)]\">\n <ng-content></ng-content>\n </div>\n </div>\n @if (dismissible) {\n <button\n type=\"button\"\n [class]=\"closeButtonClass\"\n aria-label=\"Dismiss alert\"\n (click)=\"onClose()\"\n >\n x\n </button>\n }\n </div>\n}\n" }]
68
+ }], propDecorators: { variant: [{
69
+ type: Input
70
+ }], title: [{
71
+ type: Input
72
+ }], dismissible: [{
73
+ type: Input
74
+ }], closed: [{
75
+ type: Output
76
+ }] } });
77
+
78
+ const BASE_CLASSES$6 = 'inline-flex items-center gap-1 rounded-[var(--cxs-radius-md)] border px-2.5 py-0.5 text-xs font-medium ' +
79
+ 'leading-none';
80
+ const VARIANT_CLASSES$5 = {
81
+ primary: 'border-[var(--cxs-color-primary)] bg-[var(--cxs-color-primary-ghost)] ' +
82
+ 'text-[var(--cxs-color-primary)]',
83
+ neutral: 'border-[var(--cxs-color-border)] bg-[var(--cxs-color-surface)] ' +
84
+ 'text-[var(--cxs-color-on-surface)]',
85
+ danger: 'border-[var(--cxs-color-danger)] bg-[var(--cxs-color-surface)] ' +
86
+ 'text-[var(--cxs-color-danger)]'
87
+ };
88
+ const SIZE_CLASSES$6 = {
89
+ sm: 'text-[11px]',
90
+ md: 'text-xs'
91
+ };
92
+ class CxsBadgeComponent {
93
+ variant = 'primary';
94
+ size = 'md';
95
+ get badgeClass() {
96
+ return [BASE_CLASSES$6, VARIANT_CLASSES$5[this.variant], SIZE_CLASSES$6[this.size]].join(' ');
97
+ }
98
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
99
+ 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\">\n <ng-content></ng-content>\n</span>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
100
+ }
101
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsBadgeComponent, decorators: [{
102
+ type: Component,
103
+ args: [{ selector: 'cxs-badge', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<span [class]=\"badgeClass\">\n <ng-content></ng-content>\n</span>\n" }]
104
+ }], propDecorators: { variant: [{
105
+ type: Input
106
+ }], size: [{
107
+ type: Input
108
+ }] } });
109
+
110
+ const BASE_CLASSES$5 = 'flex flex-wrap items-center gap-x-1 gap-y-1';
111
+ const ITEM_CLASSES = 'flex items-center gap-1';
112
+ const LINK_BASE_CLASSES = 'rounded-[var(--cxs-radius-md)] transition-colors focus-visible:outline focus-visible:outline-2 ' +
113
+ 'focus-visible:outline-offset-2 focus-visible:outline-[var(--cxs-color-focus)]';
114
+ const NON_LINK_CLASSES = 'text-[var(--cxs-color-on-surface-muted)]';
115
+ const SEPARATOR_CLASSES = 'text-[var(--cxs-color-on-surface-muted)] select-none';
116
+ const DISABLED_CLASSES = 'text-[var(--cxs-color-on-surface-muted)] opacity-60';
117
+ const SIZE_CLASSES$5 = {
118
+ sm: 'text-xs',
119
+ md: 'text-sm',
120
+ lg: 'text-base'
121
+ };
122
+ const LINK_VARIANT_CLASSES = {
123
+ default: 'text-[var(--cxs-color-primary)] hover:text-[var(--cxs-color-primary-hover)]',
124
+ muted: 'text-[var(--cxs-color-on-surface-muted)] hover:text-[var(--cxs-color-on-surface)]'
125
+ };
126
+ const CURRENT_VARIANT_CLASSES = {
127
+ default: 'text-[var(--cxs-color-on-surface)]',
128
+ muted: 'text-[var(--cxs-color-on-surface-muted)]'
129
+ };
130
+ class CxsBreadcrumbComponent {
131
+ items = [];
132
+ separator = '/';
133
+ ariaLabel = 'Breadcrumb';
134
+ size = 'md';
135
+ variant = 'default';
136
+ disabled = false;
137
+ get listClass() {
138
+ return [BASE_CLASSES$5, SIZE_CLASSES$5[this.size], this.disabled ? 'opacity-60' : '']
139
+ .filter(Boolean)
140
+ .join(' ');
141
+ }
142
+ get itemClass() {
143
+ return ITEM_CLASSES;
144
+ }
145
+ get separatorClass() {
146
+ return SEPARATOR_CLASSES;
147
+ }
148
+ isLink(item, isLast) {
149
+ return !!item.href && !isLast && !item.disabled && !this.disabled;
150
+ }
151
+ getLinkClass(item) {
152
+ return [
153
+ LINK_BASE_CLASSES,
154
+ LINK_VARIANT_CLASSES[this.variant],
155
+ item.disabled || this.disabled ? DISABLED_CLASSES : ''
156
+ ]
157
+ .filter(Boolean)
158
+ .join(' ');
159
+ }
160
+ getLabelClass(item, isLast) {
161
+ if (isLast) {
162
+ return [
163
+ CURRENT_VARIANT_CLASSES[this.variant],
164
+ item.disabled || this.disabled ? DISABLED_CLASSES : ''
165
+ ]
166
+ .filter(Boolean)
167
+ .join(' ');
168
+ }
169
+ return [NON_LINK_CLASSES, item.disabled || this.disabled ? DISABLED_CLASSES : '']
170
+ .filter(Boolean)
171
+ .join(' ');
172
+ }
173
+ getItemRel(item) {
174
+ if (item.target === '_blank') {
175
+ return item.rel ?? 'noopener noreferrer';
176
+ }
177
+ return item.rel ?? null;
178
+ }
179
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsBreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
180
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsBreadcrumbComponent, isStandalone: true, selector: "cxs-breadcrumb", inputs: { items: "items", separator: "separator", ariaLabel: "ariaLabel", size: "size", variant: "variant", disabled: "disabled" }, ngImport: i0, template: "<nav [attr.aria-label]=\"ariaLabel\">\n <ol [class]=\"listClass\">\n @for (item of items; track item; let last = $last) {\n <li [class]=\"itemClass\">\n @if (isLink(item, last)) {\n <a\n [class]=\"getLinkClass(item)\"\n [attr.href]=\"item.href\"\n [attr.target]=\"item.target ?? null\"\n [attr.rel]=\"getItemRel(item)\"\n [attr.aria-label]=\"item.ariaLabel ?? null\"\n >\n {{ item.label }}\n </a>\n } @else {\n <span\n [class]=\"getLabelClass(item, last)\"\n [attr.aria-current]=\"last ? 'page' : null\"\n >\n {{ item.label }}\n </span>\n }\n @if (!last && separator) {\n <span [class]=\"separatorClass\" aria-hidden=\"true\">{{ separator }}</span>\n }\n </li>\n }\n </ol>\n</nav>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
181
+ }
182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsBreadcrumbComponent, decorators: [{
183
+ type: Component,
184
+ args: [{ selector: 'cxs-breadcrumb', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav [attr.aria-label]=\"ariaLabel\">\n <ol [class]=\"listClass\">\n @for (item of items; track item; let last = $last) {\n <li [class]=\"itemClass\">\n @if (isLink(item, last)) {\n <a\n [class]=\"getLinkClass(item)\"\n [attr.href]=\"item.href\"\n [attr.target]=\"item.target ?? null\"\n [attr.rel]=\"getItemRel(item)\"\n [attr.aria-label]=\"item.ariaLabel ?? null\"\n >\n {{ item.label }}\n </a>\n } @else {\n <span\n [class]=\"getLabelClass(item, last)\"\n [attr.aria-current]=\"last ? 'page' : null\"\n >\n {{ item.label }}\n </span>\n }\n @if (!last && separator) {\n <span [class]=\"separatorClass\" aria-hidden=\"true\">{{ separator }}</span>\n }\n </li>\n }\n </ol>\n</nav>\n" }]
185
+ }], propDecorators: { items: [{
186
+ type: Input
187
+ }], separator: [{
188
+ type: Input
189
+ }], ariaLabel: [{
190
+ type: Input
191
+ }], size: [{
192
+ type: Input
193
+ }], variant: [{
194
+ type: Input
195
+ }], disabled: [{
196
+ type: Input
197
+ }] } });
198
+
199
+ const BASE_CLASSES$4 = 'relative inline-flex items-center justify-center gap-2 whitespace-nowrap font-medium transition-colors ' +
24
200
  'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
25
201
  'focus-visible:outline-[var(--cxs-color-focus)] disabled:pointer-events-none disabled:opacity-50';
26
- const VARIANT_CLASSES$2 = {
202
+ const VARIANT_CLASSES$4 = {
27
203
  primary: 'bg-[var(--cxs-color-primary)] text-[var(--cxs-color-on-primary)] ' +
28
204
  'hover:bg-[var(--cxs-color-primary-hover)] shadow-[var(--cxs-shadow-sm)]',
29
205
  secondary: 'bg-[var(--cxs-color-surface)] text-[var(--cxs-color-on-surface)] ' +
30
206
  'border border-[var(--cxs-color-border)] hover:bg-[var(--cxs-color-surface-hover)]',
31
207
  ghost: 'bg-transparent text-[var(--cxs-color-primary)] hover:bg-[var(--cxs-color-primary-ghost)]'
32
208
  };
33
- const SIZE_CLASSES$2 = {
209
+ const SIZE_CLASSES$4 = {
34
210
  sm: 'h-8 px-3 text-sm rounded-[var(--cxs-radius-md)]',
35
211
  md: 'h-10 px-4 text-sm rounded-[var(--cxs-radius-md)]',
36
212
  lg: 'h-12 px-5 text-base rounded-[var(--cxs-radius-md)]'
37
213
  };
38
214
  class CxsButtonComponent {
215
+ hostClass;
39
216
  variant = 'primary';
40
217
  size = 'md';
41
218
  disabled = false;
42
219
  loading = false;
43
220
  type = 'button';
221
+ constructor(hostClass) {
222
+ this.hostClass = hostClass;
223
+ }
44
224
  get isDisabled() {
45
225
  return this.disabled || this.loading;
46
226
  }
47
227
  get buttonClass() {
48
- return [BASE_CLASSES$2, SIZE_CLASSES$2[this.size], VARIANT_CLASSES$2[this.variant]].join(' ');
228
+ return [BASE_CLASSES$4, SIZE_CLASSES$4[this.size], VARIANT_CLASSES$4[this.variant], this.hostClass]
229
+ .filter(Boolean)
230
+ .join(' ');
49
231
  }
50
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
51
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: CxsButtonComponent, isStandalone: true, selector: "cxs-button", inputs: { variant: "variant", size: "size", disabled: "disabled", loading: "loading", type: "type" }, ngImport: i0, template: "<button\n [class]=\"buttonClass\"\n [attr.type]=\"type\"\n [disabled]=\"isDisabled\"\n [attr.aria-busy]=\"loading ? 'true' : null\"\n>\n <span\n *ngIf=\"loading\"\n class=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"truncate\">\n <ng-content></ng-content>\n </span>\n</button>\n", dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
232
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsButtonComponent, deps: [{ token: 'class', attribute: true }], target: i0.ɵɵFactoryTarget.Component });
233
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsButtonComponent, isStandalone: true, selector: "cxs-button", inputs: { variant: "variant", size: "size", disabled: "disabled", loading: "loading", type: "type" }, ngImport: i0, template: "<button\n [class]=\"buttonClass\"\n [attr.type]=\"type\"\n [disabled]=\"isDisabled\"\n [attr.aria-busy]=\"loading ? 'true' : null\"\n>\n @if (loading) {\n <span\n class=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\"\n aria-hidden=\"true\"\n ></span>\n }\n <span class=\"truncate\">\n <ng-content></ng-content>\n </span>\n</button>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
52
234
  }
53
235
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsButtonComponent, decorators: [{
54
236
  type: Component,
55
- args: [{ selector: 'cxs-button', standalone: true, imports: [NgIf], changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n [class]=\"buttonClass\"\n [attr.type]=\"type\"\n [disabled]=\"isDisabled\"\n [attr.aria-busy]=\"loading ? 'true' : null\"\n>\n <span\n *ngIf=\"loading\"\n class=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"truncate\">\n <ng-content></ng-content>\n </span>\n</button>\n" }]
56
- }], propDecorators: { variant: [{
237
+ args: [{ selector: 'cxs-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n [class]=\"buttonClass\"\n [attr.type]=\"type\"\n [disabled]=\"isDisabled\"\n [attr.aria-busy]=\"loading ? 'true' : null\"\n>\n @if (loading) {\n <span\n class=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\"\n aria-hidden=\"true\"\n ></span>\n }\n <span class=\"truncate\">\n <ng-content></ng-content>\n </span>\n</button>\n" }]
238
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
239
+ type: Attribute,
240
+ args: ['class']
241
+ }] }], propDecorators: { variant: [{
57
242
  type: Input
58
243
  }], size: [{
59
244
  type: Input
@@ -65,6 +250,472 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
65
250
  type: Input
66
251
  }] } });
67
252
 
253
+ const BASE_CLASSES$3 = 'rounded-[var(--cxs-radius-md)] border border-[var(--cxs-color-border)] ' +
254
+ 'bg-[var(--cxs-color-surface)] text-[var(--cxs-color-on-surface)]';
255
+ const VARIANT_CLASSES$3 = {
256
+ surface: 'bg-[var(--cxs-color-surface)]',
257
+ muted: 'bg-[var(--cxs-color-surface-hover)]',
258
+ outline: 'bg-transparent'
259
+ };
260
+ const SIZE_CLASSES$3 = {
261
+ sm: 'p-3',
262
+ md: 'p-5',
263
+ lg: 'p-7'
264
+ };
265
+ class CxsCardComponent {
266
+ variant = 'surface';
267
+ size = 'md';
268
+ elevated = true;
269
+ ariaLabel;
270
+ ariaLabelledby;
271
+ get cardClass() {
272
+ return [
273
+ BASE_CLASSES$3,
274
+ VARIANT_CLASSES$3[this.variant],
275
+ SIZE_CLASSES$3[this.size],
276
+ this.elevated ? 'shadow-[var(--cxs-shadow-sm)]' : ''
277
+ ]
278
+ .filter(Boolean)
279
+ .join(' ');
280
+ }
281
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
282
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: CxsCardComponent, isStandalone: true, selector: "cxs-card", inputs: { variant: "variant", size: "size", elevated: "elevated", ariaLabel: "ariaLabel", ariaLabelledby: "ariaLabelledby" }, ngImport: i0, template: "<section\n [class]=\"cardClass\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-labelledby]=\"ariaLabelledby\"\n>\n <ng-content></ng-content>\n</section>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
283
+ }
284
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsCardComponent, decorators: [{
285
+ type: Component,
286
+ args: [{ selector: 'cxs-card', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<section\n [class]=\"cardClass\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-labelledby]=\"ariaLabelledby\"\n>\n <ng-content></ng-content>\n</section>\n" }]
287
+ }], propDecorators: { variant: [{
288
+ type: Input
289
+ }], size: [{
290
+ type: Input
291
+ }], elevated: [{
292
+ type: Input
293
+ }], ariaLabel: [{
294
+ type: Input
295
+ }], ariaLabelledby: [{
296
+ type: Input
297
+ }] } });
298
+
299
+ const WRAPPER_BASE$1 = 'inline-flex items-center gap-2 select-none';
300
+ const WRAPPER_ENABLED$1 = 'cursor-pointer';
301
+ const WRAPPER_DISABLED$1 = 'cursor-not-allowed opacity-60';
302
+ const LABEL_BASE$1 = 'text-[var(--cxs-color-on-surface)]';
303
+ const LABEL_DISABLED$1 = 'text-[var(--cxs-color-on-surface-muted)]';
304
+ const LABEL_SIZE_CLASSES$1 = {
305
+ sm: 'text-sm',
306
+ md: 'text-sm',
307
+ lg: 'text-base'
308
+ };
309
+ const CONTROL_BASE$1 = "relative flex shrink-0 items-center justify-center rounded-[var(--cxs-radius-md)] border " +
310
+ "border-[var(--cxs-color-border)] bg-[var(--cxs-color-surface)] text-[var(--cxs-color-on-primary)] " +
311
+ "transition-colors after:absolute after:origin-center after:rotate-45 after:content-[''] " +
312
+ 'after:opacity-0 after:transition-opacity after:border-b-2 after:border-r-2 after:border-current ' +
313
+ "before:absolute before:content-[''] before:opacity-0 before:transition-opacity before:bg-current " +
314
+ 'peer-checked:bg-[var(--cxs-color-primary)] peer-checked:border-[var(--cxs-color-primary)] ' +
315
+ 'peer-checked:after:opacity-100 ' +
316
+ 'peer-indeterminate:bg-[var(--cxs-color-primary)] peer-indeterminate:border-[var(--cxs-color-primary)] ' +
317
+ 'peer-indeterminate:before:opacity-100 peer-indeterminate:after:opacity-0 ' +
318
+ 'peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 ' +
319
+ 'peer-focus-visible:outline-[var(--cxs-color-focus)]';
320
+ const CONTROL_SIZE_CLASSES$1 = {
321
+ sm: 'h-4 w-4',
322
+ md: 'h-5 w-5',
323
+ lg: 'h-6 w-6'
324
+ };
325
+ const MARK_SIZE_CLASSES = {
326
+ sm: 'after:h-2 after:w-1 before:h-0.5 before:w-2',
327
+ md: 'after:h-2.5 after:w-1.5 before:h-0.5 before:w-3',
328
+ lg: 'after:h-3 after:w-2 before:h-0.5 before:w-4'
329
+ };
330
+ class CxsCheckboxComponent {
331
+ checked = false;
332
+ indeterminate = false;
333
+ disabled = false;
334
+ label;
335
+ size = 'md';
336
+ id;
337
+ name;
338
+ required = false;
339
+ autofocus = false;
340
+ ariaLabel;
341
+ ariaDescribedby;
342
+ valueChange = new EventEmitter();
343
+ disabledFromControl = false;
344
+ onChange = () => { };
345
+ onTouched = () => { };
346
+ get isDisabled() {
347
+ return this.disabled || this.disabledFromControl;
348
+ }
349
+ get wrapperClass() {
350
+ return [
351
+ WRAPPER_BASE$1,
352
+ this.isDisabled ? WRAPPER_DISABLED$1 : WRAPPER_ENABLED$1
353
+ ].join(' ');
354
+ }
355
+ get labelClass() {
356
+ return [
357
+ LABEL_BASE$1,
358
+ LABEL_SIZE_CLASSES$1[this.size],
359
+ this.isDisabled ? LABEL_DISABLED$1 : ''
360
+ ]
361
+ .filter(Boolean)
362
+ .join(' ');
363
+ }
364
+ get controlClass() {
365
+ return [
366
+ CONTROL_BASE$1,
367
+ CONTROL_SIZE_CLASSES$1[this.size],
368
+ MARK_SIZE_CLASSES[this.size]
369
+ ].join(' ');
370
+ }
371
+ get ariaChecked() {
372
+ return this.indeterminate ? 'mixed' : null;
373
+ }
374
+ writeValue(value) {
375
+ this.checked = value ?? false;
376
+ }
377
+ registerOnChange(fn) {
378
+ this.onChange = fn;
379
+ }
380
+ registerOnTouched(fn) {
381
+ this.onTouched = fn;
382
+ }
383
+ setDisabledState(isDisabled) {
384
+ this.disabledFromControl = isDisabled;
385
+ }
386
+ onCheckboxChange(event) {
387
+ const target = event.target;
388
+ const nextValue = target.checked;
389
+ this.indeterminate = false;
390
+ this.checked = nextValue;
391
+ this.onChange(nextValue);
392
+ this.valueChange.emit(nextValue);
393
+ }
394
+ onBlur() {
395
+ this.onTouched();
396
+ }
397
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsCheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
398
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: CxsCheckboxComponent, isStandalone: true, selector: "cxs-checkbox", inputs: { checked: "checked", indeterminate: "indeterminate", disabled: "disabled", label: "label", size: "size", id: "id", name: "name", required: "required", autofocus: "autofocus", ariaLabel: "ariaLabel", ariaDescribedby: "ariaDescribedby" }, outputs: { valueChange: "valueChange" }, providers: [
399
+ {
400
+ provide: NG_VALUE_ACCESSOR,
401
+ useExisting: forwardRef(() => CxsCheckboxComponent),
402
+ multi: true
403
+ }
404
+ ], ngImport: i0, template: "<label [class]=\"wrapperClass\">\n <input\n class=\"peer sr-only\"\n type=\"checkbox\"\n [attr.id]=\"id\"\n [attr.name]=\"name\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.aria-checked]=\"ariaChecked\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [checked]=\"checked\"\n [indeterminate]=\"indeterminate\"\n [disabled]=\"isDisabled\"\n [required]=\"required\"\n (change)=\"onCheckboxChange($event)\"\n (blur)=\"onBlur()\"\n />\n <span [class]=\"controlClass\" aria-hidden=\"true\"></span>\n @if (label) {\n <span [class]=\"labelClass\">{{ label }}</span>\n } @else {\n <span [class]=\"labelClass\">\n <ng-content></ng-content>\n </span>\n }\n</label>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush });
405
+ }
406
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsCheckboxComponent, decorators: [{
407
+ type: Component,
408
+ args: [{ selector: 'cxs-checkbox', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
409
+ {
410
+ provide: NG_VALUE_ACCESSOR,
411
+ useExisting: forwardRef(() => CxsCheckboxComponent),
412
+ multi: true
413
+ }
414
+ ], template: "<label [class]=\"wrapperClass\">\n <input\n class=\"peer sr-only\"\n type=\"checkbox\"\n [attr.id]=\"id\"\n [attr.name]=\"name\"\n [attr.aria-label]=\"ariaLabel\"\n [attr.aria-describedby]=\"ariaDescribedby\"\n [attr.aria-checked]=\"ariaChecked\"\n [attr.autofocus]=\"autofocus ? true : null\"\n [checked]=\"checked\"\n [indeterminate]=\"indeterminate\"\n [disabled]=\"isDisabled\"\n [required]=\"required\"\n (change)=\"onCheckboxChange($event)\"\n (blur)=\"onBlur()\"\n />\n <span [class]=\"controlClass\" aria-hidden=\"true\"></span>\n @if (label) {\n <span [class]=\"labelClass\">{{ label }}</span>\n } @else {\n <span [class]=\"labelClass\">\n <ng-content></ng-content>\n </span>\n }\n</label>\n" }]
415
+ }], propDecorators: { checked: [{
416
+ type: Input
417
+ }], indeterminate: [{
418
+ type: Input
419
+ }], disabled: [{
420
+ type: Input
421
+ }], label: [{
422
+ type: Input
423
+ }], size: [{
424
+ type: Input
425
+ }], id: [{
426
+ type: Input
427
+ }], name: [{
428
+ type: Input
429
+ }], required: [{
430
+ type: Input
431
+ }], autofocus: [{
432
+ type: Input
433
+ }], ariaLabel: [{
434
+ type: Input
435
+ }], ariaDescribedby: [{
436
+ type: Input
437
+ }], valueChange: [{
438
+ type: Output
439
+ }] } });
440
+
441
+ const BASE_CLASSES$2 = 'w-full rounded-[var(--cxs-radius-md)] border border-[var(--cxs-color-border)] ' +
442
+ 'bg-[var(--cxs-color-surface)] text-[var(--cxs-color-on-surface)] ' +
443
+ 'placeholder:text-[var(--cxs-color-on-surface-muted)] transition-colors ' +
444
+ 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
445
+ 'focus-visible:outline-[var(--cxs-color-focus)] focus-visible:border-[var(--cxs-color-focus)] ' +
446
+ 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-60';
447
+ const VARIANT_CLASSES$2 = {
448
+ outline: 'bg-[var(--cxs-color-surface)]',
449
+ filled: 'bg-[var(--cxs-color-surface-hover)]'
450
+ };
451
+ const SIZE_CLASSES$2 = {
452
+ sm: 'h-8 px-3 text-sm',
453
+ md: 'h-10 px-3 text-sm',
454
+ lg: 'h-12 px-4 text-base'
455
+ };
456
+ const INVALID_CLASSES$3 = 'border-[var(--cxs-color-danger)] focus-visible:border-[var(--cxs-color-danger)] ' +
457
+ 'focus-visible:outline-[var(--cxs-color-danger)]';
458
+ const POPOVER_CLASSES = 'absolute left-0 top-full z-10 mt-2 w-full rounded-[var(--cxs-radius-md)] border ' +
459
+ 'border-[var(--cxs-color-border)] bg-[var(--cxs-color-surface)] p-3 shadow-[var(--cxs-shadow-sm)]';
460
+ const NAV_BUTTON_CLASSES = 'inline-flex h-8 w-8 items-center justify-center rounded-[var(--cxs-radius-md)] ' +
461
+ 'text-[var(--cxs-color-on-surface)] transition-colors hover:bg-[var(--cxs-color-surface-hover)] ' +
462
+ 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
463
+ 'focus-visible:outline-[var(--cxs-color-focus)]';
464
+ const DAY_BUTTON_BASE = 'flex h-8 w-8 items-center justify-center rounded-[var(--cxs-radius-md)] text-xs ' +
465
+ 'transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ' +
466
+ 'focus-visible:outline-[var(--cxs-color-focus)] disabled:cursor-not-allowed disabled:opacity-40';
467
+ const DAY_OUTSIDE_MONTH = 'text-[var(--cxs-color-on-surface-muted)]';
468
+ const DAY_TODAY = 'border border-[var(--cxs-color-primary)]';
469
+ const DAY_SELECTED = 'bg-[var(--cxs-color-primary)] text-[var(--cxs-color-on-primary)]';
470
+ const DAY_HOVER = 'hover:bg-[var(--cxs-color-surface-hover)]';
471
+ class CxsDatepickerComponent {
472
+ value = '';
473
+ variant = 'outline';
474
+ size = 'md';
475
+ useNative = true;
476
+ disabled = false;
477
+ readonly = false;
478
+ required = false;
479
+ invalid = false;
480
+ autofocus = false;
481
+ id;
482
+ name;
483
+ min;
484
+ max;
485
+ placeholder;
486
+ ariaLabel;
487
+ ariaDescribedby;
488
+ valueChange = new EventEmitter();
489
+ static nextId = 0;
490
+ fallbackId = `cxs-datepicker-panel-${CxsDatepickerComponent.nextId++}`;
491
+ disabledFromControl = false;
492
+ onChange = () => { };
493
+ onTouched = () => { };
494
+ isOpen = false;
495
+ displayMonth = new Date();
496
+ calendarDays = [];
497
+ weekDayLabels = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
498
+ get isDisabled() {
499
+ return this.disabled || this.disabledFromControl;
500
+ }
501
+ get panelId() {
502
+ return this.id ? `${this.id}-panel` : this.fallbackId;
503
+ }
504
+ get inputClass() {
505
+ return [
506
+ BASE_CLASSES$2,
507
+ SIZE_CLASSES$2[this.size],
508
+ VARIANT_CLASSES$2[this.variant],
509
+ this.invalid ? INVALID_CLASSES$3 : ''
510
+ ]
511
+ .filter(Boolean)
512
+ .join(' ');
513
+ }
514
+ get popoverClass() {
515
+ return POPOVER_CLASSES;
516
+ }
517
+ get navButtonClass() {
518
+ return NAV_BUTTON_CLASSES;
519
+ }
520
+ get displayMonthLabel() {
521
+ return this.displayMonth.toLocaleString('en-US', { month: 'long', year: 'numeric' });
522
+ }
523
+ writeValue(value) {
524
+ this.value = value ?? '';
525
+ this.syncDisplayMonthWithValue();
526
+ }
527
+ registerOnChange(fn) {
528
+ this.onChange = fn;
529
+ }
530
+ registerOnTouched(fn) {
531
+ this.onTouched = fn;
532
+ }
533
+ setDisabledState(isDisabled) {
534
+ this.disabledFromControl = isDisabled;
535
+ }
536
+ onInput(event) {
537
+ const target = event.target;
538
+ const nextValue = target.value;
539
+ this.value = nextValue;
540
+ this.onChange(nextValue);
541
+ this.valueChange.emit(nextValue);
542
+ }
543
+ onDateSelect(day) {
544
+ if (day.disabled || this.isDisabled) {
545
+ return;
546
+ }
547
+ const nextValue = this.formatDate(day.date);
548
+ this.value = nextValue;
549
+ this.onChange(nextValue);
550
+ this.valueChange.emit(nextValue);
551
+ this.isOpen = false;
552
+ }
553
+ onBlur() {
554
+ this.onTouched();
555
+ }
556
+ open() {
557
+ if (this.isDisabled || this.useNative) {
558
+ return;
559
+ }
560
+ this.isOpen = true;
561
+ this.syncDisplayMonthWithValue();
562
+ }
563
+ toggle() {
564
+ if (this.isOpen) {
565
+ this.isOpen = false;
566
+ return;
567
+ }
568
+ this.open();
569
+ }
570
+ prevMonth() {
571
+ this.displayMonth = new Date(this.displayMonth.getFullYear(), this.displayMonth.getMonth() - 1, 1);
572
+ this.updateCalendar();
573
+ }
574
+ nextMonth() {
575
+ this.displayMonth = new Date(this.displayMonth.getFullYear(), this.displayMonth.getMonth() + 1, 1);
576
+ this.updateCalendar();
577
+ }
578
+ dayButtonClass(day) {
579
+ return [
580
+ DAY_BUTTON_BASE,
581
+ day.inMonth ? '' : DAY_OUTSIDE_MONTH,
582
+ day.isToday ? DAY_TODAY : '',
583
+ this.isSelected(day.date) ? DAY_SELECTED : DAY_HOVER
584
+ ]
585
+ .filter(Boolean)
586
+ .join(' ');
587
+ }
588
+ onDocumentClick(event) {
589
+ if (this.useNative || !this.isOpen) {
590
+ return;
591
+ }
592
+ const target = event.target;
593
+ if (target && !target.closest(`#${this.panelId}`) && !target.closest(`[data-cxs-datepicker="${this.panelId}"]`)) {
594
+ this.isOpen = false;
595
+ }
596
+ }
597
+ onEscape() {
598
+ if (this.useNative || !this.isOpen) {
599
+ return;
600
+ }
601
+ this.isOpen = false;
602
+ }
603
+ syncDisplayMonthWithValue() {
604
+ const selected = this.parseDate(this.value);
605
+ this.displayMonth = selected ?? new Date();
606
+ this.updateCalendar();
607
+ }
608
+ updateCalendar() {
609
+ const year = this.displayMonth.getFullYear();
610
+ const month = this.displayMonth.getMonth();
611
+ const startOfMonth = new Date(year, month, 1);
612
+ const startDay = startOfMonth.getDay();
613
+ const calendarStart = new Date(year, month, 1 - startDay);
614
+ const minDate = this.parseDate(this.min);
615
+ const maxDate = this.parseDate(this.max);
616
+ const today = this.stripTime(new Date());
617
+ this.calendarDays = Array.from({ length: 42 }, (_, index) => {
618
+ const date = new Date(calendarStart.getFullYear(), calendarStart.getMonth(), calendarStart.getDate() + index);
619
+ const dayValue = this.stripTime(date);
620
+ const disabled = (minDate && dayValue < minDate) || (maxDate && dayValue > maxDate) || this.isDisabled;
621
+ return {
622
+ date,
623
+ label: String(date.getDate()),
624
+ inMonth: date.getMonth() === month,
625
+ disabled,
626
+ isToday: dayValue.getTime() === today.getTime(),
627
+ key: this.formatDate(date)
628
+ };
629
+ });
630
+ }
631
+ isSelected(date) {
632
+ const selected = this.parseDate(this.value);
633
+ if (!selected) {
634
+ return false;
635
+ }
636
+ return (selected.getFullYear() === date.getFullYear() &&
637
+ selected.getMonth() === date.getMonth() &&
638
+ selected.getDate() === date.getDate());
639
+ }
640
+ parseDate(value) {
641
+ if (!value) {
642
+ return null;
643
+ }
644
+ const [year, month, day] = value.split('-').map(Number);
645
+ if (!year || !month || !day) {
646
+ return null;
647
+ }
648
+ return new Date(year, month - 1, day);
649
+ }
650
+ formatDate(date) {
651
+ const year = date.getFullYear();
652
+ const month = `${date.getMonth() + 1}`.padStart(2, '0');
653
+ const day = `${date.getDate()}`.padStart(2, '0');
654
+ return `${year}-${month}-${day}`;
655
+ }
656
+ stripTime(date) {
657
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
658
+ }
659
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsDatepickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
660
+ 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: [
661
+ {
662
+ provide: NG_VALUE_ACCESSOR,
663
+ useExisting: forwardRef(() => CxsDatepickerComponent),
664
+ multi: true
665
+ }
666
+ ], ngImport: i0, template: "@if (useNative) {\n <input\n type=\"date\"\n [class]=\"inputClass\"\n [attr.id]=\"id\"\n [attr.name]=\"name\"\n [attr.min]=\"min\"\n [attr.max]=\"max\"\n [attr.placeholder]=\"placeholder\"\n [attr.aria-label]=\"ariaLabel\"\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]=\"id\"\n [attr.name]=\"name\"\n [attr.placeholder]=\"placeholder\"\n [attr.aria-label]=\"ariaLabel\"\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 <\n </button>\n <div class=\"text-sm font-semibold text-[var(--cxs-color-on-surface)]\">\n {{ displayMonthLabel }}\n </div>\n <button type=\"button\" [class]=\"navButtonClass\" aria-label=\"Next month\" (click)=\"nextMonth()\">\n >\n </button>\n </div>\n\n <div class=\"mt-3 grid grid-cols-7 gap-1 text-center text-xs text-[var(--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", changeDetection: i0.ChangeDetectionStrategy.OnPush });
667
+ }
668
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsDatepickerComponent, decorators: [{
669
+ type: Component,
670
+ args: [{ selector: 'cxs-datepicker', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
671
+ {
672
+ provide: NG_VALUE_ACCESSOR,
673
+ useExisting: forwardRef(() => CxsDatepickerComponent),
674
+ multi: true
675
+ }
676
+ ], template: "@if (useNative) {\n <input\n type=\"date\"\n [class]=\"inputClass\"\n [attr.id]=\"id\"\n [attr.name]=\"name\"\n [attr.min]=\"min\"\n [attr.max]=\"max\"\n [attr.placeholder]=\"placeholder\"\n [attr.aria-label]=\"ariaLabel\"\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]=\"id\"\n [attr.name]=\"name\"\n [attr.placeholder]=\"placeholder\"\n [attr.aria-label]=\"ariaLabel\"\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 <\n </button>\n <div class=\"text-sm font-semibold text-[var(--cxs-color-on-surface)]\">\n {{ displayMonthLabel }}\n </div>\n <button type=\"button\" [class]=\"navButtonClass\" aria-label=\"Next month\" (click)=\"nextMonth()\">\n >\n </button>\n </div>\n\n <div class=\"mt-3 grid grid-cols-7 gap-1 text-center text-xs text-[var(--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" }]
677
+ }], propDecorators: { value: [{
678
+ type: Input
679
+ }], variant: [{
680
+ type: Input
681
+ }], size: [{
682
+ type: Input
683
+ }], useNative: [{
684
+ type: Input
685
+ }], disabled: [{
686
+ type: Input
687
+ }], readonly: [{
688
+ type: Input
689
+ }], required: [{
690
+ type: Input
691
+ }], invalid: [{
692
+ type: Input
693
+ }], autofocus: [{
694
+ type: Input
695
+ }], id: [{
696
+ type: Input
697
+ }], name: [{
698
+ type: Input
699
+ }], min: [{
700
+ type: Input
701
+ }], max: [{
702
+ type: Input
703
+ }], placeholder: [{
704
+ type: Input
705
+ }], ariaLabel: [{
706
+ type: Input
707
+ }], ariaDescribedby: [{
708
+ type: Input
709
+ }], valueChange: [{
710
+ type: Output
711
+ }], onDocumentClick: [{
712
+ type: HostListener,
713
+ args: ['document:click', ['$event']]
714
+ }], onEscape: [{
715
+ type: HostListener,
716
+ args: ['document:keydown.escape']
717
+ }] } });
718
+
68
719
  const BASE_CLASSES$1 = 'w-full rounded-[var(--cxs-radius-md)] border border-[var(--cxs-color-border)] ' +
69
720
  'bg-[var(--cxs-color-surface)] text-[var(--cxs-color-on-surface)] ' +
70
721
  'placeholder:text-[var(--cxs-color-on-surface-muted)] transition-colors ' +
@@ -465,6 +1116,105 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
465
1116
  type: Output
466
1117
  }] } });
467
1118
 
1119
+ const DEFAULT_DARK_CLASS = 'cxs-theme-dark';
1120
+ class CxsThemeDirective {
1121
+ host;
1122
+ renderer;
1123
+ mode = 'light';
1124
+ darkClass = DEFAULT_DARK_CLASS;
1125
+ mediaQuery = null;
1126
+ mediaListener = null;
1127
+ constructor(host, renderer) {
1128
+ this.host = host;
1129
+ this.renderer = renderer;
1130
+ }
1131
+ set cxsTheme(value) {
1132
+ this.mode = value ?? 'light';
1133
+ this.applyTheme();
1134
+ }
1135
+ set cxsThemeDarkClass(value) {
1136
+ const nextClass = value?.trim() || DEFAULT_DARK_CLASS;
1137
+ if (nextClass === this.darkClass) {
1138
+ return;
1139
+ }
1140
+ const previousClass = this.darkClass;
1141
+ this.darkClass = nextClass;
1142
+ this.renderer.removeClass(this.host.nativeElement, previousClass);
1143
+ this.applyTheme();
1144
+ }
1145
+ ngOnDestroy() {
1146
+ this.detachMediaListener();
1147
+ }
1148
+ applyTheme() {
1149
+ if (this.mode === 'system') {
1150
+ this.attachMediaListener();
1151
+ }
1152
+ else {
1153
+ this.detachMediaListener();
1154
+ }
1155
+ const shouldEnableDark = this.mode === 'dark' || (this.mode === 'system' && this.prefersDark());
1156
+ if (shouldEnableDark) {
1157
+ this.renderer.addClass(this.host.nativeElement, this.darkClass);
1158
+ }
1159
+ else {
1160
+ this.renderer.removeClass(this.host.nativeElement, this.darkClass);
1161
+ }
1162
+ }
1163
+ prefersDark() {
1164
+ if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
1165
+ return false;
1166
+ }
1167
+ if (!this.mediaQuery) {
1168
+ this.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
1169
+ }
1170
+ return this.mediaQuery.matches;
1171
+ }
1172
+ attachMediaListener() {
1173
+ if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
1174
+ return;
1175
+ }
1176
+ if (!this.mediaQuery) {
1177
+ this.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
1178
+ }
1179
+ if (this.mediaListener) {
1180
+ return;
1181
+ }
1182
+ this.mediaListener = () => this.applyTheme();
1183
+ if (typeof this.mediaQuery.addEventListener === 'function') {
1184
+ this.mediaQuery.addEventListener('change', this.mediaListener);
1185
+ }
1186
+ else if (typeof this.mediaQuery.addListener === 'function') {
1187
+ this.mediaQuery.addListener(this.mediaListener);
1188
+ }
1189
+ }
1190
+ detachMediaListener() {
1191
+ if (!this.mediaQuery || !this.mediaListener) {
1192
+ this.mediaListener = null;
1193
+ return;
1194
+ }
1195
+ if (typeof this.mediaQuery.removeEventListener === 'function') {
1196
+ this.mediaQuery.removeEventListener('change', this.mediaListener);
1197
+ }
1198
+ else if (typeof this.mediaQuery.removeListener === 'function') {
1199
+ this.mediaQuery.removeListener(this.mediaListener);
1200
+ }
1201
+ this.mediaListener = null;
1202
+ }
1203
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsThemeDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
1204
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.16", type: CxsThemeDirective, isStandalone: true, selector: "[cxsTheme]", inputs: { cxsTheme: "cxsTheme", cxsThemeDarkClass: "cxsThemeDarkClass" }, ngImport: i0 });
1205
+ }
1206
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: CxsThemeDirective, decorators: [{
1207
+ type: Directive,
1208
+ args: [{
1209
+ selector: '[cxsTheme]',
1210
+ standalone: true
1211
+ }]
1212
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { cxsTheme: [{
1213
+ type: Input
1214
+ }], cxsThemeDarkClass: [{
1215
+ type: Input
1216
+ }] } });
1217
+
468
1218
  /*
469
1219
  * Public API Surface of cerxos-ui
470
1220
  */
@@ -473,5 +1223,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
473
1223
  * Generated bundle index. Do not edit.
474
1224
  */
475
1225
 
476
- export { CerxosUi, CxsButtonComponent, CxsInputComponent, CxsRadioComponent, CxsSelectComponent };
1226
+ export { CerxosUi, CxsAlertComponent, CxsBadgeComponent, CxsBreadcrumbComponent, CxsButtonComponent, CxsCardComponent, CxsCheckboxComponent, CxsDatepickerComponent, CxsInputComponent, CxsRadioComponent, CxsSelectComponent, CxsThemeDirective };
477
1227
  //# sourceMappingURL=cerxos-ui.mjs.map