@compsych-ui-components/angular 4.0.18 → 4.0.20

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.
package/esm2022/index.js CHANGED
@@ -1,21 +1,19 @@
1
1
  import { NgModule } from '@angular/core';
2
2
  import { ButtonComponent } from './lib/button/button';
3
3
  import { AccordionComponent } from './lib/accordion/accordion';
4
- import { AccordionItemComponent } from './lib/accordion/accordion-item';
5
4
  import * as i0 from "@angular/core";
6
5
  export { ButtonComponent } from './lib/button/button';
7
6
  export { AccordionComponent } from './lib/accordion/accordion';
8
- export { AccordionItemComponent } from './lib/accordion/accordion-item';
9
7
  export class CompsychAngularModule {
10
8
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CompsychAngularModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
11
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.14", ngImport: i0, type: CompsychAngularModule, imports: [ButtonComponent, AccordionComponent, AccordionItemComponent], exports: [ButtonComponent, AccordionComponent, AccordionItemComponent] });
9
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.14", ngImport: i0, type: CompsychAngularModule, imports: [ButtonComponent, AccordionComponent], exports: [ButtonComponent, AccordionComponent] });
12
10
  static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CompsychAngularModule });
13
11
  }
14
12
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: CompsychAngularModule, decorators: [{
15
13
  type: NgModule,
16
14
  args: [{
17
- imports: [ButtonComponent, AccordionComponent, AccordionItemComponent],
18
- exports: [ButtonComponent, AccordionComponent, AccordionItemComponent],
15
+ imports: [ButtonComponent, AccordionComponent],
16
+ exports: [ButtonComponent, AccordionComponent],
19
17
  }]
20
18
  }] });
21
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/angular/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;;AAExE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAMxE,MAAM,OAAO,qBAAqB;wGAArB,qBAAqB;yGAArB,qBAAqB,YAHtB,eAAe,EAAE,kBAAkB,EAAE,sBAAsB,aAC3D,eAAe,EAAE,kBAAkB,EAAE,sBAAsB;yGAE1D,qBAAqB;;4FAArB,qBAAqB;kBAJjC,QAAQ;mBAAC;oBACR,OAAO,EAAE,CAAC,eAAe,EAAE,kBAAkB,EAAE,sBAAsB,CAAC;oBACtE,OAAO,EAAE,CAAC,eAAe,EAAE,kBAAkB,EAAE,sBAAsB,CAAC;iBACvE","sourcesContent":["import { NgModule } from '@angular/core';\r\nimport { ButtonComponent } from './lib/button/button';\r\nimport { AccordionComponent } from './lib/accordion/accordion';\r\nimport { AccordionItemComponent } from './lib/accordion/accordion-item';\r\n\r\nexport { ButtonComponent } from './lib/button/button';\r\nexport { AccordionComponent } from './lib/accordion/accordion';\r\nexport { AccordionItemComponent } from './lib/accordion/accordion-item';\r\n\r\n@NgModule({\r\n imports: [ButtonComponent, AccordionComponent, AccordionItemComponent],\r\n exports: [ButtonComponent, AccordionComponent, AccordionItemComponent],\r\n})\r\nexport class CompsychAngularModule {}\r\n\r\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/angular/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAO/D,MAAM,OAAO,qBAAqB;wGAArB,qBAAqB;yGAArB,qBAAqB,YAHtB,eAAe,EAAE,kBAAkB,aACnC,eAAe,EAAE,kBAAkB;yGAElC,qBAAqB;;4FAArB,qBAAqB;kBAJjC,QAAQ;mBAAC;oBACR,OAAO,EAAE,CAAC,eAAe,EAAE,kBAAkB,CAAC;oBAC9C,OAAO,EAAE,CAAC,eAAe,EAAE,kBAAkB,CAAC;iBAC/C","sourcesContent":["import { NgModule } from '@angular/core';\nimport { ButtonComponent } from './lib/button/button';\nimport { AccordionComponent } from './lib/accordion/accordion';\n\nexport { ButtonComponent } from './lib/button/button';\nexport { AccordionComponent } from './lib/accordion/accordion';\nexport type { AccordionItem, AccordionButton, AccordionVariant, NestedAccordionItem } from './lib/accordion/accordion-types';\n\n@NgModule({\n imports: [ButtonComponent, AccordionComponent],\n exports: [ButtonComponent, AccordionComponent],\n})\nexport class CompsychAngularModule {}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=accordion-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion-types.js","sourceRoot":"","sources":["../../../../../../packages/angular/src/lib/accordion/accordion-types.ts"],"names":[],"mappings":"","sourcesContent":["export type AccordionVariant = 'default' | 'level-2' | 'text-only';\n\nexport interface AccordionButton {\n label: string;\n action: () => void;\n}\n\nexport type NestedAccordionItem = Omit<AccordionItem, 'buttons' | 'nestedContent'>;\n\nexport interface AccordionItem {\n title: string;\n content?: string;\n icon?: string;\n expanded?: boolean;\n buttons?: AccordionButton[];\n nestedContent?: NestedAccordionItem[];\n}\n"]}
@@ -1,46 +1,184 @@
1
- import { Component, ContentChildren, Input, } from '@angular/core';
1
+ import { Component, EventEmitter, forwardRef, Input, Output, SecurityContext, } from '@angular/core';
2
2
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
3
- import { AccordionItemComponent } from './accordion-item';
3
+ import { LUCIDE_ICONS } from '@compsych-ui-components/shared/assets/lucide-icons.generated';
4
+ import { ButtonComponent } from '../button/button';
4
5
  import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/platform-browser";
7
+ // AccordionItemComponent is defined before AccordionComponent because AccordionComponent
8
+ // uses it directly in its imports. AccordionItemComponent references AccordionComponent
9
+ // via forwardRef to break the forward-reference cycle within this file.
10
+ export class AccordionItemComponent {
11
+ sanitizer;
12
+ title = '';
13
+ content = '';
14
+ buttons = [];
15
+ nestedContent = [];
16
+ variant = 'default';
17
+ nested = false;
18
+ set icon(name) {
19
+ const svg = LUCIDE_ICONS[name];
20
+ this.iconSvg = svg ? this.sanitizer.bypassSecurityTrustHtml(svg) : null;
21
+ }
22
+ iconSvg = null;
23
+ get sanitizedContent() {
24
+ return this.sanitizer.sanitize(SecurityContext.HTML, this.content) ?? '';
25
+ }
26
+ constructor(sanitizer) {
27
+ this.sanitizer = sanitizer;
28
+ }
29
+ get expanded() { return this._expanded; }
30
+ set expanded(value) { this._expanded = coerceBooleanProperty(value); }
31
+ _expanded = false;
32
+ expandedChange = new EventEmitter();
33
+ toggle() {
34
+ this._expanded = !this._expanded;
35
+ this.expandedChange.emit(this._expanded);
36
+ }
37
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionItemComponent, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
38
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: AccordionItemComponent, isStandalone: true, selector: "compsych-accordion-item", inputs: { title: "title", content: "content", buttons: "buttons", nestedContent: "nestedContent", variant: "variant", nested: "nested", icon: "icon", expanded: "expanded" }, outputs: { expandedChange: "expandedChange" }, host: { properties: { "class.level-2": "variant === \"level-2\"", "class.text-only": "variant === \"text-only\"", "class.nested": "nested" }, classAttribute: "compsych-accordion-item" }, ngImport: i0, template: `
39
+ <button
40
+ class="trigger"
41
+ type="button"
42
+ [attr.aria-expanded]="expanded"
43
+ (click)="toggle()"
44
+ >
45
+ @if (iconSvg) {
46
+ <span class="trigger-leading-icon" [innerHTML]="iconSvg" aria-hidden="true"></span>
47
+ }
48
+ <span class="trigger-label">{{ title }}</span>
49
+ <span class="trigger-toggle material-symbols-rounded" aria-hidden="true">{{ expanded ? 'remove' : 'add' }}</span>
50
+ </button>
51
+ @if (expanded && content) {
52
+ <div class="content" role="region" [innerHTML]="sanitizedContent"></div>
53
+ }
54
+ @if (expanded && nestedContent.length) {
55
+ <compsych-accordion [items]="nestedContent" variant="level-2" [nested]="true" />
56
+ }
57
+ @if (expanded && buttons.length) {
58
+ <div class="actions">
59
+ @for (btn of buttons; track btn.label) {
60
+ <compsych-button [label]="btn.label" variant="filled" size="small" (click)="btn.action()" />
61
+ }
62
+ </div>
63
+ }
64
+ `, isInline: true, styles: [":host{display:block;border-bottom:var(--sys-stroke-thin) solid var(--sys-outline-variant)}:host:first-child{border-top:var(--sys-stroke-thin) solid var(--sys-outline-variant)}.trigger{display:flex;align-items:center;gap:var(--sys-padding-8);width:100%;padding:var(--sys-padding-16) var(--sys-padding-24);background:none;border:none;cursor:pointer;text-align:left;color:var(--sys-on-surface);font-family:var(--core-title);font-size:var(--core-lg);font-weight:var(--sys-font-weight);line-height:var(--core-2xl);letter-spacing:var(--core-spacing-0);position:relative;overflow:hidden;border-radius:0}.trigger:before{content:\"\";position:absolute;inset:0;background-color:currentColor;opacity:0;transition:opacity .15s ease;pointer-events:none}.trigger:hover:before{opacity:.08}.trigger:active:before{opacity:.1}.trigger-label{flex:1;min-width:0}.trigger-leading-icon{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;color:var(--sys-on-surface);flex-shrink:0}.trigger-leading-icon svg{width:100%;height:100%}.trigger-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;font-size:1rem;line-height:1;color:var(--sys-on-primary-fixed);background-color:var(--sys-primary-fixed-dim);border-radius:var(--sys-radius-full);box-sizing:border-box}.actions{display:flex;flex-wrap:wrap;gap:var(--sys-padding-12);align-items:center;padding:var(--sys-padding-16) var(--sys-padding-24);border-top:var(--sys-stroke-thin) solid var(--sys-outline)}:host(.level-2){border:var(--sys-stroke-thin) solid var(--sys-outline-variant);border-radius:0;overflow:hidden}:host(.level-2):first-child{border-radius:var(--sys-radius-sm) var(--sys-radius-sm) 0 0}:host(.level-2):last-child{border-radius:0 0 var(--sys-radius-sm) var(--sys-radius-sm)}:host(.level-2):only-child{border-radius:var(--sys-radius-sm)}:host(.level-2.nested){border-radius:var(--sys-radius-sm)}:host(.level-2) .trigger{padding:var(--sys-padding-8) var(--sys-padding-24) var(--sys-padding-8) var(--sys-padding-24);gap:var(--sys-padding-4);font-size:var(--core-base);line-height:var(--core-xl)}:host(.level-2) .trigger-toggle{color:var(--sys-on-surface-variant);background-color:var(--sys-surface-container)}:host(.level-2) .actions{padding:var(--sys-padding-8) var(--sys-padding-24) var(--sys-padding-8) var(--sys-padding-80)}:host(.level-2) .content{padding:0 var(--sys-padding-24) var(--sys-padding-8) var(--sys-padding-80)}:host(.text-only){border:none}:host(.text-only) .trigger{padding:var(--sys-padding-8) 0;font-size:var(--core-base);font-weight:var(--sys-font-weight-emphasized);line-height:var(--core-xl)}:host(.text-only) .trigger-leading-icon{display:none}:host(.text-only) .trigger-toggle{order:-1;color:var(--sys-on-surface-variant);background-color:var(--sys-surface-container)}.content{padding:0 var(--sys-padding-16) var(--sys-padding-16);color:var(--sys-on-surface-variant);font-family:var(--core-body);font-size:var(--core-base);font-weight:var(--sys-font-weight);line-height:var(--core-xl);letter-spacing:var(--core-spacing-0)}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => ButtonComponent), selector: "compsych-button", inputs: ["label", "variant", "size", "icon", "iconOnly", "disabled"] }, { kind: "component", type: i0.forwardRef(() => AccordionComponent), selector: "compsych-accordion", inputs: ["items", "variant", "nested", "multi"] }] });
65
+ }
66
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionItemComponent, decorators: [{
67
+ type: Component,
68
+ args: [{ selector: 'compsych-accordion-item', standalone: true, imports: [ButtonComponent, forwardRef(() => AccordionComponent)], template: `
69
+ <button
70
+ class="trigger"
71
+ type="button"
72
+ [attr.aria-expanded]="expanded"
73
+ (click)="toggle()"
74
+ >
75
+ @if (iconSvg) {
76
+ <span class="trigger-leading-icon" [innerHTML]="iconSvg" aria-hidden="true"></span>
77
+ }
78
+ <span class="trigger-label">{{ title }}</span>
79
+ <span class="trigger-toggle material-symbols-rounded" aria-hidden="true">{{ expanded ? 'remove' : 'add' }}</span>
80
+ </button>
81
+ @if (expanded && content) {
82
+ <div class="content" role="region" [innerHTML]="sanitizedContent"></div>
83
+ }
84
+ @if (expanded && nestedContent.length) {
85
+ <compsych-accordion [items]="nestedContent" variant="level-2" [nested]="true" />
86
+ }
87
+ @if (expanded && buttons.length) {
88
+ <div class="actions">
89
+ @for (btn of buttons; track btn.label) {
90
+ <compsych-button [label]="btn.label" variant="filled" size="small" (click)="btn.action()" />
91
+ }
92
+ </div>
93
+ }
94
+ `, host: {
95
+ class: 'compsych-accordion-item',
96
+ '[class.level-2]': 'variant === "level-2"',
97
+ '[class.text-only]': 'variant === "text-only"',
98
+ '[class.nested]': 'nested',
99
+ }, styles: [":host{display:block;border-bottom:var(--sys-stroke-thin) solid var(--sys-outline-variant)}:host:first-child{border-top:var(--sys-stroke-thin) solid var(--sys-outline-variant)}.trigger{display:flex;align-items:center;gap:var(--sys-padding-8);width:100%;padding:var(--sys-padding-16) var(--sys-padding-24);background:none;border:none;cursor:pointer;text-align:left;color:var(--sys-on-surface);font-family:var(--core-title);font-size:var(--core-lg);font-weight:var(--sys-font-weight);line-height:var(--core-2xl);letter-spacing:var(--core-spacing-0);position:relative;overflow:hidden;border-radius:0}.trigger:before{content:\"\";position:absolute;inset:0;background-color:currentColor;opacity:0;transition:opacity .15s ease;pointer-events:none}.trigger:hover:before{opacity:.08}.trigger:active:before{opacity:.1}.trigger-label{flex:1;min-width:0}.trigger-leading-icon{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;color:var(--sys-on-surface);flex-shrink:0}.trigger-leading-icon svg{width:100%;height:100%}.trigger-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;font-size:1rem;line-height:1;color:var(--sys-on-primary-fixed);background-color:var(--sys-primary-fixed-dim);border-radius:var(--sys-radius-full);box-sizing:border-box}.actions{display:flex;flex-wrap:wrap;gap:var(--sys-padding-12);align-items:center;padding:var(--sys-padding-16) var(--sys-padding-24);border-top:var(--sys-stroke-thin) solid var(--sys-outline)}:host(.level-2){border:var(--sys-stroke-thin) solid var(--sys-outline-variant);border-radius:0;overflow:hidden}:host(.level-2):first-child{border-radius:var(--sys-radius-sm) var(--sys-radius-sm) 0 0}:host(.level-2):last-child{border-radius:0 0 var(--sys-radius-sm) var(--sys-radius-sm)}:host(.level-2):only-child{border-radius:var(--sys-radius-sm)}:host(.level-2.nested){border-radius:var(--sys-radius-sm)}:host(.level-2) .trigger{padding:var(--sys-padding-8) var(--sys-padding-24) var(--sys-padding-8) var(--sys-padding-24);gap:var(--sys-padding-4);font-size:var(--core-base);line-height:var(--core-xl)}:host(.level-2) .trigger-toggle{color:var(--sys-on-surface-variant);background-color:var(--sys-surface-container)}:host(.level-2) .actions{padding:var(--sys-padding-8) var(--sys-padding-24) var(--sys-padding-8) var(--sys-padding-80)}:host(.level-2) .content{padding:0 var(--sys-padding-24) var(--sys-padding-8) var(--sys-padding-80)}:host(.text-only){border:none}:host(.text-only) .trigger{padding:var(--sys-padding-8) 0;font-size:var(--core-base);font-weight:var(--sys-font-weight-emphasized);line-height:var(--core-xl)}:host(.text-only) .trigger-leading-icon{display:none}:host(.text-only) .trigger-toggle{order:-1;color:var(--sys-on-surface-variant);background-color:var(--sys-surface-container)}.content{padding:0 var(--sys-padding-16) var(--sys-padding-16);color:var(--sys-on-surface-variant);font-family:var(--core-body);font-size:var(--core-base);font-weight:var(--sys-font-weight);line-height:var(--core-xl);letter-spacing:var(--core-spacing-0)}\n"] }]
100
+ }], ctorParameters: () => [{ type: i1.DomSanitizer }], propDecorators: { title: [{
101
+ type: Input
102
+ }], content: [{
103
+ type: Input
104
+ }], buttons: [{
105
+ type: Input
106
+ }], nestedContent: [{
107
+ type: Input
108
+ }], variant: [{
109
+ type: Input
110
+ }], nested: [{
111
+ type: Input
112
+ }], icon: [{
113
+ type: Input
114
+ }], expanded: [{
115
+ type: Input
116
+ }], expandedChange: [{
117
+ type: Output
118
+ }] } });
5
119
  export class AccordionComponent {
6
- items;
120
+ items = [];
121
+ variant = 'default';
122
+ nested = false;
7
123
  get multi() { return this._multi; }
8
124
  set multi(value) { this._multi = coerceBooleanProperty(value); }
9
125
  _multi = false;
10
- subscriptions = [];
11
- ngAfterContentInit() {
12
- this.wireItems();
13
- this.items.changes.subscribe(() => {
14
- this.unwireItems();
15
- this.wireItems();
16
- });
17
- }
18
- ngOnDestroy() {
19
- this.unwireItems();
20
- }
21
- wireItems() {
22
- this.items.forEach(item => {
23
- const sub = item.expandedChange.subscribe(isExpanded => {
24
- if (isExpanded && !this._multi) {
25
- this.items.filter(i => i !== item).forEach(i => (i.expanded = false));
26
- }
27
- });
28
- this.subscriptions.push(sub);
29
- });
30
- }
31
- unwireItems() {
32
- this.subscriptions.forEach(s => s.unsubscribe());
33
- this.subscriptions = [];
126
+ expandedSet = new Set();
127
+ onExpandedChange(index, isExpanded) {
128
+ if (isExpanded) {
129
+ if (!this._multi)
130
+ this.expandedSet.clear();
131
+ this.expandedSet.add(index);
132
+ }
133
+ else {
134
+ this.expandedSet.delete(index);
135
+ }
136
+ this.expandedSet = new Set(this.expandedSet);
34
137
  }
35
138
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
36
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: AccordionComponent, isStandalone: true, selector: "compsych-accordion", inputs: { multi: "multi" }, queries: [{ propertyName: "items", predicate: AccordionItemComponent }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block;background-color:var(--surface-container-sys-surface-container-lowest);border:var(--sys-stroke-thin) solid var(--sys-outline);border-radius:var(--sys-radius-md);overflow:hidden}\n"] });
139
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: AccordionComponent, isStandalone: true, selector: "compsych-accordion", inputs: { items: "items", variant: "variant", nested: "nested", multi: "multi" }, host: { properties: { "class.level-2": "variant === \"level-2\"", "class.text-only": "variant === \"text-only\"", "class.nested": "nested" } }, ngImport: i0, template: `
140
+ @for (item of items; track $index; let i = $index) {
141
+ <compsych-accordion-item
142
+ [title]="item.title"
143
+ [content]="item.content ?? ''"
144
+ [icon]="item.icon ?? ''"
145
+ [buttons]="item.buttons ?? []"
146
+ [nestedContent]="item.nestedContent ?? []"
147
+ [variant]="variant"
148
+ [nested]="nested"
149
+ [expanded]="expandedSet.has(i)"
150
+ (expandedChange)="onExpandedChange(i, $event)"
151
+ />
152
+ }
153
+ `, isInline: true, styles: [":host{display:block;background-color:var(--sys-surface-container-lowest);border:var(--sys-stroke-thin) solid var(--sys-outline);border-radius:var(--sys-radius-md);overflow:hidden}:host(.level-2){display:flex;flex-direction:column;background-color:transparent;border:none;border-radius:0;overflow:visible}:host(.level-2.nested){gap:var(--sys-padding-12);padding:0 var(--sys-padding-24) var(--sys-padding-24) var(--sys-padding-80)}:host(.text-only){background-color:transparent;border:none;border-radius:0;overflow:visible}\n"], dependencies: [{ kind: "component", type: AccordionItemComponent, selector: "compsych-accordion-item", inputs: ["title", "content", "buttons", "nestedContent", "variant", "nested", "icon", "expanded"], outputs: ["expandedChange"] }] });
37
154
  }
38
155
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionComponent, decorators: [{
39
156
  type: Component,
40
- args: [{ selector: 'compsych-accordion', standalone: true, imports: [AccordionItemComponent], template: `<ng-content />`, styles: [":host{display:block;background-color:var(--surface-container-sys-surface-container-lowest);border:var(--sys-stroke-thin) solid var(--sys-outline);border-radius:var(--sys-radius-md);overflow:hidden}\n"] }]
157
+ args: [{ selector: 'compsych-accordion', standalone: true, imports: [AccordionItemComponent], template: `
158
+ @for (item of items; track $index; let i = $index) {
159
+ <compsych-accordion-item
160
+ [title]="item.title"
161
+ [content]="item.content ?? ''"
162
+ [icon]="item.icon ?? ''"
163
+ [buttons]="item.buttons ?? []"
164
+ [nestedContent]="item.nestedContent ?? []"
165
+ [variant]="variant"
166
+ [nested]="nested"
167
+ [expanded]="expandedSet.has(i)"
168
+ (expandedChange)="onExpandedChange(i, $event)"
169
+ />
170
+ }
171
+ `, host: {
172
+ '[class.level-2]': 'variant === "level-2"',
173
+ '[class.text-only]': 'variant === "text-only"',
174
+ '[class.nested]': 'nested',
175
+ }, styles: [":host{display:block;background-color:var(--sys-surface-container-lowest);border:var(--sys-stroke-thin) solid var(--sys-outline);border-radius:var(--sys-radius-md);overflow:hidden}:host(.level-2){display:flex;flex-direction:column;background-color:transparent;border:none;border-radius:0;overflow:visible}:host(.level-2.nested){gap:var(--sys-padding-12);padding:0 var(--sys-padding-24) var(--sys-padding-24) var(--sys-padding-80)}:host(.text-only){background-color:transparent;border:none;border-radius:0;overflow:visible}\n"] }]
41
176
  }], propDecorators: { items: [{
42
- type: ContentChildren,
43
- args: [AccordionItemComponent]
177
+ type: Input
178
+ }], variant: [{
179
+ type: Input
180
+ }], nested: [{
181
+ type: Input
44
182
  }], multi: [{
45
183
  type: Input
46
184
  }] } });
@@ -1 +1 @@
1
- {"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../../../../../packages/angular/src/lib/accordion/accordion.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EACT,eAAe,EACf,KAAK,GAGN,MAAM,eAAe,CAAC;AACvB,OAAO,EAAgB,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;;AAS1D,MAAM,OAAO,kBAAkB;IACY,KAAK,CAAqC;IAEnF,IACI,KAAK,KAAc,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5C,IAAI,KAAK,CAAC,KAAmB,IAAI,IAAI,CAAC,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,GAAG,KAAK,CAAC;IAEf,aAAa,GAA8B,EAAE,CAAC;IAEtD,kBAAkB;QAChB,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE;YAChC,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,WAAW;QACT,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACxB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE;gBACrD,IAAI,UAAU,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;IAC1B,CAAC;wGApCU,kBAAkB;4FAAlB,kBAAkB,gIACZ,sBAAsB,6BAJ7B,gBAAgB;;4FAGf,kBAAkB;kBAP9B,SAAS;+BACE,oBAAoB,cAClB,IAAI,WACP,CAAC,sBAAsB,CAAC,YACvB,gBAAgB;;sBAIzB,eAAe;uBAAC,sBAAsB;;sBAEtC,KAAK","sourcesContent":["import {\n AfterContentInit,\n Component,\n ContentChildren,\n Input,\n OnDestroy,\n QueryList,\n} from '@angular/core';\nimport { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { AccordionItemComponent } from './accordion-item';\n\n@Component({\n selector: 'compsych-accordion',\n standalone: true,\n imports: [AccordionItemComponent],\n template: `<ng-content />`,\n styleUrl: './accordion.css',\n})\nexport class AccordionComponent implements AfterContentInit, OnDestroy {\n @ContentChildren(AccordionItemComponent) items!: QueryList<AccordionItemComponent>;\n\n @Input()\n get multi(): boolean { return this._multi; }\n set multi(value: BooleanInput) { this._multi = coerceBooleanProperty(value); }\n private _multi = false;\n\n private subscriptions: { unsubscribe(): void }[] = [];\n\n ngAfterContentInit(): void {\n this.wireItems();\n this.items.changes.subscribe(() => {\n this.unwireItems();\n this.wireItems();\n });\n }\n\n ngOnDestroy(): void {\n this.unwireItems();\n }\n\n private wireItems(): void {\n this.items.forEach(item => {\n const sub = item.expandedChange.subscribe(isExpanded => {\n if (isExpanded && !this._multi) {\n this.items.filter(i => i !== item).forEach(i => (i.expanded = false));\n }\n });\n this.subscriptions.push(sub);\n });\n }\n\n private unwireItems(): void {\n this.subscriptions.forEach(s => s.unsubscribe());\n this.subscriptions = [];\n }\n}\n"]}
1
+ {"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../../../../../packages/angular/src/lib/accordion/accordion.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,UAAU,EACV,KAAK,EACL,MAAM,EACN,eAAe,GAChB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAgB,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;;;AAKnD,yFAAyF;AACzF,wFAAwF;AACxF,wEAAwE;AAwCxE,MAAM,OAAO,sBAAsB;IAoBJ;IAnBpB,KAAK,GAAG,EAAE,CAAC;IACX,OAAO,GAAG,EAAE,CAAC;IACb,OAAO,GAAsB,EAAE,CAAC;IAChC,aAAa,GAA0B,EAAE,CAAC;IAC1C,OAAO,GAAqB,SAAS,CAAC;IACtC,MAAM,GAAG,KAAK,CAAC;IAExB,IACI,IAAI,CAAC,IAAY;QACnB,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,CAAC;IAED,OAAO,GAAoB,IAAI,CAAC;IAEhC,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC3E,CAAC;IAED,YAA6B,SAAuB;QAAvB,cAAS,GAAT,SAAS,CAAc;IAAG,CAAC;IAExD,IACI,QAAQ,KAAc,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAClD,IAAI,QAAQ,CAAC,KAAmB,IAAI,IAAI,CAAC,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5E,SAAS,GAAG,KAAK,CAAC;IAEhB,cAAc,GAAG,IAAI,YAAY,EAAW,CAAC;IAEvD,MAAM;QACJ,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;wGAhCU,sBAAsB;4FAAtB,sBAAsB,2eAnCvB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BT,2lGA3BS,eAAe,uJAiGd,kBAAkB;;4FA7DlB,sBAAsB;kBAvClC,SAAS;+BACE,yBAAyB,cACvB,IAAI,WACP,CAAC,eAAe,EAAE,UAAU,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,CAAC,YACtD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BT,QAEK;wBACJ,KAAK,EAAE,yBAAyB;wBAChC,iBAAiB,EAAE,uBAAuB;wBAC1C,mBAAmB,EAAE,yBAAyB;wBAC9C,gBAAgB,EAAE,QAAQ;qBAC3B;;sBAGA,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBAEL,KAAK;;sBAcL,KAAK;;sBAKL,MAAM;;AAkCT,MAAM,OAAO,kBAAkB;IACpB,KAAK,GAAoB,EAAE,CAAC;IAC5B,OAAO,GAAqB,SAAS,CAAC;IACtC,MAAM,GAAG,KAAK,CAAC;IAExB,IACI,KAAK,KAAc,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5C,IAAI,KAAK,CAAC,KAAmB,IAAI,IAAI,CAAC,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,GAAG,KAAK,CAAC;IAEvB,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhC,gBAAgB,CAAC,KAAa,EAAE,UAAmB;QACjD,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;YAC3C,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/C,CAAC;wGApBU,kBAAkB;4FAAlB,kBAAkB,gTAtBnB;;;;;;;;;;;;;;GAcT,qlBArDU,sBAAsB;;4FA6DtB,kBAAkB;kBA1B9B,SAAS;+BACE,oBAAoB,cAClB,IAAI,WACP,CAAC,sBAAsB,CAAC,YACvB;;;;;;;;;;;;;;GAcT,QAEK;wBACJ,iBAAiB,EAAE,uBAAuB;wBAC1C,mBAAmB,EAAE,yBAAyB;wBAC9C,gBAAgB,EAAE,QAAQ;qBAC3B;;sBAGA,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBAEL,KAAK","sourcesContent":["import {\n Component,\n EventEmitter,\n forwardRef,\n Input,\n Output,\n SecurityContext,\n} from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { LUCIDE_ICONS } from '@compsych-ui-components/shared/assets/lucide-icons.generated';\nimport { ButtonComponent } from '../button/button';\nimport { AccordionButton, AccordionItem, AccordionVariant, NestedAccordionItem } from './accordion-types';\n\nexport type { AccordionButton, AccordionItem, AccordionVariant, NestedAccordionItem };\n\n// AccordionItemComponent is defined before AccordionComponent because AccordionComponent\n// uses it directly in its imports. AccordionItemComponent references AccordionComponent\n// via forwardRef to break the forward-reference cycle within this file.\n@Component({\n selector: 'compsych-accordion-item',\n standalone: true,\n imports: [ButtonComponent, forwardRef(() => AccordionComponent)],\n template: `\n <button\n class=\"trigger\"\n type=\"button\"\n [attr.aria-expanded]=\"expanded\"\n (click)=\"toggle()\"\n >\n @if (iconSvg) {\n <span class=\"trigger-leading-icon\" [innerHTML]=\"iconSvg\" aria-hidden=\"true\"></span>\n }\n <span class=\"trigger-label\">{{ title }}</span>\n <span class=\"trigger-toggle material-symbols-rounded\" aria-hidden=\"true\">{{ expanded ? 'remove' : 'add' }}</span>\n </button>\n @if (expanded && content) {\n <div class=\"content\" role=\"region\" [innerHTML]=\"sanitizedContent\"></div>\n }\n @if (expanded && nestedContent.length) {\n <compsych-accordion [items]=\"nestedContent\" variant=\"level-2\" [nested]=\"true\" />\n }\n @if (expanded && buttons.length) {\n <div class=\"actions\">\n @for (btn of buttons; track btn.label) {\n <compsych-button [label]=\"btn.label\" variant=\"filled\" size=\"small\" (click)=\"btn.action()\" />\n }\n </div>\n }\n `,\n styleUrl: './accordion-item.css',\n host: {\n class: 'compsych-accordion-item',\n '[class.level-2]': 'variant === \"level-2\"',\n '[class.text-only]': 'variant === \"text-only\"',\n '[class.nested]': 'nested',\n },\n})\nexport class AccordionItemComponent {\n @Input() title = '';\n @Input() content = '';\n @Input() buttons: AccordionButton[] = [];\n @Input() nestedContent: NestedAccordionItem[] = [];\n @Input() variant: AccordionVariant = 'default';\n @Input() nested = false;\n\n @Input()\n set icon(name: string) {\n const svg = LUCIDE_ICONS[name];\n this.iconSvg = svg ? this.sanitizer.bypassSecurityTrustHtml(svg) : null;\n }\n\n iconSvg: SafeHtml | null = null;\n\n get sanitizedContent(): SafeHtml {\n return this.sanitizer.sanitize(SecurityContext.HTML, this.content) ?? '';\n }\n\n constructor(private readonly sanitizer: DomSanitizer) {}\n\n @Input()\n get expanded(): boolean { return this._expanded; }\n set expanded(value: BooleanInput) { this._expanded = coerceBooleanProperty(value); }\n private _expanded = false;\n\n @Output() expandedChange = new EventEmitter<boolean>();\n\n toggle(): void {\n this._expanded = !this._expanded;\n this.expandedChange.emit(this._expanded);\n }\n}\n\n@Component({\n selector: 'compsych-accordion',\n standalone: true,\n imports: [AccordionItemComponent],\n template: `\n @for (item of items; track $index; let i = $index) {\n <compsych-accordion-item\n [title]=\"item.title\"\n [content]=\"item.content ?? ''\"\n [icon]=\"item.icon ?? ''\"\n [buttons]=\"item.buttons ?? []\"\n [nestedContent]=\"item.nestedContent ?? []\"\n [variant]=\"variant\"\n [nested]=\"nested\"\n [expanded]=\"expandedSet.has(i)\"\n (expandedChange)=\"onExpandedChange(i, $event)\"\n />\n }\n `,\n styleUrl: './accordion.css',\n host: {\n '[class.level-2]': 'variant === \"level-2\"',\n '[class.text-only]': 'variant === \"text-only\"',\n '[class.nested]': 'nested',\n },\n})\nexport class AccordionComponent {\n @Input() items: AccordionItem[] = [];\n @Input() variant: AccordionVariant = 'default';\n @Input() nested = false;\n\n @Input()\n get multi(): boolean { return this._multi; }\n set multi(value: BooleanInput) { this._multi = coerceBooleanProperty(value); }\n private _multi = false;\n\n expandedSet = new Set<number>();\n\n onExpandedChange(index: number, isExpanded: boolean): void {\n if (isExpanded) {\n if (!this._multi) this.expandedSet.clear();\n this.expandedSet.add(index);\n } else {\n this.expandedSet.delete(index);\n }\n this.expandedSet = new Set(this.expandedSet);\n }\n}\n"]}
@@ -42,14 +42,14 @@ export class ButtonComponent {
42
42
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: ButtonComponent, isStandalone: true, selector: "compsych-button", inputs: { label: "label", variant: "variant", size: "size", icon: "icon", iconOnly: "iconOnly", disabled: "disabled" }, host: { properties: { "class": "this.hostClass", "attr.disabled": "this.attrDisabled" } }, ngImport: i0, template: `
43
43
  <span *ngIf="icon" class="icon material-symbols-rounded" aria-hidden="true">{{ icon }}</span>
44
44
  <span class="label">{{ label }}</span>
45
- `, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;border-radius:var(--sys-radius-full);border:none;cursor:pointer;white-space:nowrap;position:relative;overflow:hidden}:host:before{content:\"\";position:absolute;inset:0;border-radius:inherit;background-color:currentColor;opacity:0;transition:opacity .15s ease;pointer-events:none}:host(:hover):before{opacity:.08}:host(:active):before{opacity:.1}:host(.focus-keyboard):before{opacity:.12}:host(.focus-keyboard){outline:var(--sys-stroke-thick) solid var(--primary-fixed-sys-on-primary-fixed-variant);outline-offset:var(--sys-stroke-thick)}:host:disabled,:host([disabled]){cursor:not-allowed;opacity:.38;pointer-events:none}.icon{font-size:inherit;line-height:1;-webkit-user-select:none;user-select:none}:host(.icon-only){padding:0;aspect-ratio:1}:host(.icon-only.small){width:2rem}:host(.icon-only.medium){width:2.5rem}:host(.icon-only.large){width:3rem}:host(.icon-only.xlarge){width:3.5rem}:host(.small){gap:var(--padding-sys-padding-4);height:2rem;padding:var(--padding-sys-padding-4) var(--padding-sys-padding-12);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.medium){gap:var(--padding-sys-padding-8);height:2.5rem;padding:var(--padding-sys-padding-8) var(--padding-sys-padding-16);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.large){gap:var(--padding-sys-padding-8);height:3rem;padding:var(--padding-sys-padding-8) var(--padding-sys-padding-24);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.xlarge){gap:var(--padding-sys-padding-12);height:3.5rem;padding:var(--padding-sys-padding-8) var(--padding-sys-padding-24);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.filled){background-color:var(--primary-sys-primary);color:var(--primary-sys-on-primary)}:host(.tonal){background-color:var(--primary-fixed-sys-primary-fixed-dim);color:var(--primary-fixed-sys-on-primary-fixed)}:host(.outlined){background-color:transparent;color:var(--surface-sys-on-surface);border:var(--sys-stroke-thin) solid var(--sys-outline)}:host(.elevated){background-color:var(--surface-container-sys-surface-container-lowest);color:var(--surface-sys-on-surface);box-shadow:0 .125rem .25rem #00000014,0 .25rem 1rem var(--neutral-sys-black-10)}:host(.text){background-color:transparent;color:var(--surface-sys-on-surface);padding-inline:0}:host(.danger){background-color:var(--sys-error);color:var(--sys-on-error)}:host(.danger-outlined){background-color:transparent;color:var(--sys-error);border:var(--sys-stroke-thin) solid var(--sys-error-container)}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
45
+ `, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center;border-radius:var(--sys-radius-full);border:none;cursor:pointer;white-space:nowrap;position:relative;overflow:hidden}:host:before{content:\"\";position:absolute;inset:0;border-radius:inherit;background-color:currentColor;opacity:0;transition:opacity .15s ease;pointer-events:none}:host(:hover):before{opacity:.08}:host(:active):before{opacity:.1}:host(.focus-keyboard):before{opacity:.12}:host(.focus-keyboard){outline:var(--sys-stroke-thick) solid var(--sys-on-primary-fixed-variant);outline-offset:var(--sys-stroke-thick)}:host:disabled,:host([disabled]){cursor:not-allowed;opacity:.38;pointer-events:none}.icon{font-size:inherit;line-height:1;-webkit-user-select:none;user-select:none}:host(.icon-only){padding:0;aspect-ratio:1}:host(.icon-only.small){width:2rem}:host(.icon-only.medium){width:2.5rem}:host(.icon-only.large){width:3rem}:host(.icon-only.xlarge){width:3.5rem}:host(.small){gap:var(--sys-padding-4);height:2rem;padding:var(--sys-padding-4) var(--sys-padding-12);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.medium){gap:var(--sys-padding-8);height:2.5rem;padding:var(--sys-padding-8) var(--sys-padding-16);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.large){gap:var(--sys-padding-8);height:3rem;padding:var(--sys-padding-8) var(--sys-padding-24);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.xlarge){gap:var(--sys-padding-12);height:3.5rem;padding:var(--sys-padding-8) var(--sys-padding-24);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.filled){background-color:var(--sys-primary);color:var(--sys-on-primary)}:host(.tonal){background-color:var(--sys-primary-fixed-dim);color:var(--sys-on-primary-fixed)}:host(.outlined){background-color:transparent;color:var(--sys-on-surface);border:var(--sys-stroke-thin) solid var(--sys-outline)}:host(.elevated){background-color:var(--sys-surface-container-lowest);color:var(--sys-on-surface);box-shadow:0 .125rem .25rem #00000014,0 .25rem 1rem var(--sys-black-10)}:host(.text){background-color:transparent;color:var(--sys-on-surface);padding-inline:0}:host(.danger){background-color:var(--sys-error);color:var(--sys-on-error)}:host(.danger-outlined){background-color:transparent;color:var(--sys-error);border:var(--sys-stroke-thin) solid var(--sys-error-container)}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
46
46
  }
47
47
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ButtonComponent, decorators: [{
48
48
  type: Component,
49
49
  args: [{ selector: 'compsych-button', standalone: true, imports: [NgIf], template: `
50
50
  <span *ngIf="icon" class="icon material-symbols-rounded" aria-hidden="true">{{ icon }}</span>
51
51
  <span class="label">{{ label }}</span>
52
- `, styles: [":host{display:inline-flex;align-items:center;justify-content:center;border-radius:var(--sys-radius-full);border:none;cursor:pointer;white-space:nowrap;position:relative;overflow:hidden}:host:before{content:\"\";position:absolute;inset:0;border-radius:inherit;background-color:currentColor;opacity:0;transition:opacity .15s ease;pointer-events:none}:host(:hover):before{opacity:.08}:host(:active):before{opacity:.1}:host(.focus-keyboard):before{opacity:.12}:host(.focus-keyboard){outline:var(--sys-stroke-thick) solid var(--primary-fixed-sys-on-primary-fixed-variant);outline-offset:var(--sys-stroke-thick)}:host:disabled,:host([disabled]){cursor:not-allowed;opacity:.38;pointer-events:none}.icon{font-size:inherit;line-height:1;-webkit-user-select:none;user-select:none}:host(.icon-only){padding:0;aspect-ratio:1}:host(.icon-only.small){width:2rem}:host(.icon-only.medium){width:2.5rem}:host(.icon-only.large){width:3rem}:host(.icon-only.xlarge){width:3.5rem}:host(.small){gap:var(--padding-sys-padding-4);height:2rem;padding:var(--padding-sys-padding-4) var(--padding-sys-padding-12);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.medium){gap:var(--padding-sys-padding-8);height:2.5rem;padding:var(--padding-sys-padding-8) var(--padding-sys-padding-16);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.large){gap:var(--padding-sys-padding-8);height:3rem;padding:var(--padding-sys-padding-8) var(--padding-sys-padding-24);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.xlarge){gap:var(--padding-sys-padding-12);height:3.5rem;padding:var(--padding-sys-padding-8) var(--padding-sys-padding-24);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.filled){background-color:var(--primary-sys-primary);color:var(--primary-sys-on-primary)}:host(.tonal){background-color:var(--primary-fixed-sys-primary-fixed-dim);color:var(--primary-fixed-sys-on-primary-fixed)}:host(.outlined){background-color:transparent;color:var(--surface-sys-on-surface);border:var(--sys-stroke-thin) solid var(--sys-outline)}:host(.elevated){background-color:var(--surface-container-sys-surface-container-lowest);color:var(--surface-sys-on-surface);box-shadow:0 .125rem .25rem #00000014,0 .25rem 1rem var(--neutral-sys-black-10)}:host(.text){background-color:transparent;color:var(--surface-sys-on-surface);padding-inline:0}:host(.danger){background-color:var(--sys-error);color:var(--sys-on-error)}:host(.danger-outlined){background-color:transparent;color:var(--sys-error);border:var(--sys-stroke-thin) solid var(--sys-error-container)}\n"] }]
52
+ `, styles: [":host{display:inline-flex;align-items:center;justify-content:center;border-radius:var(--sys-radius-full);border:none;cursor:pointer;white-space:nowrap;position:relative;overflow:hidden}:host:before{content:\"\";position:absolute;inset:0;border-radius:inherit;background-color:currentColor;opacity:0;transition:opacity .15s ease;pointer-events:none}:host(:hover):before{opacity:.08}:host(:active):before{opacity:.1}:host(.focus-keyboard):before{opacity:.12}:host(.focus-keyboard){outline:var(--sys-stroke-thick) solid var(--sys-on-primary-fixed-variant);outline-offset:var(--sys-stroke-thick)}:host:disabled,:host([disabled]){cursor:not-allowed;opacity:.38;pointer-events:none}.icon{font-size:inherit;line-height:1;-webkit-user-select:none;user-select:none}:host(.icon-only){padding:0;aspect-ratio:1}:host(.icon-only.small){width:2rem}:host(.icon-only.medium){width:2.5rem}:host(.icon-only.large){width:3rem}:host(.icon-only.xlarge){width:3.5rem}:host(.small){gap:var(--sys-padding-4);height:2rem;padding:var(--sys-padding-4) var(--sys-padding-12);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.medium){gap:var(--sys-padding-8);height:2.5rem;padding:var(--sys-padding-8) var(--sys-padding-16);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.large){gap:var(--sys-padding-8);height:3rem;padding:var(--sys-padding-8) var(--sys-padding-24);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.xlarge){gap:var(--sys-padding-12);height:3.5rem;padding:var(--sys-padding-8) var(--sys-padding-24);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight-emphasized);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking)}:host(.filled){background-color:var(--sys-primary);color:var(--sys-on-primary)}:host(.tonal){background-color:var(--sys-primary-fixed-dim);color:var(--sys-on-primary-fixed)}:host(.outlined){background-color:transparent;color:var(--sys-on-surface);border:var(--sys-stroke-thin) solid var(--sys-outline)}:host(.elevated){background-color:var(--sys-surface-container-lowest);color:var(--sys-on-surface);box-shadow:0 .125rem .25rem #00000014,0 .25rem 1rem var(--sys-black-10)}:host(.text){background-color:transparent;color:var(--sys-on-surface);padding-inline:0}:host(.danger){background-color:var(--sys-error);color:var(--sys-on-error)}:host(.danger-outlined){background-color:transparent;color:var(--sys-error);border:var(--sys-stroke-thin) solid var(--sys-error-container)}\n"] }]
53
53
  }], propDecorators: { label: [{
54
54
  type: Input
55
55
  }], variant: [{
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../../../packages/angular/src/lib/button/button.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,WAAW,EACX,KAAK,EACL,UAAU,EAGV,MAAM,GACP,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAe,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAgB,MAAM,uBAAuB,CAAC;;AAY5E,MAAM,OAAO,eAAe;IACT,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IACpC,UAAU,GAAG,MAAM,CAAC,CAAA,UAAuB,CAAA,CAAC,CAAC;IAErD,KAAK,GAAG,EAAE,CAAC;IACX,OAAO,GAAyF,QAAQ,CAAC;IACzG,IAAI,GAA4C,OAAO,CAAC;IACxD,IAAI,CAAU;IAEvB,IACI,QAAQ,KAAc,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAClD,IAAI,QAAQ,CAAC,KAAmB,IAAI,IAAI,CAAC,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5E,SAAS,GAAG,KAAK,CAAC;IAE1B,IACI,QAAQ,KAAc,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAClD,IAAI,QAAQ,CAAC,KAAmB,IAAI,IAAI,CAAC,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5E,SAAS,GAAG,KAAK,CAAC;IAEhB,QAAQ,GAAG,KAAK,CAAC;IACjB,YAAY,GAAgB,IAAI,CAAC;IAE3C,IAA0B,SAAS;QACjC,OAAO;YACL,IAAI,CAAC,OAAO;YACZ,IAAI,CAAC,IAAI;YACT,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;YACjC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,YAAY,KAAK,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE;SAC1E,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,IAAkC,YAAY;QAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,CAAC;IAED,eAAe;QACb,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;YAC5D,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;YACzB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,WAAW;QACT,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC;wGA5CU,eAAe;4FAAf,eAAe,8RANhB;;;GAGT,qkGAJS,IAAI;;4FAOH,eAAe;kBAV3B,SAAS;+BACE,iBAAiB,cACf,IAAI,WACP,CAAC,IAAI,CAAC,YACL;;;GAGT;;sBAOA,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBAEL,KAAK;;sBAKL,KAAK;;sBAQL,WAAW;uBAAC,OAAO;;sBASnB,WAAW;uBAAC,eAAe","sourcesContent":["import {\r\n Component,\r\n HostBinding,\r\n Input,\r\n ElementRef,\r\n AfterViewInit,\r\n OnDestroy,\r\n inject,\r\n} from '@angular/core';\r\nimport { NgIf } from '@angular/common';\r\nimport { FocusMonitor, FocusOrigin } from '@angular/cdk/a11y';\r\nimport { coerceBooleanProperty, BooleanInput } from '@angular/cdk/coercion';\r\n\r\n@Component({\r\n selector: 'compsych-button',\r\n standalone: true,\r\n imports: [NgIf],\r\n template: `\r\n <span *ngIf=\"icon\" class=\"icon material-symbols-rounded\" aria-hidden=\"true\">{{ icon }}</span>\r\n <span class=\"label\">{{ label }}</span>\r\n `,\r\n styleUrl: './button.css',\r\n})\r\nexport class ButtonComponent implements AfterViewInit, OnDestroy {\r\n private readonly focusMonitor = inject(FocusMonitor);\r\n private readonly elementRef = inject(ElementRef<HTMLElement>);\r\n\r\n @Input() label = '';\r\n @Input() variant: 'filled' | 'tonal' | 'outlined' | 'elevated' | 'text' | 'danger' | 'danger-outlined' = 'filled';\r\n @Input() size: 'small' | 'medium' | 'large' | 'xlarge' = 'small';\r\n @Input() icon?: string;\r\n\r\n @Input()\r\n get iconOnly(): boolean { return this._iconOnly; }\r\n set iconOnly(value: BooleanInput) { this._iconOnly = coerceBooleanProperty(value); }\r\n private _iconOnly = false;\r\n\r\n @Input()\r\n get disabled(): boolean { return this._disabled; }\r\n set disabled(value: BooleanInput) { this._disabled = coerceBooleanProperty(value); }\r\n private _disabled = false;\r\n\r\n protected _focused = false;\r\n protected _focusOrigin: FocusOrigin = null;\r\n\r\n @HostBinding('class') get hostClass(): string {\r\n return [\r\n this.variant,\r\n this.size,\r\n this._iconOnly ? 'icon-only' : '',\r\n this._focused && this._focusOrigin === 'keyboard' ? 'focus-keyboard' : '',\r\n ].filter(Boolean).join(' ');\r\n }\r\n\r\n @HostBinding('attr.disabled') get attrDisabled(): '' | null {\r\n return this._disabled ? '' : null;\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n this.focusMonitor.monitor(this.elementRef).subscribe(origin => {\r\n this._focused = !!origin;\r\n this._focusOrigin = origin;\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.focusMonitor.stopMonitoring(this.elementRef);\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../../../packages/angular/src/lib/button/button.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,WAAW,EACX,KAAK,EACL,UAAU,EAGV,MAAM,GACP,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAe,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAgB,MAAM,uBAAuB,CAAC;;AAY5E,MAAM,OAAO,eAAe;IACT,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IACpC,UAAU,GAAG,MAAM,CAAC,CAAA,UAAuB,CAAA,CAAC,CAAC;IAErD,KAAK,GAAG,EAAE,CAAC;IACX,OAAO,GAAyF,QAAQ,CAAC;IACzG,IAAI,GAA4C,OAAO,CAAC;IACxD,IAAI,CAAU;IAEvB,IACI,QAAQ,KAAc,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAClD,IAAI,QAAQ,CAAC,KAAmB,IAAI,IAAI,CAAC,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5E,SAAS,GAAG,KAAK,CAAC;IAE1B,IACI,QAAQ,KAAc,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAClD,IAAI,QAAQ,CAAC,KAAmB,IAAI,IAAI,CAAC,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5E,SAAS,GAAG,KAAK,CAAC;IAEhB,QAAQ,GAAG,KAAK,CAAC;IACjB,YAAY,GAAgB,IAAI,CAAC;IAE3C,IAA0B,SAAS;QACjC,OAAO;YACL,IAAI,CAAC,OAAO;YACZ,IAAI,CAAC,IAAI;YACT,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;YACjC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,YAAY,KAAK,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE;SAC1E,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,IAAkC,YAAY;QAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,CAAC;IAED,eAAe;QACb,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;YAC5D,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC;YACzB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,WAAW;QACT,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC;wGA5CU,eAAe;4FAAf,eAAe,8RANhB;;;GAGT,y3FAJS,IAAI;;4FAOH,eAAe;kBAV3B,SAAS;+BACE,iBAAiB,cACf,IAAI,WACP,CAAC,IAAI,CAAC,YACL;;;GAGT;;sBAOA,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBACL,KAAK;;sBAEL,KAAK;;sBAKL,KAAK;;sBAQL,WAAW;uBAAC,OAAO;;sBASnB,WAAW;uBAAC,eAAe","sourcesContent":["import {\r\n Component,\r\n HostBinding,\r\n Input,\r\n ElementRef,\r\n AfterViewInit,\r\n OnDestroy,\r\n inject,\r\n} from '@angular/core';\r\nimport { NgIf } from '@angular/common';\r\nimport { FocusMonitor, FocusOrigin } from '@angular/cdk/a11y';\r\nimport { coerceBooleanProperty, BooleanInput } from '@angular/cdk/coercion';\r\n\r\n@Component({\r\n selector: 'compsych-button',\r\n standalone: true,\r\n imports: [NgIf],\r\n template: `\r\n <span *ngIf=\"icon\" class=\"icon material-symbols-rounded\" aria-hidden=\"true\">{{ icon }}</span>\r\n <span class=\"label\">{{ label }}</span>\r\n `,\r\n styleUrl: './button.css',\r\n})\r\nexport class ButtonComponent implements AfterViewInit, OnDestroy {\r\n private readonly focusMonitor = inject(FocusMonitor);\r\n private readonly elementRef = inject(ElementRef<HTMLElement>);\r\n\r\n @Input() label = '';\r\n @Input() variant: 'filled' | 'tonal' | 'outlined' | 'elevated' | 'text' | 'danger' | 'danger-outlined' = 'filled';\r\n @Input() size: 'small' | 'medium' | 'large' | 'xlarge' = 'small';\r\n @Input() icon?: string;\r\n\r\n @Input()\r\n get iconOnly(): boolean { return this._iconOnly; }\r\n set iconOnly(value: BooleanInput) { this._iconOnly = coerceBooleanProperty(value); }\r\n private _iconOnly = false;\r\n\r\n @Input()\r\n get disabled(): boolean { return this._disabled; }\r\n set disabled(value: BooleanInput) { this._disabled = coerceBooleanProperty(value); }\r\n private _disabled = false;\r\n\r\n protected _focused = false;\r\n protected _focusOrigin: FocusOrigin = null;\r\n\r\n @HostBinding('class') get hostClass(): string {\r\n return [\r\n this.variant,\r\n this.size,\r\n this._iconOnly ? 'icon-only' : '',\r\n this._focused && this._focusOrigin === 'keyboard' ? 'focus-keyboard' : '',\r\n ].filter(Boolean).join(' ');\r\n }\r\n\r\n @HostBinding('attr.disabled') get attrDisabled(): '' | null {\r\n return this._disabled ? '' : null;\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n this.focusMonitor.monitor(this.elementRef).subscribe(origin => {\r\n this._focused = !!origin;\r\n this._focusOrigin = origin;\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.focusMonitor.stopMonitoring(this.elementRef);\r\n }\r\n}\r\n"]}
package/index.d.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import * as i1 from "./lib/button/button";
3
3
  import * as i2 from "./lib/accordion/accordion";
4
- import * as i3 from "./lib/accordion/accordion-item";
5
4
  export { ButtonComponent } from './lib/button/button';
6
5
  export { AccordionComponent } from './lib/accordion/accordion';
7
- export { AccordionItemComponent } from './lib/accordion/accordion-item';
6
+ export type { AccordionItem, AccordionButton, AccordionVariant, NestedAccordionItem } from './lib/accordion/accordion-types';
8
7
  export declare class CompsychAngularModule {
9
8
  static ɵfac: i0.ɵɵFactoryDeclaration<CompsychAngularModule, never>;
10
- static ɵmod: i0.ɵɵNgModuleDeclaration<CompsychAngularModule, never, [typeof i1.ButtonComponent, typeof i2.AccordionComponent, typeof i3.AccordionItemComponent], [typeof i1.ButtonComponent, typeof i2.AccordionComponent, typeof i3.AccordionItemComponent]>;
9
+ static ɵmod: i0.ɵɵNgModuleDeclaration<CompsychAngularModule, never, [typeof i1.ButtonComponent, typeof i2.AccordionComponent], [typeof i1.ButtonComponent, typeof i2.AccordionComponent]>;
11
10
  static ɵinj: i0.ɵɵInjectorDeclaration<CompsychAngularModule>;
12
11
  }
@@ -0,0 +1,14 @@
1
+ export type AccordionVariant = 'default' | 'level-2' | 'text-only';
2
+ export interface AccordionButton {
3
+ label: string;
4
+ action: () => void;
5
+ }
6
+ export type NestedAccordionItem = Omit<AccordionItem, 'buttons' | 'nestedContent'>;
7
+ export interface AccordionItem {
8
+ title: string;
9
+ content?: string;
10
+ icon?: string;
11
+ expanded?: boolean;
12
+ buttons?: AccordionButton[];
13
+ nestedContent?: NestedAccordionItem[];
14
+ }
@@ -1,17 +1,38 @@
1
- import { AfterContentInit, OnDestroy, QueryList } from '@angular/core';
1
+ import { EventEmitter } from '@angular/core';
2
+ import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
2
3
  import { BooleanInput } from '@angular/cdk/coercion';
3
- import { AccordionItemComponent } from './accordion-item';
4
+ import { AccordionButton, AccordionItem, AccordionVariant, NestedAccordionItem } from './accordion-types';
4
5
  import * as i0 from "@angular/core";
5
- export declare class AccordionComponent implements AfterContentInit, OnDestroy {
6
- items: QueryList<AccordionItemComponent>;
6
+ export type { AccordionButton, AccordionItem, AccordionVariant, NestedAccordionItem };
7
+ export declare class AccordionItemComponent {
8
+ private readonly sanitizer;
9
+ title: string;
10
+ content: string;
11
+ buttons: AccordionButton[];
12
+ nestedContent: NestedAccordionItem[];
13
+ variant: AccordionVariant;
14
+ nested: boolean;
15
+ set icon(name: string);
16
+ iconSvg: SafeHtml | null;
17
+ get sanitizedContent(): SafeHtml;
18
+ constructor(sanitizer: DomSanitizer);
19
+ get expanded(): boolean;
20
+ set expanded(value: BooleanInput);
21
+ private _expanded;
22
+ expandedChange: EventEmitter<boolean>;
23
+ toggle(): void;
24
+ static ɵfac: i0.ɵɵFactoryDeclaration<AccordionItemComponent, never>;
25
+ static ɵcmp: i0.ɵɵComponentDeclaration<AccordionItemComponent, "compsych-accordion-item", never, { "title": { "alias": "title"; "required": false; }; "content": { "alias": "content"; "required": false; }; "buttons": { "alias": "buttons"; "required": false; }; "nestedContent": { "alias": "nestedContent"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "nested": { "alias": "nested"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "expanded": { "alias": "expanded"; "required": false; }; }, { "expandedChange": "expandedChange"; }, never, never, true, never>;
26
+ }
27
+ export declare class AccordionComponent {
28
+ items: AccordionItem[];
29
+ variant: AccordionVariant;
30
+ nested: boolean;
7
31
  get multi(): boolean;
8
32
  set multi(value: BooleanInput);
9
33
  private _multi;
10
- private subscriptions;
11
- ngAfterContentInit(): void;
12
- ngOnDestroy(): void;
13
- private wireItems;
14
- private unwireItems;
34
+ expandedSet: Set<number>;
35
+ onExpandedChange(index: number, isExpanded: boolean): void;
15
36
  static ɵfac: i0.ɵɵFactoryDeclaration<AccordionComponent, never>;
16
- static ɵcmp: i0.ɵɵComponentDeclaration<AccordionComponent, "compsych-accordion", never, { "multi": { "alias": "multi"; "required": false; }; }, {}, ["items"], ["*"], true, never>;
37
+ static ɵcmp: i0.ɵɵComponentDeclaration<AccordionComponent, "compsych-accordion", never, { "items": { "alias": "items"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "nested": { "alias": "nested"; "required": false; }; "multi": { "alias": "multi"; "required": false; }; }, {}, never, never, true, never>;
17
38
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compsych-ui-components/angular",
3
- "version": "4.0.18",
3
+ "version": "4.0.20",
4
4
  "description": "Angular UI components for compsych",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -1,69 +0,0 @@
1
- import { Component, EventEmitter, Input, Output, } from '@angular/core';
2
- import { NgIf } from '@angular/common';
3
- import { coerceBooleanProperty } from '@angular/cdk/coercion';
4
- import { LUCIDE_ICONS } from '@compsych-ui-components/shared/assets/lucide-icons.generated';
5
- import * as i0 from "@angular/core";
6
- import * as i1 from "@angular/platform-browser";
7
- export class AccordionItemComponent {
8
- sanitizer;
9
- title = '';
10
- set icon(name) {
11
- const svg = LUCIDE_ICONS[name];
12
- this.iconSvg = svg ? this.sanitizer.bypassSecurityTrustHtml(svg) : null;
13
- }
14
- iconSvg = null;
15
- constructor(sanitizer) {
16
- this.sanitizer = sanitizer;
17
- }
18
- get expanded() { return this._expanded; }
19
- set expanded(value) { this._expanded = coerceBooleanProperty(value); }
20
- _expanded = false;
21
- expandedChange = new EventEmitter();
22
- toggle() {
23
- this._expanded = !this._expanded;
24
- this.expandedChange.emit(this._expanded);
25
- }
26
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionItemComponent, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
27
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.14", type: AccordionItemComponent, isStandalone: true, selector: "compsych-accordion-item", inputs: { title: "title", icon: "icon", expanded: "expanded" }, outputs: { expandedChange: "expandedChange" }, host: { classAttribute: "compsych-accordion-item" }, ngImport: i0, template: `
28
- <button
29
- class="trigger"
30
- type="button"
31
- [attr.aria-expanded]="expanded"
32
- (click)="toggle()"
33
- >
34
- <span *ngIf="iconSvg" class="trigger-leading-icon" [innerHTML]="iconSvg" aria-hidden="true"></span>
35
- <span class="trigger-label">{{ title }}</span>
36
- <span class="trigger-toggle material-symbols-rounded" aria-hidden="true">{{ expanded ? 'remove' : 'add' }}</span>
37
- </button>
38
- <div *ngIf="expanded" class="content" role="region">
39
- <ng-content />
40
- </div>
41
- `, isInline: true, styles: [":host{display:block;border-bottom:var(--sys-stroke-thin) solid var(--sys-outline-variant)}:host:first-child{border-top:var(--sys-stroke-thin) solid var(--sys-outline-variant)}.trigger{display:flex;align-items:center;gap:var(--padding-sys-padding-8);width:100%;padding:var(--padding-sys-padding-16) var(--padding-sys-padding-24);background:none;border:none;cursor:pointer;text-align:left;color:var(--surface-sys-on-surface);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking);position:relative;overflow:hidden;border-radius:0}.trigger:before{content:\"\";position:absolute;inset:0;background-color:currentColor;opacity:0;transition:opacity .15s ease;pointer-events:none}.trigger:hover:before{opacity:.08}.trigger:active:before{opacity:.1}.trigger-label{flex:1;min-width:0}.trigger-leading-icon{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;color:var(--surface-sys-on-surface);flex-shrink:0}.trigger-leading-icon svg{width:100%;height:100%}.trigger-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;font-size:1rem;line-height:1;color:var(--primary-fixed-sys-on-primary-fixed);background-color:var(--primary-fixed-sys-primary-fixed-dim);border-radius:var(--sys-radius-full);box-sizing:border-box}.content{padding:0 var(--padding-sys-padding-16) var(--padding-sys-padding-16);color:var(--surface-sys-on-surface-variant);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight);line-height:var(--sys-line-height)}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
42
- }
43
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionItemComponent, decorators: [{
44
- type: Component,
45
- args: [{ selector: 'compsych-accordion-item', standalone: true, imports: [NgIf], template: `
46
- <button
47
- class="trigger"
48
- type="button"
49
- [attr.aria-expanded]="expanded"
50
- (click)="toggle()"
51
- >
52
- <span *ngIf="iconSvg" class="trigger-leading-icon" [innerHTML]="iconSvg" aria-hidden="true"></span>
53
- <span class="trigger-label">{{ title }}</span>
54
- <span class="trigger-toggle material-symbols-rounded" aria-hidden="true">{{ expanded ? 'remove' : 'add' }}</span>
55
- </button>
56
- <div *ngIf="expanded" class="content" role="region">
57
- <ng-content />
58
- </div>
59
- `, host: { class: 'compsych-accordion-item' }, styles: [":host{display:block;border-bottom:var(--sys-stroke-thin) solid var(--sys-outline-variant)}:host:first-child{border-top:var(--sys-stroke-thin) solid var(--sys-outline-variant)}.trigger{display:flex;align-items:center;gap:var(--padding-sys-padding-8);width:100%;padding:var(--padding-sys-padding-16) var(--padding-sys-padding-24);background:none;border:none;cursor:pointer;text-align:left;color:var(--surface-sys-on-surface);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight);line-height:var(--sys-line-height);letter-spacing:var(--sys-tracking);position:relative;overflow:hidden;border-radius:0}.trigger:before{content:\"\";position:absolute;inset:0;background-color:currentColor;opacity:0;transition:opacity .15s ease;pointer-events:none}.trigger:hover:before{opacity:.08}.trigger:active:before{opacity:.1}.trigger-label{flex:1;min-width:0}.trigger-leading-icon{display:flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;color:var(--surface-sys-on-surface);flex-shrink:0}.trigger-leading-icon svg{width:100%;height:100%}.trigger-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;font-size:1rem;line-height:1;color:var(--primary-fixed-sys-on-primary-fixed);background-color:var(--primary-fixed-sys-primary-fixed-dim);border-radius:var(--sys-radius-full);box-sizing:border-box}.content{padding:0 var(--padding-sys-padding-16) var(--padding-sys-padding-16);color:var(--surface-sys-on-surface-variant);font-family:var(--sys-font-family);font-size:var(--sys-font-size);font-weight:var(--sys-font-weight);line-height:var(--sys-line-height)}\n"] }]
60
- }], ctorParameters: () => [{ type: i1.DomSanitizer }], propDecorators: { title: [{
61
- type: Input
62
- }], icon: [{
63
- type: Input
64
- }], expanded: [{
65
- type: Input
66
- }], expandedChange: [{
67
- type: Output
68
- }] } });
69
- //# sourceMappingURL=accordion-item.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"accordion-item.js","sourceRoot":"","sources":["../../../../../../packages/angular/src/lib/accordion/accordion-item.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,YAAY,EACZ,KAAK,EACL,MAAM,GACP,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,OAAO,EAAgB,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAC;;;AAwB5F,MAAM,OAAO,sBAAsB;IAWJ;IAVpB,KAAK,GAAG,EAAE,CAAC;IAEpB,IACI,IAAI,CAAC,IAAY;QACnB,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,CAAC;IAED,OAAO,GAAoB,IAAI,CAAC;IAEhC,YAA6B,SAAuB;QAAvB,cAAS,GAAT,SAAS,CAAc;IAAG,CAAC;IAExD,IACI,QAAQ,KAAc,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAClD,IAAI,QAAQ,CAAC,KAAmB,IAAI,IAAI,CAAC,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5E,SAAS,GAAG,KAAK,CAAC;IAEhB,cAAc,GAAG,IAAI,YAAY,EAAW,CAAC;IAEvD,MAAM;QACJ,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC;wGAvBU,sBAAsB;4FAAtB,sBAAsB,uPAlBvB;;;;;;;;;;;;;;GAcT,wsDAfS,IAAI;;4FAmBH,sBAAsB;kBAtBlC,SAAS;+BACE,yBAAyB,cACvB,IAAI,WACP,CAAC,IAAI,CAAC,YACL;;;;;;;;;;;;;;GAcT,QAEK,EAAE,KAAK,EAAE,yBAAyB,EAAE;;sBAGzC,KAAK;;sBAEL,KAAK;;sBAUL,KAAK;;sBAKL,MAAM","sourcesContent":["import {\n Component,\n EventEmitter,\n Input,\n Output,\n} from '@angular/core';\nimport { NgIf } from '@angular/common';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { LUCIDE_ICONS } from '@compsych-ui-components/shared/assets/lucide-icons.generated';\n\n@Component({\n selector: 'compsych-accordion-item',\n standalone: true,\n imports: [NgIf],\n template: `\n <button\n class=\"trigger\"\n type=\"button\"\n [attr.aria-expanded]=\"expanded\"\n (click)=\"toggle()\"\n >\n <span *ngIf=\"iconSvg\" class=\"trigger-leading-icon\" [innerHTML]=\"iconSvg\" aria-hidden=\"true\"></span>\n <span class=\"trigger-label\">{{ title }}</span>\n <span class=\"trigger-toggle material-symbols-rounded\" aria-hidden=\"true\">{{ expanded ? 'remove' : 'add' }}</span>\n </button>\n <div *ngIf=\"expanded\" class=\"content\" role=\"region\">\n <ng-content />\n </div>\n `,\n styleUrl: './accordion-item.css',\n host: { class: 'compsych-accordion-item' },\n})\nexport class AccordionItemComponent {\n @Input() title = '';\n\n @Input()\n set icon(name: string) {\n const svg = LUCIDE_ICONS[name];\n this.iconSvg = svg ? this.sanitizer.bypassSecurityTrustHtml(svg) : null;\n }\n\n iconSvg: SafeHtml | null = null;\n\n constructor(private readonly sanitizer: DomSanitizer) {}\n\n @Input()\n get expanded(): boolean { return this._expanded; }\n set expanded(value: BooleanInput) { this._expanded = coerceBooleanProperty(value); }\n private _expanded = false;\n\n @Output() expandedChange = new EventEmitter<boolean>();\n\n toggle(): void {\n this._expanded = !this._expanded;\n this.expandedChange.emit(this._expanded);\n }\n}\n"]}
@@ -1,18 +0,0 @@
1
- import { EventEmitter } from '@angular/core';
2
- import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
3
- import { BooleanInput } from '@angular/cdk/coercion';
4
- import * as i0 from "@angular/core";
5
- export declare class AccordionItemComponent {
6
- private readonly sanitizer;
7
- title: string;
8
- set icon(name: string);
9
- iconSvg: SafeHtml | null;
10
- constructor(sanitizer: DomSanitizer);
11
- get expanded(): boolean;
12
- set expanded(value: BooleanInput);
13
- private _expanded;
14
- expandedChange: EventEmitter<boolean>;
15
- toggle(): void;
16
- static ɵfac: i0.ɵɵFactoryDeclaration<AccordionItemComponent, never>;
17
- static ɵcmp: i0.ɵɵComponentDeclaration<AccordionItemComponent, "compsych-accordion-item", never, { "title": { "alias": "title"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "expanded": { "alias": "expanded"; "required": false; }; }, { "expandedChange": "expandedChange"; }, never, ["*"], true, never>;
18
- }