ngx-com 0.0.1 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/fesm2022/ngx-com-components-avatar.mjs +772 -0
  2. package/fesm2022/ngx-com-components-avatar.mjs.map +1 -0
  3. package/fesm2022/ngx-com-components-badge.mjs +138 -0
  4. package/fesm2022/ngx-com-components-badge.mjs.map +1 -0
  5. package/fesm2022/ngx-com-components-button.mjs +146 -0
  6. package/fesm2022/ngx-com-components-button.mjs.map +1 -0
  7. package/fesm2022/ngx-com-components-calendar.mjs +5046 -0
  8. package/fesm2022/ngx-com-components-calendar.mjs.map +1 -0
  9. package/fesm2022/ngx-com-components-card.mjs +590 -0
  10. package/fesm2022/ngx-com-components-card.mjs.map +1 -0
  11. package/fesm2022/ngx-com-components-checkbox.mjs +344 -0
  12. package/fesm2022/ngx-com-components-checkbox.mjs.map +1 -0
  13. package/fesm2022/ngx-com-components-collapsible.mjs +612 -0
  14. package/fesm2022/ngx-com-components-collapsible.mjs.map +1 -0
  15. package/fesm2022/ngx-com-components-confirm.mjs +562 -0
  16. package/fesm2022/ngx-com-components-confirm.mjs.map +1 -0
  17. package/fesm2022/ngx-com-components-dropdown-testing.mjs +255 -0
  18. package/fesm2022/ngx-com-components-dropdown-testing.mjs.map +1 -0
  19. package/fesm2022/ngx-com-components-dropdown.mjs +2692 -0
  20. package/fesm2022/ngx-com-components-dropdown.mjs.map +1 -0
  21. package/fesm2022/ngx-com-components-empty-state.mjs +382 -0
  22. package/fesm2022/ngx-com-components-empty-state.mjs.map +1 -0
  23. package/fesm2022/ngx-com-components-form-field.mjs +924 -0
  24. package/fesm2022/ngx-com-components-form-field.mjs.map +1 -0
  25. package/fesm2022/ngx-com-components-icon.mjs +183 -0
  26. package/fesm2022/ngx-com-components-icon.mjs.map +1 -0
  27. package/fesm2022/ngx-com-components-item.mjs +578 -0
  28. package/fesm2022/ngx-com-components-item.mjs.map +1 -0
  29. package/fesm2022/ngx-com-components-menu.mjs +1200 -0
  30. package/fesm2022/ngx-com-components-menu.mjs.map +1 -0
  31. package/fesm2022/ngx-com-components-paginator.mjs +823 -0
  32. package/fesm2022/ngx-com-components-paginator.mjs.map +1 -0
  33. package/fesm2022/ngx-com-components-popover.mjs +901 -0
  34. package/fesm2022/ngx-com-components-popover.mjs.map +1 -0
  35. package/fesm2022/ngx-com-components-radio.mjs +621 -0
  36. package/fesm2022/ngx-com-components-radio.mjs.map +1 -0
  37. package/fesm2022/ngx-com-components-segmented-control.mjs +538 -0
  38. package/fesm2022/ngx-com-components-segmented-control.mjs.map +1 -0
  39. package/fesm2022/ngx-com-components-sort.mjs +368 -0
  40. package/fesm2022/ngx-com-components-sort.mjs.map +1 -0
  41. package/fesm2022/ngx-com-components-spinner.mjs +189 -0
  42. package/fesm2022/ngx-com-components-spinner.mjs.map +1 -0
  43. package/fesm2022/ngx-com-components-tabs.mjs +1522 -0
  44. package/fesm2022/ngx-com-components-tabs.mjs.map +1 -0
  45. package/fesm2022/ngx-com-components-tooltip.mjs +625 -0
  46. package/fesm2022/ngx-com-components-tooltip.mjs.map +1 -0
  47. package/fesm2022/ngx-com-components.mjs +17 -0
  48. package/fesm2022/ngx-com-components.mjs.map +1 -0
  49. package/fesm2022/ngx-com-tokens.mjs +12 -0
  50. package/fesm2022/ngx-com-tokens.mjs.map +1 -0
  51. package/fesm2022/ngx-com-utils.mjs +601 -0
  52. package/fesm2022/ngx-com-utils.mjs.map +1 -0
  53. package/fesm2022/ngx-com.mjs +9 -23
  54. package/fesm2022/ngx-com.mjs.map +1 -1
  55. package/package.json +105 -1
  56. package/types/ngx-com-components-avatar.d.ts +409 -0
  57. package/types/ngx-com-components-badge.d.ts +97 -0
  58. package/types/ngx-com-components-button.d.ts +69 -0
  59. package/types/ngx-com-components-calendar.d.ts +1665 -0
  60. package/types/ngx-com-components-card.d.ts +373 -0
  61. package/types/ngx-com-components-checkbox.d.ts +116 -0
  62. package/types/ngx-com-components-collapsible.d.ts +379 -0
  63. package/types/ngx-com-components-confirm.d.ts +160 -0
  64. package/types/ngx-com-components-dropdown-testing.d.ts +116 -0
  65. package/types/ngx-com-components-dropdown.d.ts +938 -0
  66. package/types/ngx-com-components-empty-state.d.ts +269 -0
  67. package/types/ngx-com-components-form-field.d.ts +531 -0
  68. package/types/ngx-com-components-icon.d.ts +94 -0
  69. package/types/ngx-com-components-item.d.ts +336 -0
  70. package/types/ngx-com-components-menu.d.ts +479 -0
  71. package/types/ngx-com-components-paginator.d.ts +265 -0
  72. package/types/ngx-com-components-popover.d.ts +309 -0
  73. package/types/ngx-com-components-radio.d.ts +258 -0
  74. package/types/ngx-com-components-segmented-control.d.ts +274 -0
  75. package/types/ngx-com-components-sort.d.ts +133 -0
  76. package/types/ngx-com-components-spinner.d.ts +120 -0
  77. package/types/ngx-com-components-tabs.d.ts +396 -0
  78. package/types/ngx-com-components-tooltip.d.ts +200 -0
  79. package/types/ngx-com-components.d.ts +12 -0
  80. package/types/ngx-com-tokens.d.ts +7 -0
  81. package/types/ngx-com-utils.d.ts +424 -0
  82. package/types/ngx-com.d.ts +10 -7
@@ -0,0 +1,612 @@
1
+ import { cva } from 'class-variance-authority';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, TemplateRef, Directive, model, input, booleanAttribute, computed, contentChild, ChangeDetectionStrategy, Component, signal, effect } from '@angular/core';
4
+ import { mergeClasses } from 'ngx-com/utils';
5
+ import { NgTemplateOutlet } from '@angular/common';
6
+
7
+ /**
8
+ * CVA variants for the collapsible shell (root directive).
9
+ *
10
+ * @tokens `--color-border`, `--color-background`, `--color-foreground`, `--shadow-xs`, `--radius-collapsible`
11
+ */
12
+ const collapsibleVariants = cva(
13
+ // Base — structural only
14
+ 'com-collapsible block', {
15
+ variants: {
16
+ variant: {
17
+ card: 'rounded-collapsible border border-border bg-background text-foreground shadow-xs',
18
+ bordered: 'rounded-collapsible border border-border',
19
+ flush: 'border-b border-border',
20
+ ghost: '',
21
+ unstyled: '',
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: 'ghost',
26
+ },
27
+ });
28
+
29
+ /**
30
+ * CVA variants for the collapsible trigger directive.
31
+ *
32
+ * @tokens `--color-foreground`, `--color-muted`, `--color-muted-foreground`, `--color-muted-hover`,
33
+ * `--color-ring`, `--color-disabled-foreground`, `--radius-collapsible`
34
+ */
35
+ const collapsibleTriggerVariants = cva([
36
+ 'com-collapsible-trigger',
37
+ 'flex w-full items-center justify-between',
38
+ 'cursor-pointer select-none',
39
+ 'text-sm font-medium',
40
+ 'transition-colors',
41
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
42
+ 'disabled:pointer-events-none disabled:text-disabled-foreground',
43
+ '[&>svg]:transition-transform [&>svg]:duration-200',
44
+ '[&>svg.com-collapsible-icon]:data-[state=open]:rotate-180',
45
+ ].join(' '), {
46
+ variants: {
47
+ variant: {
48
+ ghost: 'rounded-collapsible text-foreground hover:bg-muted hover:text-muted-foreground',
49
+ filled: 'rounded-collapsible bg-muted text-muted-foreground hover:bg-muted-hover',
50
+ header: 'text-foreground hover:text-muted-foreground',
51
+ unstyled: '',
52
+ },
53
+ size: {
54
+ sm: 'px-2 py-1 text-xs gap-1',
55
+ default: 'px-3 py-2 text-sm gap-2',
56
+ lg: 'px-4 py-3 text-base gap-3',
57
+ },
58
+ },
59
+ defaultVariants: {
60
+ variant: 'ghost',
61
+ size: 'default',
62
+ },
63
+ });
64
+
65
+ /**
66
+ * Directive to mark a template as the custom trigger layout template.
67
+ * Replaces the inner content of the trigger while preserving ARIA and keyboard handling.
68
+ *
69
+ * @example
70
+ * ```html
71
+ * <button comCollapsibleTrigger>
72
+ * <ng-template comCollapsibleTriggerTpl let-open let-toggle="toggle" let-disabled="disabled">
73
+ * <div class="flex items-center gap-3 w-full">
74
+ * <span class="h-2 w-2 rounded-full" [class]="open ? 'bg-success' : 'bg-muted'"></span>
75
+ * <span class="font-medium">Notifications</span>
76
+ * <svg class="com-collapsible-icon h-4 w-4" [attr.data-state]="open ? 'open' : 'closed'">
77
+ * <!-- chevron icon -->
78
+ * </svg>
79
+ * </div>
80
+ * </ng-template>
81
+ * </button>
82
+ * ```
83
+ */
84
+ class ComCollapsibleTriggerTpl {
85
+ /** Reference to the template. */
86
+ templateRef = inject(TemplateRef);
87
+ /**
88
+ * Static type guard for template type checking.
89
+ * Enables type-safe access to context properties in templates.
90
+ */
91
+ static ngTemplateContextGuard(_dir, ctx) {
92
+ return true;
93
+ }
94
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleTriggerTpl, deps: [], target: i0.ɵɵFactoryTarget.Directive });
95
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.0", type: ComCollapsibleTriggerTpl, isStandalone: true, selector: "ng-template[comCollapsibleTriggerTpl]", ngImport: i0 });
96
+ }
97
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleTriggerTpl, decorators: [{
98
+ type: Directive,
99
+ args: [{
100
+ selector: 'ng-template[comCollapsibleTriggerTpl]',
101
+ }]
102
+ }] });
103
+
104
+ /**
105
+ * Directive to mark a template as the custom content chrome template.
106
+ * Wraps the content with custom chrome (headers, footers, padding).
107
+ * The grid animation still applies on the host.
108
+ *
109
+ * @example
110
+ * ```html
111
+ * <com-collapsible-content>
112
+ * <ng-template comCollapsibleContentTpl let-open="open">
113
+ * <div class="border-t border-border">
114
+ * <div class="p-4 space-y-3">
115
+ * <!-- Content here -->
116
+ * </div>
117
+ * <div class="flex justify-end gap-2 px-4 py-3 border-t border-border-subtle bg-muted">
118
+ * <button>Reset</button>
119
+ * <button>Apply</button>
120
+ * </div>
121
+ * </div>
122
+ * </ng-template>
123
+ * </com-collapsible-content>
124
+ * ```
125
+ */
126
+ class ComCollapsibleContentTpl {
127
+ /** Reference to the template. */
128
+ templateRef = inject(TemplateRef);
129
+ /**
130
+ * Static type guard for template type checking.
131
+ * Enables type-safe access to context properties in templates.
132
+ */
133
+ static ngTemplateContextGuard(_dir, ctx) {
134
+ return true;
135
+ }
136
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleContentTpl, deps: [], target: i0.ɵɵFactoryTarget.Directive });
137
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.0", type: ComCollapsibleContentTpl, isStandalone: true, selector: "ng-template[comCollapsibleContentTpl]", ngImport: i0 });
138
+ }
139
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleContentTpl, decorators: [{
140
+ type: Directive,
141
+ args: [{
142
+ selector: 'ng-template[comCollapsibleContentTpl]',
143
+ }]
144
+ }] });
145
+
146
+ /**
147
+ * Directive to mark a template as the custom icon template.
148
+ * Replaces only the chevron icon inside the default trigger layout.
149
+ *
150
+ * @example
151
+ * ```html
152
+ * <button comCollapsibleTrigger>
153
+ * Settings
154
+ * <ng-template comCollapsibleIcon let-open="open">
155
+ * <span class="text-muted-foreground text-xs">{{ open ? '▲' : '▼' }}</span>
156
+ * </ng-template>
157
+ * </button>
158
+ * ```
159
+ */
160
+ class ComCollapsibleIconTpl {
161
+ /** Reference to the template. */
162
+ templateRef = inject(TemplateRef);
163
+ /**
164
+ * Static type guard for template type checking.
165
+ * Enables type-safe access to context properties in templates.
166
+ */
167
+ static ngTemplateContextGuard(_dir, ctx) {
168
+ return true;
169
+ }
170
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleIconTpl, deps: [], target: i0.ɵɵFactoryTarget.Directive });
171
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.0", type: ComCollapsibleIconTpl, isStandalone: true, selector: "ng-template[comCollapsibleIcon]", ngImport: i0 });
172
+ }
173
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleIconTpl, decorators: [{
174
+ type: Directive,
175
+ args: [{
176
+ selector: 'ng-template[comCollapsibleIcon]',
177
+ }]
178
+ }] });
179
+
180
+ /**
181
+ * Structural directive for lazy content rendering.
182
+ * Content is only instantiated on first expand, preserving state on subsequent toggles.
183
+ *
184
+ * @example
185
+ * ```html
186
+ * <com-collapsible-content>
187
+ * <ng-template comCollapsibleLazy>
188
+ * <app-heavy-chart [data]="chartData()" />
189
+ * </ng-template>
190
+ * </com-collapsible-content>
191
+ * ```
192
+ */
193
+ class ComCollapsibleLazy {
194
+ /** Reference to the template. */
195
+ templateRef = inject(TemplateRef);
196
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleLazy, deps: [], target: i0.ɵɵFactoryTarget.Directive });
197
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.0", type: ComCollapsibleLazy, isStandalone: true, selector: "ng-template[comCollapsibleLazy]", ngImport: i0 });
198
+ }
199
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleLazy, decorators: [{
200
+ type: Directive,
201
+ args: [{
202
+ selector: 'ng-template[comCollapsibleLazy]',
203
+ }]
204
+ }] });
205
+
206
+ let collapsibleIdCounter = 0;
207
+ /**
208
+ * Generates a unique ID for collapsible components.
209
+ * @returns A unique string ID
210
+ */
211
+ function generateCollapsibleId() {
212
+ return `com-collapsible-${++collapsibleIdCounter}`;
213
+ }
214
+
215
+ /**
216
+ * Root collapsible directive — manages state and provides shell styling.
217
+ *
218
+ * Works as a DI anchor for child directives (trigger, content).
219
+ * Exposes programmatic control via template reference.
220
+ *
221
+ * @tokens `--color-border`, `--color-background`, `--color-foreground`, `--shadow-xs`
222
+ *
223
+ * @example Basic usage
224
+ * ```html
225
+ * <div comCollapsible variant="card">
226
+ * <button comCollapsibleTrigger>Section Title</button>
227
+ * <com-collapsible-content>
228
+ * <div class="p-4">Content here.</div>
229
+ * </com-collapsible-content>
230
+ * </div>
231
+ * ```
232
+ *
233
+ * @example Two-way binding with external control
234
+ * ```html
235
+ * <div comCollapsible [(open)]="sectionOpen" #section="comCollapsible">
236
+ * <button comCollapsibleTrigger>Advanced</button>
237
+ * <com-collapsible-content>...</com-collapsible-content>
238
+ * </div>
239
+ * <button (click)="section.toggle()">Toggle externally</button>
240
+ * ```
241
+ */
242
+ class ComCollapsible {
243
+ /** Unique ID for the collapsible instance. */
244
+ id = generateCollapsibleId();
245
+ /** ID for the trigger element (used for aria-labelledby). */
246
+ triggerId = `${this.id}-trigger`;
247
+ /** ID for the content panel (used for aria-controls). */
248
+ contentId = `${this.id}-content`;
249
+ // ============ INPUTS ============
250
+ /** Two-way bound open state. */
251
+ open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
252
+ /** Disables the collapsible, preventing state changes. */
253
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : {}), transform: booleanAttribute });
254
+ /** Shell preset variant. */
255
+ variant = input('ghost', ...(ngDevMode ? [{ debugName: "variant" }] : []));
256
+ /** Consumer CSS classes — merged with variant classes. */
257
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : {}), alias: 'class' });
258
+ // ============ COMPUTED STATE ============
259
+ /** @internal Computed host class from CVA + consumer overrides. */
260
+ computedClass = computed(() => mergeClasses(collapsibleVariants({ variant: this.variant() }), this.userClass()), ...(ngDevMode ? [{ debugName: "computedClass" }] : []));
261
+ // ============ PUBLIC API ============
262
+ /** Returns the current open state. */
263
+ isOpen() {
264
+ return this.open();
265
+ }
266
+ /** Returns the current disabled state. */
267
+ isDisabled() {
268
+ return this.disabled();
269
+ }
270
+ /** Toggles the open state (if not disabled). */
271
+ toggle() {
272
+ if (this.disabled())
273
+ return;
274
+ this.open.update((v) => !v);
275
+ }
276
+ /** Expands the collapsible (if not disabled). */
277
+ expand() {
278
+ if (this.disabled())
279
+ return;
280
+ this.open.set(true);
281
+ }
282
+ /** Collapses the collapsible (if not disabled). */
283
+ collapse() {
284
+ if (this.disabled())
285
+ return;
286
+ this.open.set(false);
287
+ }
288
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsible, deps: [], target: i0.ɵɵFactoryTarget.Directive });
289
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.0", type: ComCollapsible, isStandalone: true, selector: "[comCollapsible]", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { properties: { "class": "computedClass()", "attr.data-state": "isOpen() ? \"open\" : \"closed\"" } }, exportAs: ["comCollapsible"], ngImport: i0 });
290
+ }
291
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsible, decorators: [{
292
+ type: Directive,
293
+ args: [{
294
+ selector: '[comCollapsible]',
295
+ exportAs: 'comCollapsible',
296
+ host: {
297
+ '[class]': 'computedClass()',
298
+ '[attr.data-state]': 'isOpen() ? "open" : "closed"',
299
+ },
300
+ }]
301
+ }], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
302
+
303
+ /**
304
+ * Collapsible trigger component — handles toggle interaction, ARIA, keyboard, and template rendering.
305
+ *
306
+ * Uses attribute selector so it can be applied to `<button>` or any focusable element.
307
+ * Injects the parent `ComCollapsible` directive to access state.
308
+ * Supports custom trigger layout via `comCollapsibleTriggerTpl` and custom icon via `comCollapsibleIcon`.
309
+ *
310
+ * @tokens `--color-foreground`, `--color-muted`, `--color-muted-foreground`, `--color-muted-hover`,
311
+ * `--color-ring`, `--color-disabled-foreground`
312
+ *
313
+ * @example Default trigger with auto icon
314
+ * ```html
315
+ * <button comCollapsibleTrigger>Section Title</button>
316
+ * ```
317
+ *
318
+ * @example Without icon
319
+ * ```html
320
+ * <button comCollapsibleTrigger [showIcon]="false">Section Title</button>
321
+ * ```
322
+ *
323
+ * @example With custom icon
324
+ * ```html
325
+ * <button comCollapsibleTrigger>
326
+ * Settings
327
+ * <ng-template comCollapsibleIcon let-open="open">
328
+ * <span class="text-xs text-muted-foreground">{{ open ? '▲' : '▼' }}</span>
329
+ * </ng-template>
330
+ * </button>
331
+ * ```
332
+ *
333
+ * @example Full trigger layout override
334
+ * ```html
335
+ * <button comCollapsibleTrigger>
336
+ * <ng-template comCollapsibleTriggerTpl let-open let-toggle="toggle">
337
+ * <div class="flex items-center gap-3 w-full">
338
+ * <span class="h-2 w-2 rounded-full" [class]="open ? 'bg-success' : 'bg-muted'"></span>
339
+ * <span class="font-medium">Notifications</span>
340
+ * <svg class="com-collapsible-icon h-4 w-4" [attr.data-state]="open ? 'open' : 'closed'">
341
+ * <!-- chevron -->
342
+ * </svg>
343
+ * </div>
344
+ * </ng-template>
345
+ * </button>
346
+ * ```
347
+ */
348
+ class ComCollapsibleTrigger {
349
+ /** Parent collapsible directive (provides state). */
350
+ collapsible = inject(ComCollapsible);
351
+ /** Custom trigger layout template (replaces inner content). */
352
+ triggerTpl = contentChild(ComCollapsibleTriggerTpl, ...(ngDevMode ? [{ debugName: "triggerTpl" }] : []));
353
+ /** Custom icon template (replaces default chevron). */
354
+ iconTpl = contentChild(ComCollapsibleIconTpl, ...(ngDevMode ? [{ debugName: "iconTpl" }] : []));
355
+ // ============ INPUTS ============
356
+ /** Trigger preset variant. */
357
+ variant = input('ghost', ...(ngDevMode ? [{ debugName: "variant" }] : []));
358
+ /** Trigger size. */
359
+ size = input('default', ...(ngDevMode ? [{ debugName: "size" }] : []));
360
+ /** Show/hide the toggle icon. */
361
+ showIcon = input(true, { ...(ngDevMode ? { debugName: "showIcon" } : {}), transform: booleanAttribute });
362
+ /** Consumer CSS classes — merged with variant classes. */
363
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : {}), alias: 'class' });
364
+ // ============ COMPUTED STATE ============
365
+ /** @internal Computed host class from CVA + consumer overrides. */
366
+ computedClass = computed(() => mergeClasses(collapsibleTriggerVariants({
367
+ variant: this.variant(),
368
+ size: this.size(),
369
+ }), this.userClass()), ...(ngDevMode ? [{ debugName: "computedClass" }] : []));
370
+ /** Context for trigger template. */
371
+ triggerContext = computed(() => ({
372
+ $implicit: this.collapsible.isOpen(),
373
+ open: this.collapsible.isOpen(),
374
+ disabled: this.collapsible.isDisabled(),
375
+ toggle: () => this.collapsible.toggle(),
376
+ }), ...(ngDevMode ? [{ debugName: "triggerContext" }] : []));
377
+ /** Context for icon template. */
378
+ iconContext = computed(() => ({
379
+ $implicit: this.collapsible.isOpen(),
380
+ open: this.collapsible.isOpen(),
381
+ }), ...(ngDevMode ? [{ debugName: "iconContext" }] : []));
382
+ // ============ EVENT HANDLERS ============
383
+ /** @internal */
384
+ onClick(event) {
385
+ event.preventDefault();
386
+ this.collapsible.toggle();
387
+ }
388
+ /** @internal */
389
+ onKeydown(event) {
390
+ event.preventDefault();
391
+ this.collapsible.toggle();
392
+ }
393
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleTrigger, deps: [], target: i0.ɵɵFactoryTarget.Component });
394
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComCollapsibleTrigger, isStandalone: true, selector: "[comCollapsibleTrigger]", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick($event)", "keydown.enter": "onKeydown($event)", "keydown.space": "onKeydown($event)" }, properties: { "class": "computedClass()", "attr.id": "collapsible.triggerId", "attr.type": "\"button\"", "attr.aria-expanded": "collapsible.isOpen()", "attr.aria-controls": "collapsible.contentId", "attr.aria-disabled": "collapsible.isDisabled() || null", "attr.data-state": "collapsible.isOpen() ? \"open\" : \"closed\"", "attr.disabled": "collapsible.isDisabled() || null", "tabindex": "collapsible.isDisabled() ? -1 : 0" } }, queries: [{ propertyName: "triggerTpl", first: true, predicate: ComCollapsibleTriggerTpl, descendants: true, isSignal: true }, { propertyName: "iconTpl", first: true, predicate: ComCollapsibleIconTpl, descendants: true, isSignal: true }], ngImport: i0, template: `
395
+ @if (triggerTpl()) {
396
+ <ng-container
397
+ [ngTemplateOutlet]="triggerTpl()!.templateRef"
398
+ [ngTemplateOutletContext]="triggerContext()"
399
+ />
400
+ } @else {
401
+ <span class="flex-1 truncate text-left">
402
+ <ng-content />
403
+ </span>
404
+ @if (showIcon()) {
405
+ @if (iconTpl()) {
406
+ <ng-container
407
+ [ngTemplateOutlet]="iconTpl()!.templateRef"
408
+ [ngTemplateOutletContext]="iconContext()"
409
+ />
410
+ } @else {
411
+ <svg
412
+ class="com-collapsible-icon h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200"
413
+ [attr.data-state]="collapsible.isOpen() ? 'open' : 'closed'"
414
+ viewBox="0 0 24 24"
415
+ fill="none"
416
+ stroke="currentColor"
417
+ stroke-width="2"
418
+ stroke-linecap="round"
419
+ stroke-linejoin="round"
420
+ >
421
+ <polyline points="6 9 12 15 18 9" />
422
+ </svg>
423
+ }
424
+ }
425
+ }
426
+ `, isInline: true, styles: [":host{display:flex}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
427
+ }
428
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleTrigger, decorators: [{
429
+ type: Component,
430
+ args: [{ selector: '[comCollapsibleTrigger]', template: `
431
+ @if (triggerTpl()) {
432
+ <ng-container
433
+ [ngTemplateOutlet]="triggerTpl()!.templateRef"
434
+ [ngTemplateOutletContext]="triggerContext()"
435
+ />
436
+ } @else {
437
+ <span class="flex-1 truncate text-left">
438
+ <ng-content />
439
+ </span>
440
+ @if (showIcon()) {
441
+ @if (iconTpl()) {
442
+ <ng-container
443
+ [ngTemplateOutlet]="iconTpl()!.templateRef"
444
+ [ngTemplateOutletContext]="iconContext()"
445
+ />
446
+ } @else {
447
+ <svg
448
+ class="com-collapsible-icon h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200"
449
+ [attr.data-state]="collapsible.isOpen() ? 'open' : 'closed'"
450
+ viewBox="0 0 24 24"
451
+ fill="none"
452
+ stroke="currentColor"
453
+ stroke-width="2"
454
+ stroke-linecap="round"
455
+ stroke-linejoin="round"
456
+ >
457
+ <polyline points="6 9 12 15 18 9" />
458
+ </svg>
459
+ }
460
+ }
461
+ }
462
+ `, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
463
+ '[class]': 'computedClass()',
464
+ '[attr.id]': 'collapsible.triggerId',
465
+ '[attr.type]': '"button"',
466
+ '[attr.aria-expanded]': 'collapsible.isOpen()',
467
+ '[attr.aria-controls]': 'collapsible.contentId',
468
+ '[attr.aria-disabled]': 'collapsible.isDisabled() || null',
469
+ '[attr.data-state]': 'collapsible.isOpen() ? "open" : "closed"',
470
+ '[attr.disabled]': 'collapsible.isDisabled() || null',
471
+ '[tabindex]': 'collapsible.isDisabled() ? -1 : 0',
472
+ '(click)': 'onClick($event)',
473
+ '(keydown.enter)': 'onKeydown($event)',
474
+ '(keydown.space)': 'onKeydown($event)',
475
+ }, styles: [":host{display:flex}\n"] }]
476
+ }], propDecorators: { triggerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComCollapsibleTriggerTpl), { isSignal: true }] }], iconTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComCollapsibleIconTpl), { isSignal: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
477
+
478
+ /**
479
+ * Collapsible content component — animated panel with region role.
480
+ *
481
+ * Uses CSS grid technique for smooth height animation without JS measurement.
482
+ * Supports lazy rendering via `comCollapsibleLazy` directive.
483
+ *
484
+ * @tokens None (structural only — styling is applied via templates or consumer classes)
485
+ *
486
+ * @example Basic usage
487
+ * ```html
488
+ * <com-collapsible-content>
489
+ * <div class="p-4">Content here.</div>
490
+ * </com-collapsible-content>
491
+ * ```
492
+ *
493
+ * @example With custom duration
494
+ * ```html
495
+ * <com-collapsible-content [duration]="300">
496
+ * <div class="p-4">Slower animation.</div>
497
+ * </com-collapsible-content>
498
+ * ```
499
+ *
500
+ * @example With content chrome template
501
+ * ```html
502
+ * <com-collapsible-content>
503
+ * <ng-template comCollapsibleContentTpl let-open="open">
504
+ * <div class="border-t border-border p-4">
505
+ * <!-- Content with custom chrome -->
506
+ * </div>
507
+ * </ng-template>
508
+ * </com-collapsible-content>
509
+ * ```
510
+ *
511
+ * @example Lazy content
512
+ * ```html
513
+ * <com-collapsible-content>
514
+ * <ng-template comCollapsibleLazy>
515
+ * <app-heavy-component />
516
+ * </ng-template>
517
+ * </com-collapsible-content>
518
+ * ```
519
+ */
520
+ class ComCollapsibleContent {
521
+ /** Parent collapsible directive (provides state). */
522
+ collapsible = inject(ComCollapsible);
523
+ /** Custom content chrome template. */
524
+ contentTpl = contentChild(ComCollapsibleContentTpl, ...(ngDevMode ? [{ debugName: "contentTpl" }] : []));
525
+ /** Lazy content template. */
526
+ lazyTpl = contentChild(ComCollapsibleLazy, ...(ngDevMode ? [{ debugName: "lazyTpl" }] : []));
527
+ /** Track if collapsible has ever been opened (for lazy rendering). */
528
+ hasBeenOpened = signal(false, ...(ngDevMode ? [{ debugName: "hasBeenOpened" }] : []));
529
+ // ============ INPUTS ============
530
+ /** Transition duration in milliseconds. */
531
+ duration = input(200, ...(ngDevMode ? [{ debugName: "duration" }] : []));
532
+ /** Consumer CSS classes for the inner wrapper. */
533
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : {}), alias: 'class' });
534
+ // ============ COMPUTED STATE ============
535
+ /** @internal Computed inner wrapper class. */
536
+ innerClass = computed(() => mergeClasses('com-collapsible-content-inner', this.userClass()), ...(ngDevMode ? [{ debugName: "innerClass" }] : []));
537
+ /** Context for content template. */
538
+ templateContext = computed(() => ({
539
+ $implicit: this.collapsible.isOpen(),
540
+ open: this.collapsible.isOpen(),
541
+ }), ...(ngDevMode ? [{ debugName: "templateContext" }] : []));
542
+ constructor() {
543
+ // Track first open for lazy rendering
544
+ effect(() => {
545
+ if (this.collapsible.isOpen() && !this.hasBeenOpened()) {
546
+ this.hasBeenOpened.set(true);
547
+ }
548
+ });
549
+ }
550
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
551
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComCollapsibleContent, isStandalone: true, selector: "com-collapsible-content", inputs: { duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--duration.ms": "duration()", "attr.id": "collapsible.contentId", "attr.role": "\"region\"", "attr.aria-labelledby": "collapsible.triggerId", "attr.data-state": "collapsible.isOpen() ? \"open\" : \"closed\"", "attr.inert": "!collapsible.isOpen() || null" }, classAttribute: "com-collapsible-content" }, queries: [{ propertyName: "contentTpl", first: true, predicate: ComCollapsibleContentTpl, descendants: true, isSignal: true }, { propertyName: "lazyTpl", first: true, predicate: ComCollapsibleLazy, descendants: true, isSignal: true }], ngImport: i0, template: `
552
+ @if (contentTpl()) {
553
+ <div class="com-collapsible-content-inner" [class]="innerClass()">
554
+ <ng-container
555
+ [ngTemplateOutlet]="contentTpl()!.templateRef"
556
+ [ngTemplateOutletContext]="templateContext()"
557
+ />
558
+ </div>
559
+ } @else if (lazyTpl()) {
560
+ @if (hasBeenOpened()) {
561
+ <div class="com-collapsible-content-inner" [class]="innerClass()">
562
+ <ng-container [ngTemplateOutlet]="lazyTpl()!.templateRef" />
563
+ </div>
564
+ }
565
+ } @else {
566
+ <div class="com-collapsible-content-inner" [class]="innerClass()">
567
+ <ng-content />
568
+ </div>
569
+ }
570
+ `, isInline: true, styles: [":host{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--duration, .2s) ease}:host([data-state=\"open\"]){grid-template-rows:1fr}.com-collapsible-content-inner{overflow:hidden}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
571
+ }
572
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComCollapsibleContent, decorators: [{
573
+ type: Component,
574
+ args: [{ selector: 'com-collapsible-content', template: `
575
+ @if (contentTpl()) {
576
+ <div class="com-collapsible-content-inner" [class]="innerClass()">
577
+ <ng-container
578
+ [ngTemplateOutlet]="contentTpl()!.templateRef"
579
+ [ngTemplateOutletContext]="templateContext()"
580
+ />
581
+ </div>
582
+ } @else if (lazyTpl()) {
583
+ @if (hasBeenOpened()) {
584
+ <div class="com-collapsible-content-inner" [class]="innerClass()">
585
+ <ng-container [ngTemplateOutlet]="lazyTpl()!.templateRef" />
586
+ </div>
587
+ }
588
+ } @else {
589
+ <div class="com-collapsible-content-inner" [class]="innerClass()">
590
+ <ng-content />
591
+ </div>
592
+ }
593
+ `, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
594
+ class: 'com-collapsible-content',
595
+ '[style.--duration.ms]': 'duration()',
596
+ '[attr.id]': 'collapsible.contentId',
597
+ '[attr.role]': '"region"',
598
+ '[attr.aria-labelledby]': 'collapsible.triggerId',
599
+ '[attr.data-state]': 'collapsible.isOpen() ? "open" : "closed"',
600
+ '[attr.inert]': '!collapsible.isOpen() || null',
601
+ }, styles: [":host{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--duration, .2s) ease}:host([data-state=\"open\"]){grid-template-rows:1fr}.com-collapsible-content-inner{overflow:hidden}\n"] }]
602
+ }], ctorParameters: () => [], propDecorators: { contentTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComCollapsibleContentTpl), { isSignal: true }] }], lazyTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComCollapsibleLazy), { isSignal: true }] }], duration: [{ type: i0.Input, args: [{ isSignal: true, alias: "duration", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
603
+
604
+ // Public API for the collapsible component
605
+ // Variants
606
+
607
+ /**
608
+ * Generated bundle index. Do not edit.
609
+ */
610
+
611
+ export { ComCollapsible, ComCollapsibleContent, ComCollapsibleContentTpl, ComCollapsibleIconTpl, ComCollapsibleLazy, ComCollapsibleTrigger, ComCollapsibleTriggerTpl, collapsibleTriggerVariants, collapsibleVariants };
612
+ //# sourceMappingURL=ngx-com-components-collapsible.mjs.map