@compsych-ui-components/angular 5.1.8 → 6.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar.js","sourceRoot":"","sources":["../../../../../../packages/angular/src/lib/sidebar/sidebar.ts","../../../../../../packages/angular/src/lib/sidebar/sidebar.html"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n model,\n input,\n signal,\n} from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { LUCIDE_ICONS } from '@compsych-ui-components/shared/assets/lucide-icons.generated';\n\nexport interface SidebarItem {\n id: string;\n label: string;\n /** Lucide icon name (kebab-case). */\n icon: string;\n /** Nested items — renders an expandable group with a chevron. */\n children?: SidebarItem[];\n /** Render a divider above this item. */\n dividerBefore?: boolean;\n disabled?: boolean;\n}\n\n/** Default content from the Figma (node 260:4700). */\nconst DEFAULT_ITEMS: SidebarItem[] = [\n { id: 'home', label: 'Home', icon: 'house' },\n { id: 'connect', label: 'Connect Me', icon: 'message-circle', dividerBefore: true },\n { id: 'guide', label: 'Guide Me', icon: 'compass' },\n { id: 'assess', label: 'Assess Me', icon: 'binoculars' },\n {\n id: 'resources',\n label: 'Resource Library',\n icon: 'folder',\n dividerBefore: true,\n children: [\n { id: 'wellness', label: 'Wellness', icon: 'leaf' },\n { id: 'relationships', label: 'Relationships', icon: 'users' },\n { id: 'work', label: 'Work & Education', icon: 'briefcase' },\n { id: 'financial', label: 'Financial', icon: 'landmark' },\n { id: 'legal', label: 'Legal', icon: 'scale' },\n { id: 'lifestyle', label: 'Lifestyle', icon: 'smile' },\n { id: 'home-auto', label: 'Home & Auto', icon: 'car' },\n { id: 'abroad', label: 'Working Abroad', icon: 'plane' },\n ],\n },\n];\n\nconst DEFAULT_FOOTER: SidebarItem[] = [\n { id: 'location', label: 'Location & Language', icon: 'globe' },\n { id: 'logout', label: 'Logout', icon: 'log-out' },\n];\n\n/**\n * Sidebar — vertical app navigation from the ComPsych Design System.\n *\n * Figma: Core Components — base 260:4700, parts 213:1585.\n *\n * Icon + label items with default / hover / selected / focus / disabled states,\n * section dividers, expandable groups (chevron), and a pinned footer\n * (location & language, logout). Data-driven via `items` / `footerItems`,\n * defaulting to the design's content. All values are sys tokens.\n */\n@Component({\n selector: 'compsych-sidebar',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [],\n templateUrl: './sidebar.html',\n styleUrl: './sidebar.css',\n host: { role: 'navigation', 'aria-label': 'Sidebar' },\n})\nexport class SidebarComponent {\n readonly items = input<SidebarItem[]>(DEFAULT_ITEMS);\n readonly footerItems = input<SidebarItem[]>(DEFAULT_FOOTER);\n /** Currently selected item id — supports two-way binding via [(activeId)]. */\n readonly activeId = model<string>('home');\n\n private readonly expanded = signal<Set<string>>(new Set());\n\n constructor(private readonly sanitizer: DomSanitizer) {}\n\n isExpanded(id: string): boolean {\n return this.expanded().has(id);\n }\n\n isActive(id: string): boolean {\n return this.activeId() === id;\n }\n\n onItemClick(item: SidebarItem): void {\n if (item.disabled) return;\n if (item.children?.length) {\n this.expanded.update((s) => {\n const next = new Set(s);\n next.has(item.id) ? next.delete(item.id) : next.add(item.id);\n return next;\n });\n return;\n }\n this.activeId.set(item.id);\n }\n\n /**\n * Looks up a Lucide icon by name and injects explicit width/height attributes\n * so the SVG renders at the correct size when injected via [innerHTML].\n * Angular's CSS encapsulation does not add _ngcontent attributes to dynamically\n * injected content, so explicit SVG attributes are the reliable solution.\n */\n iconSvg(name: string, size = 20, strokeWidth = 1.5): SafeHtml {\n let svg = LUCIDE_ICONS[name] ?? '';\n svg = svg.replace('<svg ', `<svg width=\"${size}\" height=\"${size}\" `);\n if (strokeWidth !== 1.5) {\n svg = svg.replace('stroke-width=\"1.5\"', `stroke-width=\"${strokeWidth}\"`);\n }\n return this.sanitizer.bypassSecurityTrustHtml(svg);\n }\n}\n","<div class=\"cs-sb__scroll\">\n <ul class=\"cs-sb__list\">\n @for (item of items(); track item.id) {\n @if (item.dividerBefore) {\n <li class=\"cs-sb__divider\" aria-hidden=\"true\"></li>\n }\n <li class=\"cs-sb__item\">\n <button\n type=\"button\"\n class=\"cs-sb__row\"\n [class.cs-sb__row--active]=\"isActive(item.id)\"\n [disabled]=\"item.disabled || null\"\n [attr.aria-current]=\"isActive(item.id) ? 'page' : null\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item.id) : null\"\n (click)=\"onItemClick(item)\"\n >\n <span\n class=\"cs-sb__icon\"\n [innerHTML]=\"iconSvg(item.icon, 20, isActive(item.id) ? 2 : 1.5)\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"cs-sb__label\">{{ item.label }}</span>\n @if (item.children?.length) {\n <span\n class=\"cs-sb__chevron\"\n [class.cs-sb__chevron--open]=\"isExpanded(item.id)\"\n [innerHTML]=\"iconSvg('chevron-down', 18)\"\n aria-hidden=\"true\"\n ></span>\n }\n </button>\n\n @if (item.children?.length && isExpanded(item.id)) {\n <ul class=\"cs-sb__sublist\">\n @for (child of item.children; track child.id) {\n <li>\n <button\n type=\"button\"\n class=\"cs-sb__row cs-sb__row--sub\"\n [class.cs-sb__row--active]=\"isActive(child.id)\"\n [disabled]=\"child.disabled || null\"\n [attr.aria-current]=\"isActive(child.id) ? 'page' : null\"\n (click)=\"onItemClick(child)\"\n >\n <span\n class=\"cs-sb__icon\"\n [innerHTML]=\"iconSvg(child.icon, 20, isActive(child.id) ? 2 : 1.5)\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"cs-sb__label\">{{ child.label }}</span>\n </button>\n </li>\n }\n </ul>\n }\n </li>\n }\n </ul>\n</div>\n\n<div class=\"cs-sb__footer\">\n <ul class=\"cs-sb__list\">\n @for (item of footerItems(); track item.id) {\n <li class=\"cs-sb__item\">\n <button\n type=\"button\"\n class=\"cs-sb__row\"\n [class.cs-sb__row--active]=\"isActive(item.id)\"\n [disabled]=\"item.disabled || null\"\n (click)=\"onItemClick(item)\"\n >\n <span\n class=\"cs-sb__icon\"\n [innerHTML]=\"iconSvg(item.icon, 20, isActive(item.id) ? 2 : 1.5)\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"cs-sb__label\">{{ item.label }}</span>\n </button>\n </li>\n }\n </ul>\n</div>\n"]}
1
+ {"version":3,"file":"sidebar.js","sourceRoot":"","sources":["../../../../../../packages/angular/src/lib/sidebar/sidebar.ts","../../../../../../packages/angular/src/lib/sidebar/sidebar.html"],"names":[],"mappings":"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","sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n model,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\r\nimport { LUCIDE_ICONS } from '@compsych-ui-components/shared/assets/lucide-icons.generated';\r\n\r\nexport interface SidebarItem {\r\n /** Stable identifier used by `activeId` and emitted by `itemClick`. */\r\n id: string;\r\n /** Text label displayed next to the icon. */\r\n label: string;\r\n /** Lucide icon name (kebab-case), e.g. `'house'` or `'folder'`. */\r\n icon: string;\r\n /** Child items — renders this item as an expandable group with a chevron toggle. Child items cannot have their own children. */\r\n children?: SidebarItem[];\r\n /** When true, renders a horizontal divider above this item in the list. */\r\n dividerBefore?: boolean;\r\n /** When true, the item is non-interactive — it cannot be clicked and receives no hover or active styling. */\r\n disabled?: boolean;\r\n /**\r\n * When true, clicking the item emits `itemClick` but does not highlight it\r\n * as active or update `activeId`. Use for action items (e.g. logout)\r\n * that are not navigation destinations.\r\n */\r\n nonRoute?: boolean;\r\n}\r\n\r\n/** Default content from the Figma (node 260:4700). */\r\nconst DEFAULT_ITEMS: SidebarItem[] = [\r\n { id: 'home', label: 'Home', icon: 'house' },\r\n { id: 'connect', label: 'Connect Me', icon: 'message-circle', dividerBefore: true },\r\n { id: 'guide', label: 'Guide Me', icon: 'compass' },\r\n { id: 'assess', label: 'Assess Me', icon: 'binoculars' },\r\n {\r\n id: 'resources',\r\n label: 'Resource Library',\r\n icon: 'folder',\r\n dividerBefore: true,\r\n children: [\r\n { id: 'wellness', label: 'Wellness', icon: 'leaf' },\r\n { id: 'relationships', label: 'Relationships', icon: 'users' },\r\n { id: 'work', label: 'Work & Education', icon: 'briefcase' },\r\n { id: 'financial', label: 'Financial', icon: 'landmark' },\r\n { id: 'legal', label: 'Legal', icon: 'scale' },\r\n { id: 'lifestyle', label: 'Lifestyle', icon: 'smile' },\r\n { id: 'home-auto', label: 'Home & Auto', icon: 'car' },\r\n { id: 'abroad', label: 'Working Abroad', icon: 'plane' },\r\n ],\r\n },\r\n];\r\n\r\nconst DEFAULT_FOOTER: SidebarItem[] = [\r\n { id: 'location', label: 'Location & Language', icon: 'globe' },\r\n { id: 'logout', label: 'Logout', icon: 'log-out' },\r\n];\r\n\r\n/**\r\n * Sidebar — vertical app navigation from the ComPsych Design System.\r\n *\r\n * Figma: Core Components — base 260:4700, parts 213:1585.\r\n *\r\n * Icon + label items with default / hover / selected / focus / disabled states,\r\n * section dividers, expandable groups (chevron), and a pinned footer\r\n * (location & language, logout). Data-driven via `items` / `footerItems`,\r\n * defaulting to the design's content. All values are sys tokens.\r\n */\r\n@Component({\r\n selector: 'compsych-sidebar',\r\n standalone: true,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n imports: [],\r\n templateUrl: './sidebar.html',\r\n styleUrl: './sidebar.css',\r\n host: { role: 'navigation', 'aria-label': 'Sidebar' },\r\n})\r\nexport class SidebarComponent {\r\n /** Navigation items rendered in the scrollable main area. Defaults to the standard ComPsych nav set. */\r\n readonly items = input<SidebarItem[]>(DEFAULT_ITEMS);\r\n /** Items pinned to the bottom of the sidebar, outside the scroll region. Intended for utility actions such as language selection and logout. */\r\n readonly footerItems = input<SidebarItem[]>(DEFAULT_FOOTER);\r\n /** Currently active item id — supports two-way binding via `[(activeId)]`. Updated on click for route items; unchanged for `nonRoute` items. */\r\n readonly activeId = model<string>('home');\r\n /**\r\n * Emitted with the item's `id` whenever a non-disabled, non-group item is clicked.\r\n * Fires for both route items and `nonRoute` items.\r\n * Group items (those with `children`) do not emit — they only toggle their expanded state.\r\n */\r\n readonly itemClick = output<string>();\r\n\r\n private readonly expanded = signal<Set<string>>(new Set());\r\n\r\n constructor(private readonly sanitizer: DomSanitizer) {}\r\n\r\n isExpanded(id: string): boolean {\r\n return this.expanded().has(id);\r\n }\r\n\r\n isActive(id: string): boolean {\r\n return this.activeId() === id;\r\n }\r\n\r\n onItemClick(item: SidebarItem): void {\r\n if (item.disabled) return;\r\n if (item.children?.length) {\r\n this.expanded.update((s) => {\r\n const next = new Set(s);\r\n next.has(item.id) ? next.delete(item.id) : next.add(item.id);\r\n return next;\r\n });\r\n return;\r\n }\r\n if (item.nonRoute) {\r\n this.itemClick.emit(item.id);\r\n return;\r\n }\r\n this.activeId.set(item.id);\r\n }\r\n\r\n /**\r\n * Looks up a Lucide icon by name and injects explicit width/height attributes\r\n * so the SVG renders at the correct size when injected via [innerHTML].\r\n * Angular's CSS encapsulation does not add _ngcontent attributes to dynamically\r\n * injected content, so explicit SVG attributes are the reliable solution.\r\n */\r\n iconSvg(name: string, size = 20, strokeWidth = 1.5): SafeHtml {\r\n let svg = LUCIDE_ICONS[name] ?? '';\r\n svg = svg.replace('<svg ', `<svg width=\"${size}\" height=\"${size}\" `);\r\n if (strokeWidth !== 1.5) {\r\n svg = svg.replace('stroke-width=\"1.5\"', `stroke-width=\"${strokeWidth}\"`);\r\n }\r\n return this.sanitizer.bypassSecurityTrustHtml(svg);\r\n }\r\n}\r\n","<div class=\"cs-sb__scroll\">\r\n <ul class=\"cs-sb__list\">\r\n @for (item of items(); track item.id) {\r\n @if (item.dividerBefore) {\r\n <li class=\"cs-sb__divider\" aria-hidden=\"true\"></li>\r\n }\r\n <li class=\"cs-sb__item\">\r\n <button\r\n type=\"button\"\r\n class=\"cs-sb__row\"\r\n [class.cs-sb__row--active]=\"!item.nonRoute && isActive(item.id)\"\r\n [disabled]=\"item.disabled || null\"\r\n [attr.aria-current]=\"!item.nonRoute && isActive(item.id) ? 'page' : null\"\r\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item.id) : null\"\r\n (click)=\"onItemClick(item)\"\r\n >\r\n <span\r\n class=\"cs-sb__icon\"\r\n [innerHTML]=\"iconSvg(item.icon, 20, !item.nonRoute && isActive(item.id) ? 2 : 1.5)\"\r\n aria-hidden=\"true\"\r\n ></span>\r\n <span class=\"cs-sb__label\">{{ item.label }}</span>\r\n @if (item.children?.length) {\r\n <span\r\n class=\"cs-sb__chevron\"\r\n [class.cs-sb__chevron--open]=\"isExpanded(item.id)\"\r\n [innerHTML]=\"iconSvg('chevron-down', 18)\"\r\n aria-hidden=\"true\"\r\n ></span>\r\n }\r\n </button>\r\n\r\n @if (item.children?.length && isExpanded(item.id)) {\r\n <ul class=\"cs-sb__sublist\">\r\n @for (child of item.children; track child.id) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"cs-sb__row cs-sb__row--sub\"\r\n [class.cs-sb__row--active]=\"isActive(child.id)\"\r\n [disabled]=\"child.disabled || null\"\r\n [attr.aria-current]=\"isActive(child.id) ? 'page' : null\"\r\n (click)=\"onItemClick(child)\"\r\n >\r\n <span\r\n class=\"cs-sb__icon\"\r\n [innerHTML]=\"iconSvg(child.icon, 20, isActive(child.id) ? 2 : 1.5)\"\r\n aria-hidden=\"true\"\r\n ></span>\r\n <span class=\"cs-sb__label\">{{ child.label }}</span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n</div>\r\n\r\n<div class=\"cs-sb__footer\">\r\n <ul class=\"cs-sb__list\">\r\n @for (item of footerItems(); track item.id) {\r\n <li class=\"cs-sb__item\">\r\n <button\r\n type=\"button\"\r\n class=\"cs-sb__row\"\r\n [class.cs-sb__row--active]=\"!item.nonRoute && isActive(item.id)\"\r\n [disabled]=\"item.disabled || null\"\r\n (click)=\"onItemClick(item)\"\r\n >\r\n <span\r\n class=\"cs-sb__icon\"\r\n [innerHTML]=\"iconSvg(item.icon, 20, !item.nonRoute && isActive(item.id) ? 2 : 1.5)\"\r\n aria-hidden=\"true\"\r\n ></span>\r\n <span class=\"cs-sb__label\">{{ item.label }}</span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n</div>\r\n"]}
@@ -1,14 +1,35 @@
1
+ /**
2
+ * Visual style variant applied to the accordion and all its items.
3
+ * - `'default'` — standard card style with borders and a background surface.
4
+ * - `'level-2'` — compact nested style used inside another accordion panel.
5
+ * - `'text-only'` — no card chrome; plain text trigger rows.
6
+ */
1
7
  export type AccordionVariant = 'default' | 'level-2' | 'text-only';
8
+ /** An action button rendered at the bottom of an accordion panel. */
2
9
  export interface AccordionButton {
10
+ /** Text displayed on the button. */
3
11
  label: string;
12
+ /** Called when the button is clicked. */
4
13
  action: () => void;
5
14
  }
15
+ /**
16
+ * A simplified accordion item used inside `AccordionItem.nestedContent`.
17
+ * Identical to `AccordionItem` but without `buttons` and `nestedContent` —
18
+ * nesting beyond one level is not supported.
19
+ */
6
20
  export type NestedAccordionItem = Omit<AccordionItem, 'buttons' | 'nestedContent'>;
21
+ /** Data model for a single expandable row in a `compsych-accordion`. */
7
22
  export interface AccordionItem {
23
+ /** Text shown in the trigger button header. */
8
24
  title: string;
25
+ /** HTML string rendered in the panel body when expanded. Sanitized before display. Omit when using `nestedContent`. */
9
26
  content?: string;
27
+ /** Lucide icon name (kebab-case) shown to the left of the title, e.g. `'globe'` or `'folder'`. */
10
28
  icon?: string;
29
+ /** Whether this panel starts expanded on initial render. Defaults to false. */
11
30
  expanded?: boolean;
31
+ /** Action buttons rendered at the bottom of the panel, below `content`. */
12
32
  buttons?: AccordionButton[];
33
+ /** Items rendered as a nested level-2 accordion inside this panel. Cannot contain `buttons` or further nesting. */
13
34
  nestedContent?: NestedAccordionItem[];
14
35
  }
@@ -9,19 +9,28 @@ export declare class AccordionItemComponent {
9
9
  private readonly el;
10
10
  readonly triggerId: string;
11
11
  readonly panelId: string;
12
+ /** Text shown in the trigger button header. */
12
13
  title: string;
14
+ /** HTML string rendered in the panel body when expanded. Sanitized before display. */
13
15
  content: string;
16
+ /** Action buttons rendered at the bottom of the panel. */
14
17
  buttons: AccordionButton[];
18
+ /** Items rendered as a nested level-2 accordion inside this panel. */
15
19
  nestedContent: NestedAccordionItem[];
20
+ /** Visual style — inherited from the parent AccordionComponent. */
16
21
  variant: AccordionVariant;
22
+ /** True when this item is rendered inside a parent accordion panel. Adds nested styling. Set automatically by AccordionComponent — do not set directly. */
17
23
  nested: boolean;
24
+ /** Lucide icon name (kebab-case) shown to the left of the title. Pass an empty string to show no icon. */
18
25
  set icon(name: string);
19
26
  iconSvg: SafeHtml | null;
20
27
  get sanitizedContent(): SafeHtml;
21
28
  constructor(sanitizer: DomSanitizer, el: ElementRef<HTMLElement>);
29
+ /** Whether this panel is currently open. Supports boolean coercion (e.g. `[expanded]="true"`). */
22
30
  get expanded(): boolean;
23
31
  set expanded(value: BooleanInput);
24
32
  private _expanded;
33
+ /** Emitted when the panel is toggled. `true` = opening, `false` = closing. */
25
34
  expandedChange: EventEmitter<boolean>;
26
35
  toggle(): void;
27
36
  onKeydown(event: KeyboardEvent): void;
@@ -29,9 +38,13 @@ export declare class AccordionItemComponent {
29
38
  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>;
30
39
  }
31
40
  export declare class AccordionComponent {
41
+ /** Items to render as expandable rows. */
32
42
  items: AccordionItem[];
43
+ /** Visual style applied to all items. `'default'` is the standard card style; `'level-2'` is compact nested style; `'text-only'` removes card chrome. */
33
44
  variant: AccordionVariant;
45
+ /** Set automatically when this accordion is rendered inside another accordion panel. Do not set directly. */
34
46
  nested: boolean;
47
+ /** When true, multiple panels can be open simultaneously. Defaults to false — opening one panel closes any others. Supports boolean coercion. */
35
48
  get multi(): boolean;
36
49
  set multi(value: BooleanInput);
37
50
  private _multi;
@@ -2,17 +2,24 @@ import { AfterViewInit, OnDestroy } from '@angular/core';
2
2
  import { FocusOrigin } from '@angular/cdk/a11y';
3
3
  import { BooleanInput } from '@angular/cdk/coercion';
4
4
  import * as i0 from "@angular/core";
5
+ /** Visual style of a `compsych-button`. Controls color, border, and elevation. */
5
6
  export type ButtonVariant = 'filled' | 'tonal' | 'outlined' | 'elevated' | 'text' | 'danger' | 'danger-outlined';
6
7
  export declare class ButtonComponent implements AfterViewInit, OnDestroy {
7
8
  private readonly focusMonitor;
8
9
  private readonly elementRef;
10
+ /** Text label rendered on the button. */
9
11
  label: string;
12
+ /** Visual style of the button. Defaults to `'filled'`. */
10
13
  variant: ButtonVariant;
14
+ /** Button dimensions — controls height, padding, and font size. Defaults to `'small'`. */
11
15
  size: 'small' | 'medium' | 'large' | 'xlarge';
16
+ /** Material Symbols icon name shown to the left of the label (e.g. `'search'`, `'add'`). Omit to show label only. */
12
17
  icon?: string;
18
+ /** When true, hides the label and renders a square icon-only button. Requires `icon` to be set. Supports boolean coercion. */
13
19
  get iconOnly(): boolean;
14
20
  set iconOnly(value: BooleanInput);
15
21
  private _iconOnly;
22
+ /** When true, the button is non-interactive — `disabled` and `aria-disabled` attributes are set and `tabIndex` is set to `-1`. Supports boolean coercion. */
16
23
  get disabled(): boolean;
17
24
  set disabled(value: BooleanInput);
18
25
  private _disabled;
@@ -5,31 +5,37 @@ import * as i0 from "@angular/core";
5
5
  export type HeaderNavLevel = 'main' | 'sub-page' | 'not-logged';
6
6
  /**
7
7
  * A navigation item used for both breadcrumbs and action buttons.
8
- * Use `id` to identify which item was clicked in the parent's `action` handler.
9
8
  * - Breadcrumb: provide `id` and `label`.
10
- * - Action button: provide `id`, `label`, and `variant`.
9
+ * - Action button: provide `id`, `label`, and optionally `variant`.
11
10
  */
12
11
  export interface NavAction {
12
+ /** Stable identifier emitted by the `action` output when this item is clicked. */
13
13
  id: string;
14
+ /** Text displayed in the breadcrumb trail or on the action button. */
14
15
  label: string;
16
+ /** Button style for action buttons. Defaults to `'filled'` when omitted. Not used for breadcrumbs. */
15
17
  variant?: ButtonVariant;
16
18
  }
17
19
  /**
18
20
  * Header Navigation — top app bar from the ComPsych Design System.
19
21
  *
20
- * Three levels × sidebar-open state:
21
- * - `main` — menu toggle, brand logo + wordmark, logged-in action cluster.
22
- * - `sub-page` — menu toggle, logo mark + breadcrumb trail, logged-in action cluster.
23
- * - `not-logged` — menu toggle, brand, public action cluster (language, help, CTA).
22
+ * Three layout levels controlled by `level`:
23
+ * - `'main'` — menu toggle, brand logo + wordmark, logged-in action cluster.
24
+ * - `'sub-page'` — menu toggle, logo mark + breadcrumb trail, logged-in action cluster.
25
+ * - `'not-logged'` — menu toggle, brand, public action cluster (language, help, CTA buttons).
24
26
  *
25
- * Pass `breadcrumbs` as an ordered list of `NavAction` items. The last item is
26
- * rendered as the current-page indicator (non-interactive); all others are
27
- * buttons that emit `action` with `{ type: 'breadcrumb', item }` on click.
28
- * Use `item.id` in the handler to identify which crumb was clicked.
27
+ * All interactive elements emit a string id via the `action` output.
28
+ * For breadcrumbs and action buttons the emitted value is the `NavAction.id`.
29
+ * For built-in icon buttons a fixed string is emitted (see `action` docs).
29
30
  */
30
31
  export declare class HeaderNavComponent {
31
32
  private readonly sanitizer;
32
- /** Which header level to render. */
33
+ /**
34
+ * Layout and feature set of the header.
35
+ * - `'main'` — logo + brand label, logged-in action cluster (search, notifications, documents, language, avatar, logout).
36
+ * - `'sub-page'` — symbol mark + breadcrumb trail, same logged-in action cluster.
37
+ * - `'not-logged'` — logo + brand label, public action cluster (language, help, action buttons).
38
+ */
33
39
  level: HeaderNavLevel;
34
40
  /** Whether the paired sidebar is open — toggles the menu icon (☰ ↔ ✕). */
35
41
  sidebarOpen: boolean;
@@ -39,15 +45,19 @@ export declare class HeaderNavComponent {
39
45
  brandLabelAria: string;
40
46
  /** Brand wordmark text rendered next to the logo on `main` and `not-logged` levels. */
41
47
  brandLabel: string;
48
+ /** Optional hex color (e.g. `'#ff0000'`) applied to the brand label text. Overrides the default inherited color. */
49
+ brandLabelColor?: string;
42
50
  /**
43
- * URL of a client logo image. When provided, replaces the ComPsych SVG with
44
- * `<img [src]="clientLogoUrl" alt="">` at the same position.
51
+ * URL of a client logo image. When provided, replaces the ComPsych SVG logo
52
+ * with an `<img>` at the same position. The image receives `brandLabelAria`
53
+ * as its accessible label.
45
54
  */
46
55
  clientLogoUrl?: string;
47
56
  /**
48
- * Ordered breadcrumb trail for `sub-page` level.
49
- * Each item requires an `id` and `label`. The last item is rendered as the
50
- * current page (non-interactive); all others emit `{ type: 'breadcrumb', item }`.
57
+ * Ordered breadcrumb trail rendered at `'sub-page'` level.
58
+ * Each item requires `id` and `label`. The last item is the current page
59
+ * (non-interactive). All preceding items are buttons that emit their `id`
60
+ * via the `action` output when clicked.
51
61
  */
52
62
  breadcrumbs: NavAction[];
53
63
  /** Notification badge count. Badge is hidden when 0. */
@@ -56,6 +66,8 @@ export declare class HeaderNavComponent {
56
66
  avatarInitials: string;
57
67
  /** Show the search icon button (logged-in levels). */
58
68
  showSearch: boolean;
69
+ /** Show the calendar-check icon button (logged-in levels). */
70
+ showCalendarChecked: boolean;
59
71
  /** Show the notifications icon button (logged-in levels). */
60
72
  showNotifications: boolean;
61
73
  /** Show the documents icon button (logged-in levels). */
@@ -70,14 +82,29 @@ export declare class HeaderNavComponent {
70
82
  showLogout: boolean;
71
83
  /**
72
84
  * Additional configurable buttons rendered in the actions area.
73
- * Each entry is `{ id, label, variant? }` where `variant` is a `ButtonVariant`
74
- * (defaults to `'filled'`) and `id` is a required stable identifier.
75
- * Clicking any of these emits `action` with `{ type: 'action-button', item }`.
85
+ * Each entry requires `id` and `label`; `variant` defaults to `'filled'`.
86
+ * Clicking any button emits its `id` via the `action` output.
76
87
  */
77
88
  actionButtons: NavAction[];
78
- /** Emitted for every interactive element. Emits a string id: the `NavAction` id for breadcrumb/action-button, or the action name for icon buttons. */
89
+ /**
90
+ * Emitted as a string whenever any interactive element is activated.
91
+ * Fixed values for built-in controls:
92
+ * - `'menu-toggle'` — hamburger / close button
93
+ * - `'logo'` — brand / logo button
94
+ * - `'search'` — search icon button
95
+ * - `'calendar-checked'` — calendar-check icon button
96
+ * - `'notifications'` — notifications icon button
97
+ * - `'documents'` — documents icon button
98
+ * - `'language'` — language icon button
99
+ * - `'help'` — help icon button
100
+ * - `'avatar'` — avatar button
101
+ * - `'logout'` — logout icon button
102
+ *
103
+ * For `breadcrumbs` and `actionButtons` items, the item's `NavAction.id` is emitted.
104
+ */
79
105
  readonly action: EventEmitter<string>;
80
106
  readonly searchIconSvg: SafeHtml;
107
+ readonly calendarCheckedIconSvg: SafeHtml;
81
108
  readonly bellIconSvg: SafeHtml;
82
109
  readonly fileTextIconSvg: SafeHtml;
83
110
  readonly globeIconSvg: SafeHtml;
@@ -99,5 +126,5 @@ export declare class HeaderNavComponent {
99
126
  */
100
127
  private trustedIcon;
101
128
  static ɵfac: i0.ɵɵFactoryDeclaration<HeaderNavComponent, never>;
102
- static ɵcmp: i0.ɵɵComponentDeclaration<HeaderNavComponent, "compsych-header-nav", never, { "level": { "alias": "level"; "required": false; }; "sidebarOpen": { "alias": "sidebarOpen"; "required": false; }; "showMenuToggle": { "alias": "showMenuToggle"; "required": false; }; "brandLabelAria": { "alias": "brandLabelAria"; "required": false; }; "brandLabel": { "alias": "brandLabel"; "required": false; }; "clientLogoUrl": { "alias": "clientLogoUrl"; "required": false; }; "breadcrumbs": { "alias": "breadcrumbs"; "required": false; }; "notificationCount": { "alias": "notificationCount"; "required": false; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; }; "showSearch": { "alias": "showSearch"; "required": false; }; "showNotifications": { "alias": "showNotifications"; "required": false; }; "showDocuments": { "alias": "showDocuments"; "required": false; }; "showAvatar": { "alias": "showAvatar"; "required": false; }; "showLanguage": { "alias": "showLanguage"; "required": false; }; "showHelp": { "alias": "showHelp"; "required": false; }; "showLogout": { "alias": "showLogout"; "required": false; }; "actionButtons": { "alias": "actionButtons"; "required": false; }; }, { "action": "action"; }, never, never, true, never>;
129
+ static ɵcmp: i0.ɵɵComponentDeclaration<HeaderNavComponent, "compsych-header-nav", never, { "level": { "alias": "level"; "required": false; }; "sidebarOpen": { "alias": "sidebarOpen"; "required": false; }; "showMenuToggle": { "alias": "showMenuToggle"; "required": false; }; "brandLabelAria": { "alias": "brandLabelAria"; "required": false; }; "brandLabel": { "alias": "brandLabel"; "required": false; }; "brandLabelColor": { "alias": "brandLabelColor"; "required": false; }; "clientLogoUrl": { "alias": "clientLogoUrl"; "required": false; }; "breadcrumbs": { "alias": "breadcrumbs"; "required": false; }; "notificationCount": { "alias": "notificationCount"; "required": false; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; }; "showSearch": { "alias": "showSearch"; "required": false; }; "showCalendarChecked": { "alias": "showCalendarChecked"; "required": false; }; "showNotifications": { "alias": "showNotifications"; "required": false; }; "showDocuments": { "alias": "showDocuments"; "required": false; }; "showAvatar": { "alias": "showAvatar"; "required": false; }; "showLanguage": { "alias": "showLanguage"; "required": false; }; "showHelp": { "alias": "showHelp"; "required": false; }; "showLogout": { "alias": "showLogout"; "required": false; }; "actionButtons": { "alias": "actionButtons"; "required": false; }; }, { "action": "action"; }, never, never, true, never>;
103
130
  }
@@ -1,15 +1,24 @@
1
1
  import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
2
2
  import * as i0 from "@angular/core";
3
3
  export interface SidebarItem {
4
+ /** Stable identifier used by `activeId` and emitted by `itemClick`. */
4
5
  id: string;
6
+ /** Text label displayed next to the icon. */
5
7
  label: string;
6
- /** Lucide icon name (kebab-case). */
8
+ /** Lucide icon name (kebab-case), e.g. `'house'` or `'folder'`. */
7
9
  icon: string;
8
- /** Nested items — renders an expandable group with a chevron. */
10
+ /** Child items — renders this item as an expandable group with a chevron toggle. Child items cannot have their own children. */
9
11
  children?: SidebarItem[];
10
- /** Render a divider above this item. */
12
+ /** When true, renders a horizontal divider above this item in the list. */
11
13
  dividerBefore?: boolean;
14
+ /** When true, the item is non-interactive — it cannot be clicked and receives no hover or active styling. */
12
15
  disabled?: boolean;
16
+ /**
17
+ * When true, clicking the item emits `itemClick` but does not highlight it
18
+ * as active or update `activeId`. Use for action items (e.g. logout)
19
+ * that are not navigation destinations.
20
+ */
21
+ nonRoute?: boolean;
13
22
  }
14
23
  /**
15
24
  * Sidebar — vertical app navigation from the ComPsych Design System.
@@ -23,10 +32,18 @@ export interface SidebarItem {
23
32
  */
24
33
  export declare class SidebarComponent {
25
34
  private readonly sanitizer;
35
+ /** Navigation items rendered in the scrollable main area. Defaults to the standard ComPsych nav set. */
26
36
  readonly items: import("@angular/core").InputSignal<SidebarItem[]>;
37
+ /** Items pinned to the bottom of the sidebar, outside the scroll region. Intended for utility actions such as language selection and logout. */
27
38
  readonly footerItems: import("@angular/core").InputSignal<SidebarItem[]>;
28
- /** Currently selected item id — supports two-way binding via [(activeId)]. */
39
+ /** Currently active item id — supports two-way binding via `[(activeId)]`. Updated on click for route items; unchanged for `nonRoute` items. */
29
40
  readonly activeId: import("@angular/core").ModelSignal<string>;
41
+ /**
42
+ * Emitted with the item's `id` whenever a non-disabled, non-group item is clicked.
43
+ * Fires for both route items and `nonRoute` items.
44
+ * Group items (those with `children`) do not emit — they only toggle their expanded state.
45
+ */
46
+ readonly itemClick: import("@angular/core").OutputEmitterRef<string>;
30
47
  private readonly expanded;
31
48
  constructor(sanitizer: DomSanitizer);
32
49
  isExpanded(id: string): boolean;
@@ -40,5 +57,5 @@ export declare class SidebarComponent {
40
57
  */
41
58
  iconSvg(name: string, size?: number, strokeWidth?: number): SafeHtml;
42
59
  static ɵfac: i0.ɵɵFactoryDeclaration<SidebarComponent, never>;
43
- static ɵcmp: i0.ɵɵComponentDeclaration<SidebarComponent, "compsych-sidebar", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "footerItems": { "alias": "footerItems"; "required": false; "isSignal": true; }; "activeId": { "alias": "activeId"; "required": false; "isSignal": true; }; }, { "activeId": "activeIdChange"; }, never, never, true, never>;
60
+ static ɵcmp: i0.ɵɵComponentDeclaration<SidebarComponent, "compsych-sidebar", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "footerItems": { "alias": "footerItems"; "required": false; "isSignal": true; }; "activeId": { "alias": "activeId"; "required": false; "isSignal": true; }; }, { "activeId": "activeIdChange"; "itemClick": "itemClick"; }, never, never, true, never>;
44
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compsych-ui-components/angular",
3
- "version": "5.1.8",
3
+ "version": "6.0.8",
4
4
  "description": "Angular UI components for compsych",
5
5
  "publishConfig": {
6
6
  "access": "public",