ps-helix 5.0.0 → 5.1.2

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A comprehensive Angular component library built with Angular 21+ featuring modern design patterns, accessibility-first development, and optimal developer experience.
4
4
 
5
- [![npm version](https://img.shields.io/badge/npm-5.0.0-blue.svg)](https://www.npmjs.com/package/ps-helix)
5
+ [![npm version](https://img.shields.io/badge/npm-5.1.2-blue.svg)](https://www.npmjs.com/package/ps-helix)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
  [![Angular](https://img.shields.io/badge/Angular-21.0.3-red.svg)](https://angular.dev/)
8
8
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.9.0-blue.svg)](https://www.typescriptlang.org/)
@@ -106,7 +106,7 @@ After installation, verify that ps-helix is in your `package.json`:
106
106
  ```json
107
107
  {
108
108
  "dependencies": {
109
- "ps-helix": "^5.0.0"
109
+ "ps-helix": "^5.1.2"
110
110
  }
111
111
  }
112
112
  ```
@@ -546,7 +546,7 @@ Helix provides **28 production-ready components** organized by category:
546
546
 
547
547
  ### Navigation Components (4)
548
548
 
549
- - **PshMenuComponent** - Dropdown menu with nested items
549
+ - **PshMenuComponent** - Dropdown menu with nested items, vertical/horizontal modes and collapsible mode; when collapsed, automatic tooltips appear on icons for both root items and sub-items (right position, 300ms delay) with `aria-describedby` linkage
550
550
  - **PshPaginationComponent** - Pagination controls with page numbers
551
551
  - **PshStepperComponent** + **PshStepComponent** - Step-by-step wizard navigation with validation
552
552
  - **PshDropdownComponent** - Dropdown trigger and content container
@@ -1182,7 +1182,7 @@ Copyright (c) 2025 PACK Solutions
1182
1182
 
1183
1183
  ---
1184
1184
 
1185
- **Version**: 5.0.0
1185
+ **Version**: 5.1.2
1186
1186
  **Built with**: Angular 21.0.3, TypeScript 5.9.0, Phosphor Icons 2.0.3
1187
1187
  **Author**: Fabrice PEREZ | Product Designer at PACK Solutions
1188
1188
  **Last Updated**: January 2026
@@ -831,6 +831,18 @@ class PshInfoCardComponent {
831
831
  this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
832
832
  /** Emitted when card is clicked */
833
833
  this.clicked = output();
834
+ /** Whether to show copy buttons on rows (opt-in) */
835
+ this.copyable = input(false, ...(ngDevMode ? [{ debugName: "copyable" }] : /* istanbul ignore next */ []));
836
+ /** Label prefix for the copy button aria-label */
837
+ this.copyButtonLabel = input('Copier', ...(ngDevMode ? [{ debugName: "copyButtonLabel" }] : /* istanbul ignore next */ []));
838
+ /** Text shown as feedback after successful copy */
839
+ this.copyFeedbackText = input('Copié', ...(ngDevMode ? [{ debugName: "copyFeedbackText" }] : /* istanbul ignore next */ []));
840
+ /** Emitted when a row value is successfully copied */
841
+ this.copied = output();
842
+ /** Emitted when a copy attempt fails */
843
+ this.copyFailed = output();
844
+ /** Tracks the row index currently showing success feedback */
845
+ this.copiedRowIndex = signal(null, ...(ngDevMode ? [{ debugName: "copiedRowIndex" }] : /* istanbul ignore next */ []));
834
846
  /** Whether to auto-enable full width buttons on mobile (default: true) */
835
847
  this.autoFullWidthOnMobile = input(true, ...(ngDevMode ? [{ debugName: "autoFullWidthOnMobile" }] : /* istanbul ignore next */ []));
836
848
  /** Signal to track if viewport is mobile */
@@ -909,6 +921,9 @@ class PshInfoCardComponent {
909
921
  if (this.resizeObserver) {
910
922
  this.resizeObserver.disconnect();
911
923
  }
924
+ if (this.feedbackTimeout) {
925
+ clearTimeout(this.feedbackTimeout);
926
+ }
912
927
  }
913
928
  checkMobileViewport() {
914
929
  if (typeof window !== 'undefined') {
@@ -934,15 +949,47 @@ class PshInfoCardComponent {
934
949
  }
935
950
  }
936
951
  }
952
+ isRowCopyable(item) {
953
+ return item.copyable ?? this.copyable();
954
+ }
955
+ hasNonEmptyValue(item) {
956
+ const val = item.value;
957
+ if (val == null)
958
+ return false;
959
+ return val.toString().trim().length > 0;
960
+ }
961
+ copyRowValue(item, index) {
962
+ if (!isPlatformBrowser(this.platformId)) {
963
+ this.copyFailed.emit(item);
964
+ return;
965
+ }
966
+ if (!window.isSecureContext || !navigator.clipboard) {
967
+ this.copyFailed.emit(item);
968
+ return;
969
+ }
970
+ const text = item.copyValue ?? item.value?.toString() ?? '';
971
+ navigator.clipboard.writeText(text).then(() => {
972
+ if (this.feedbackTimeout) {
973
+ clearTimeout(this.feedbackTimeout);
974
+ }
975
+ this.copiedRowIndex.set(index);
976
+ this.copied.emit(item);
977
+ this.feedbackTimeout = setTimeout(() => {
978
+ this.copiedRowIndex.set(null);
979
+ }, 1800);
980
+ }, () => {
981
+ this.copyFailed.emit(item);
982
+ });
983
+ }
937
984
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PshInfoCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
938
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: PshInfoCardComponent, isStandalone: true, selector: "psh-info-card", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, cssClass: { classPropertyName: "cssClass", publicName: "cssClass", isSignal: true, isRequired: false, transformFunction: null }, customStyle: { classPropertyName: "customStyle", publicName: "customStyle", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, autoFullWidthOnMobile: { classPropertyName: "autoFullWidthOnMobile", publicName: "autoFullWidthOnMobile", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, host: { styleAttribute: "display: block; height: 100%;" }, ngImport: i0, template: "<div\n [class]=\"computedClasses()\"\n [ngStyle]=\"computedStyles()\"\n (click)=\"handleClick($event)\"\n (keydown)=\"handleKeydown($event)\"\n role=\"region\"\n [attr.tabindex]=\"interactive() && !disabled() ? 0 : null\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-disabled]=\"disabled() ? 'true' : null\"\n [attr.aria-busy]=\"loading() ? 'true' : null\"\n>\n @if (title() || hasHeaderActions()) {\n <div class=\"info-card-header\">\n @if (title()) {\n <h3 class=\"info-card-title\">\n @if (icon()) {\n <i\n class=\"ph {{ titleIcon() }}\"\n aria-hidden=\"true\"\n [attr.data-icon]=\"icon()\"\n ></i>\n }\n {{ title() }}\n </h3>\n }\n <div class=\"info-card-header-actions\">\n <ng-content select=\"[card-header-actions]\"></ng-content>\n </div>\n </div>\n }\n\n <div class=\"info-card-body\">\n @if (loading()) {\n <div class=\"info-card-loading\">\n <div class=\"skeleton-line\"></div>\n <div class=\"skeleton-line\"></div>\n <div class=\"skeleton-line short\"></div>\n </div>\n } @else {\n <div\n class=\"info-card-content\"\n role=\"list\"\n >\n @if (shouldShowEmptyState()) {\n <div\n class=\"info-card-empty-state\"\n role=\"status\"\n aria-live=\"polite\"\n [attr.data-testid]=\"'info-card-empty-state'\"\n >\n {{ getEmptyStateMessage() }}\n </div>\n } @else {\n @for (item of data(); track $index) {\n <div\n class=\"info-card-row\"\n role=\"listitem\"\n [attr.data-index]=\"$index\"\n [class]=\"item.customClass || ''\"\n >\n <div\n class=\"info-card-label\"\n [style.width]=\"item.labelWidth || options().labelWidth\"\n [attr.data-label]=\"item.label\"\n >\n {{ item.label }}\n </div>\n <div\n class=\"info-card-value\"\n [style.width]=\"item.valueWidth || options().valueWidth\"\n [attr.data-value]=\"item.value\"\n [title]=\"item.value?.toString() || ''\"\n >\n {{ item.value ?? 'Non renseign\u00E9' }}\n </div>\n </div>\n }\n }\n </div>\n }\n </div>\n\n <div class=\"info-card-actions\" [class]=\"getActionsClasses()\">\n <ng-content select=\"[card-actions]\"></ng-content>\n </div>\n</div>\n", styles: [".info-card{background:var(--surface-card);border-radius:var(--border-radius-lg, .75rem);overflow:hidden;transition:all .2s ease;width:100%;height:100%;display:flex;flex-direction:column;position:relative}.info-card.variant-elevated{box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f}.info-card.variant-elevated.hoverable:hover{box-shadow:0 4px 6px #0000001a,0 2px 4px #0000000f}.info-card.variant-outlined{border:1px solid var(--surface-border)}.info-card.variant-default{background:var(--surface-section)}.info-card.hoverable:hover{transform:translateY(-2px)}.info-card.interactive{cursor:pointer;-webkit-user-select:none;user-select:none}.info-card.interactive:focus{outline:none;box-shadow:0 0 0 3px rgba(var(--primary-500-rgb, 59, 130, 246),.2)}.info-card.interactive:focus:not(:focus-visible){box-shadow:none}.info-card.interactive:active{transform:translateY(0)}.info-card.disabled{opacity:.6;pointer-events:none;cursor:not-allowed}.info-card.loading{pointer-events:none}.info-card-header{background:var(--surface-ground);border-bottom:var(--border-width-1) solid var(--surface-border);display:flex;align-items:center;justify-content:space-between;gap:var(--size-2)}.info-card-header-actions{display:flex;align-items:center;gap:var(--spacing-xs);padding-right:var(--size-2);flex-shrink:0}.info-card-header-actions:empty{display:none}.info-card-title{color:var(--primary-color);margin:0;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);padding:var(--size-2) var(--size-4);display:flex;align-items:center;gap:var(--size-2);transition:all var(--animation-duration-fast) var(--animation-easing-default)}.info-card-title i{font-size:var(--icon-size-md);flex-shrink:0}.info-card-body{flex:1;display:flex;flex-direction:column}.info-card-content{padding:var(--size-2);min-height:var(--size-48);display:flex;flex-direction:column;transition:opacity var(--animation-duration-normal) var(--animation-easing-default)}.info-card-row{display:flex;align-items:center;padding:var(--size-1) 0;min-height:var(--size-8);animation:fadeIn var(--animation-duration-fast) var(--animation-easing-default);transition:background-color var(--animation-duration-fast) var(--animation-easing-default)}.info-card-row:hover{background-color:var(--surface-hover);border-radius:var(--radius-base)}.info-card-row:last-child{border-bottom:none}.info-card-label{font-weight:var(--font-weight-medium);color:var(--text-color-secondary);font-size:var(--font-size-sm);padding-right:var(--size-2);position:relative;min-width:0;flex:1;line-height:var(--line-height-normal)}.info-card-label:after{content:\"\";position:absolute;right:0;top:50%;width:var(--size-1);height:var(--border-width-1);background-color:var(--surface-border)}.info-card-value{font-weight:var(--font-weight-medium);color:var(--text-color);font-size:var(--font-size-sm);padding-left:var(--size-2);text-align:left;min-width:0;flex:2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:var(--line-height-normal)}.info-card-empty-state{flex:1;display:flex;align-items:center;justify-content:center;text-align:center;color:var(--text-color-secondary);font-style:italic;font-size:var(--font-size-sm);padding:var(--size-6);background:var(--surface-ground);border-radius:var(--radius-lg);margin:var(--size-2);border:var(--border-width-1) dashed var(--surface-border);animation:fadeIn var(--animation-duration-normal) var(--animation-easing-default)}.info-card-actions>*{padding:var(--size-3) var(--size-4);background:var(--surface-ground);border-top:var(--border-width-1) solid var(--surface-border);display:flex;gap:var(--spacing-sm);align-items:center;justify-content:flex-end}.info-card-actions:not(:has(*)){display:none}.info-card-actions.mobile-full-width-buttons>*{display:flex;flex-direction:column;width:100%;gap:var(--spacing-sm)}.info-card-loading{display:flex;flex-direction:column;gap:var(--spacing-sm);padding:var(--size-2);animation:pulse 1.5s ease-in-out infinite}.skeleton-line{height:var(--size-4);background:linear-gradient(90deg,var(--surface-border) 25%,var(--surface-hover) 50%,var(--surface-border) 75%);background-size:200% 100%;animation:shimmer 1.5s ease-in-out infinite;border-radius:var(--spacing-xs)}.skeleton-line.short{width:60%}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}@keyframes fadeIn{0%{opacity:0;transform:translateY(var(--size-1))}to{opacity:1;transform:translateY(0)}}@media(max-width:768px){.info-card-title{font-size:var(--font-size-sm);padding:var(--size-1-5) var(--size-3);gap:var(--size-1-5)}.info-card-title i{font-size:var(--icon-size-sm)}.info-card-header-actions{padding-right:var(--size-1-5)}.info-card-content{padding:var(--size-1-5);min-height:var(--size-36)}.info-card-row{min-height:var(--size-7);padding:var(--size-0-5) 0}.info-card-label,.info-card-value{font-size:var(--font-size-xs)}.info-card-empty-state{font-size:var(--font-size-xs);padding:var(--size-4);margin:var(--size-1-5)}.info-card-actions{padding:var(--size-2) var(--size-3)}}@media(max-width:480px){.info-card-header{flex-wrap:wrap;gap:var(--size-1)}.info-card-title{font-size:var(--font-size-xs);padding:var(--size-1) var(--size-2);gap:var(--size-1)}.info-card-title i{font-size:var(--icon-size-xs)}.info-card-header-actions{padding:0 var(--size-1) var(--size-1) var(--size-1)}.info-card-content{padding:var(--size-1);min-height:auto}.info-card-row{flex-direction:column;align-items:flex-start;gap:var(--size-0-5);padding:var(--size-1-5) 0;min-height:auto}.info-card-row:hover{background-color:transparent}.info-card-label{width:100%;padding-right:0;text-align:left;flex:none;font-weight:var(--font-weight-semibold);color:var(--text-color)}.info-card-label:after{display:none}.info-card-value{width:100%;padding-left:0;text-align:left;flex:none;font-weight:var(--font-weight-normal);white-space:normal}.info-card-empty-state{padding:var(--size-3);margin:var(--size-1)}.info-card-actions{padding:var(--size-1-5) var(--size-2);flex-direction:column;gap:var(--spacing-md)}.info-card-actions>*{width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
985
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: PshInfoCardComponent, isStandalone: true, selector: "psh-info-card", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, cssClass: { classPropertyName: "cssClass", publicName: "cssClass", isSignal: true, isRequired: false, transformFunction: null }, customStyle: { classPropertyName: "customStyle", publicName: "customStyle", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, copyable: { classPropertyName: "copyable", publicName: "copyable", isSignal: true, isRequired: false, transformFunction: null }, copyButtonLabel: { classPropertyName: "copyButtonLabel", publicName: "copyButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, copyFeedbackText: { classPropertyName: "copyFeedbackText", publicName: "copyFeedbackText", isSignal: true, isRequired: false, transformFunction: null }, autoFullWidthOnMobile: { classPropertyName: "autoFullWidthOnMobile", publicName: "autoFullWidthOnMobile", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked", copied: "copied", copyFailed: "copyFailed" }, host: { styleAttribute: "display: block; height: 100%;" }, ngImport: i0, template: "<div\n [class]=\"computedClasses()\"\n [ngStyle]=\"computedStyles()\"\n (click)=\"handleClick($event)\"\n (keydown)=\"handleKeydown($event)\"\n role=\"region\"\n [attr.tabindex]=\"interactive() && !disabled() ? 0 : null\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-disabled]=\"disabled() ? 'true' : null\"\n [attr.aria-busy]=\"loading() ? 'true' : null\"\n>\n @if (title() || hasHeaderActions()) {\n <div class=\"info-card-header\">\n @if (title()) {\n <h3 class=\"info-card-title\">\n @if (icon()) {\n <i\n class=\"ph {{ titleIcon() }}\"\n aria-hidden=\"true\"\n [attr.data-icon]=\"icon()\"\n ></i>\n }\n {{ title() }}\n </h3>\n }\n <div class=\"info-card-header-actions\">\n <ng-content select=\"[card-header-actions]\"></ng-content>\n </div>\n </div>\n }\n\n <div class=\"info-card-body\">\n @if (loading()) {\n <div class=\"info-card-loading\">\n <div class=\"skeleton-line\"></div>\n <div class=\"skeleton-line\"></div>\n <div class=\"skeleton-line short\"></div>\n </div>\n } @else {\n <div\n class=\"info-card-content\"\n role=\"list\"\n >\n @if (shouldShowEmptyState()) {\n <div\n class=\"info-card-empty-state\"\n role=\"status\"\n aria-live=\"polite\"\n [attr.data-testid]=\"'info-card-empty-state'\"\n >\n {{ getEmptyStateMessage() }}\n </div>\n } @else {\n @for (item of data(); track $index) {\n <div\n class=\"info-card-row\"\n role=\"listitem\"\n [attr.data-index]=\"$index\"\n [class]=\"item.customClass || ''\"\n >\n <div\n class=\"info-card-label\"\n [style.width]=\"item.labelWidth || options().labelWidth\"\n [attr.data-label]=\"item.label\"\n >\n {{ item.label }}\n </div>\n <div\n class=\"info-card-value-group\"\n [style.width]=\"item.valueWidth || options().valueWidth\"\n >\n <span\n class=\"info-card-value\"\n [attr.data-value]=\"item.value\"\n [title]=\"item.value?.toString() || ''\"\n >{{ item.value ?? 'Non renseign\u00E9' }}</span>\n @if (isRowCopyable(item) && hasNonEmptyValue(item)) {\n <button\n type=\"button\"\n class=\"info-card-copy-btn\"\n [class.copied]=\"copiedRowIndex() === $index\"\n [attr.aria-label]=\"copyButtonLabel() + ' ' + item.label\"\n (click)=\"copyRowValue(item, $index); $event.stopPropagation()\"\n >\n @if (copiedRowIndex() === $index) {\n <i class=\"ph ph-check\" aria-hidden=\"true\"></i>\n <span class=\"info-card-copy-feedback\" aria-hidden=\"true\">{{ copyFeedbackText() }}</span>\n } @else {\n <i class=\"ph ph-copy\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n </div>\n </div>\n }\n <span\n class=\"info-card-sr-only\"\n role=\"status\"\n aria-live=\"polite\"\n >\n @if (copiedRowIndex() !== null) {\n {{ copyFeedbackText() }}\n }\n </span>\n }\n </div>\n }\n </div>\n\n <div class=\"info-card-actions\" [class]=\"getActionsClasses()\">\n <ng-content select=\"[card-actions]\"></ng-content>\n </div>\n</div>\n", styles: [".info-card{background:var(--surface-card);border-radius:var(--border-radius-lg, .75rem);overflow:hidden;transition:all .2s ease;width:100%;height:100%;display:flex;flex-direction:column;position:relative}.info-card.variant-elevated{box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f}.info-card.variant-elevated.hoverable:hover{box-shadow:0 4px 6px #0000001a,0 2px 4px #0000000f}.info-card.variant-outlined{border:1px solid var(--surface-border)}.info-card.variant-default{background:var(--surface-section)}.info-card.hoverable:hover{transform:translateY(-2px)}.info-card.interactive{cursor:pointer;-webkit-user-select:none;user-select:none}.info-card.interactive:focus{outline:none;box-shadow:0 0 0 3px rgba(var(--primary-500-rgb, 59, 130, 246),.2)}.info-card.interactive:focus:not(:focus-visible){box-shadow:none}.info-card.interactive:active{transform:translateY(0)}.info-card.disabled{opacity:.6;pointer-events:none;cursor:not-allowed}.info-card.loading{pointer-events:none}.info-card-header{background:var(--surface-ground);border-bottom:var(--border-width-1) solid var(--surface-border);display:flex;align-items:center;justify-content:space-between;gap:var(--size-2)}.info-card-header-actions{display:flex;align-items:center;gap:var(--spacing-xs);padding-right:var(--size-2);flex-shrink:0}.info-card-header-actions:empty{display:none}.info-card-title{color:var(--primary-color);margin:0;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);padding:var(--size-2) var(--size-4);display:flex;align-items:center;gap:var(--size-2);transition:all var(--animation-duration-fast) var(--animation-easing-default)}.info-card-title i{font-size:var(--icon-size-md);flex-shrink:0}.info-card-body{flex:1;display:flex;flex-direction:column}.info-card-content{padding:var(--size-2);min-height:var(--size-48);display:flex;flex-direction:column;transition:opacity var(--animation-duration-normal) var(--animation-easing-default)}.info-card-row{display:flex;align-items:center;padding:var(--size-1) 0;min-height:var(--size-8);animation:fadeIn var(--animation-duration-fast) var(--animation-easing-default);transition:background-color var(--animation-duration-fast) var(--animation-easing-default)}.info-card-row:hover{background-color:var(--surface-hover);border-radius:var(--radius-base)}.info-card-row:last-child{border-bottom:none}.info-card-label{font-weight:var(--font-weight-medium);color:var(--text-color-secondary);font-size:var(--font-size-sm);padding-right:var(--size-2);position:relative;min-width:0;flex:1;line-height:var(--line-height-normal)}.info-card-label:after{content:\"\";position:absolute;right:0;top:50%;width:var(--size-1);height:var(--border-width-1);background-color:var(--surface-border)}.info-card-value-group{display:inline-flex;align-items:center;gap:var(--spacing-xs);padding-left:var(--size-2);min-width:0;flex:2}.info-card-value{font-weight:var(--font-weight-medium);color:var(--text-color);font-size:var(--font-size-sm);text-align:left;min-width:0;flex-shrink:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:var(--line-height-normal)}.info-card-empty-state{flex:1;display:flex;align-items:center;justify-content:center;text-align:center;color:var(--text-color-secondary);font-style:italic;font-size:var(--font-size-sm);padding:var(--size-6);background:var(--surface-ground);border-radius:var(--radius-lg);margin:var(--size-2);border:var(--border-width-1) dashed var(--surface-border);animation:fadeIn var(--animation-duration-normal) var(--animation-easing-default)}.info-card-actions>*{padding:var(--size-3) var(--size-4);background:var(--surface-ground);border-top:var(--border-width-1) solid var(--surface-border);display:flex;gap:var(--spacing-sm);align-items:center;justify-content:flex-end}.info-card-actions:not(:has(*)){display:none}.info-card-actions.mobile-full-width-buttons>*{display:flex;flex-direction:column;width:100%;gap:var(--spacing-sm)}.info-card-loading{display:flex;flex-direction:column;gap:var(--spacing-sm);padding:var(--size-2);animation:pulse 1.5s ease-in-out infinite}.skeleton-line{height:var(--size-4);background:linear-gradient(90deg,var(--surface-border) 25%,var(--surface-hover) 50%,var(--surface-border) 75%);background-size:200% 100%;animation:shimmer 1.5s ease-in-out infinite;border-radius:var(--spacing-xs)}.skeleton-line.short{width:60%}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}@keyframes fadeIn{0%{opacity:0;transform:translateY(var(--size-1))}to{opacity:1;transform:translateY(0)}}.info-card-copy-btn{display:inline-flex;align-items:center;gap:var(--spacing-xs);padding:var(--spacing-xs);border:none;background:transparent;color:var(--text-color-secondary);border-radius:var(--border-radius);cursor:pointer;min-width:24px;min-height:24px;flex-shrink:0;transition:opacity var(--animation-duration-fast) var(--animation-easing-default),color var(--animation-duration-fast) var(--animation-easing-default)}@media(hover:hover){.info-card-copy-btn{opacity:0}.info-card-row:hover .info-card-copy-btn,.info-card-row:focus-within .info-card-copy-btn,.info-card-value-group:hover .info-card-copy-btn,.info-card-value-group:focus-within .info-card-copy-btn{opacity:1}}.info-card-copy-btn:hover{color:var(--primary-color)}.info-card-copy-btn:focus-visible{outline:none;box-shadow:0 0 0 2px var(--primary-color);opacity:1}.info-card-copy-btn.copied{color:var(--success-color);opacity:1}.info-card-copy-btn i{font-size:var(--icon-size-sm)}.info-card-copy-feedback{font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);color:var(--success-color);white-space:nowrap}.info-card-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media(max-width:768px){.info-card-title{font-size:var(--font-size-sm);padding:var(--size-1-5) var(--size-3);gap:var(--size-1-5)}.info-card-title i{font-size:var(--icon-size-sm)}.info-card-header-actions{padding-right:var(--size-1-5)}.info-card-content{padding:var(--size-1-5);min-height:var(--size-36)}.info-card-row{min-height:var(--size-7);padding:var(--size-0-5) 0}.info-card-label,.info-card-value{font-size:var(--font-size-xs)}.info-card-empty-state{font-size:var(--font-size-xs);padding:var(--size-4);margin:var(--size-1-5)}.info-card-actions{padding:var(--size-2) var(--size-3)}}@media(max-width:480px){.info-card-header{flex-wrap:wrap;gap:var(--size-1)}.info-card-title{font-size:var(--font-size-xs);padding:var(--size-1) var(--size-2);gap:var(--size-1)}.info-card-title i{font-size:var(--icon-size-xs)}.info-card-header-actions{padding:0 var(--size-1) var(--size-1) var(--size-1)}.info-card-content{padding:var(--size-1);min-height:auto}.info-card-row{flex-direction:column;align-items:flex-start;gap:var(--size-0-5);padding:var(--size-1-5) 0;min-height:auto}.info-card-row:hover{background-color:transparent}.info-card-label{width:100%;padding-right:0;text-align:left;flex:none;font-weight:var(--font-weight-semibold);color:var(--text-color)}.info-card-label:after{display:none}.info-card-value-group{width:100%;padding-left:0;flex:none}.info-card-value{padding-left:0;text-align:left;flex-shrink:1;font-weight:var(--font-weight-normal);white-space:normal}.info-card-empty-state{padding:var(--size-3);margin:var(--size-1)}.info-card-actions{padding:var(--size-1-5) var(--size-2);flex-direction:column;gap:var(--spacing-md)}.info-card-actions>*{width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
939
986
  }
940
987
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PshInfoCardComponent, decorators: [{
941
988
  type: Component,
942
989
  args: [{ selector: 'psh-info-card', imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
943
990
  style: 'display: block; height: 100%;'
944
- }, template: "<div\n [class]=\"computedClasses()\"\n [ngStyle]=\"computedStyles()\"\n (click)=\"handleClick($event)\"\n (keydown)=\"handleKeydown($event)\"\n role=\"region\"\n [attr.tabindex]=\"interactive() && !disabled() ? 0 : null\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-disabled]=\"disabled() ? 'true' : null\"\n [attr.aria-busy]=\"loading() ? 'true' : null\"\n>\n @if (title() || hasHeaderActions()) {\n <div class=\"info-card-header\">\n @if (title()) {\n <h3 class=\"info-card-title\">\n @if (icon()) {\n <i\n class=\"ph {{ titleIcon() }}\"\n aria-hidden=\"true\"\n [attr.data-icon]=\"icon()\"\n ></i>\n }\n {{ title() }}\n </h3>\n }\n <div class=\"info-card-header-actions\">\n <ng-content select=\"[card-header-actions]\"></ng-content>\n </div>\n </div>\n }\n\n <div class=\"info-card-body\">\n @if (loading()) {\n <div class=\"info-card-loading\">\n <div class=\"skeleton-line\"></div>\n <div class=\"skeleton-line\"></div>\n <div class=\"skeleton-line short\"></div>\n </div>\n } @else {\n <div\n class=\"info-card-content\"\n role=\"list\"\n >\n @if (shouldShowEmptyState()) {\n <div\n class=\"info-card-empty-state\"\n role=\"status\"\n aria-live=\"polite\"\n [attr.data-testid]=\"'info-card-empty-state'\"\n >\n {{ getEmptyStateMessage() }}\n </div>\n } @else {\n @for (item of data(); track $index) {\n <div\n class=\"info-card-row\"\n role=\"listitem\"\n [attr.data-index]=\"$index\"\n [class]=\"item.customClass || ''\"\n >\n <div\n class=\"info-card-label\"\n [style.width]=\"item.labelWidth || options().labelWidth\"\n [attr.data-label]=\"item.label\"\n >\n {{ item.label }}\n </div>\n <div\n class=\"info-card-value\"\n [style.width]=\"item.valueWidth || options().valueWidth\"\n [attr.data-value]=\"item.value\"\n [title]=\"item.value?.toString() || ''\"\n >\n {{ item.value ?? 'Non renseign\u00E9' }}\n </div>\n </div>\n }\n }\n </div>\n }\n </div>\n\n <div class=\"info-card-actions\" [class]=\"getActionsClasses()\">\n <ng-content select=\"[card-actions]\"></ng-content>\n </div>\n</div>\n", styles: [".info-card{background:var(--surface-card);border-radius:var(--border-radius-lg, .75rem);overflow:hidden;transition:all .2s ease;width:100%;height:100%;display:flex;flex-direction:column;position:relative}.info-card.variant-elevated{box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f}.info-card.variant-elevated.hoverable:hover{box-shadow:0 4px 6px #0000001a,0 2px 4px #0000000f}.info-card.variant-outlined{border:1px solid var(--surface-border)}.info-card.variant-default{background:var(--surface-section)}.info-card.hoverable:hover{transform:translateY(-2px)}.info-card.interactive{cursor:pointer;-webkit-user-select:none;user-select:none}.info-card.interactive:focus{outline:none;box-shadow:0 0 0 3px rgba(var(--primary-500-rgb, 59, 130, 246),.2)}.info-card.interactive:focus:not(:focus-visible){box-shadow:none}.info-card.interactive:active{transform:translateY(0)}.info-card.disabled{opacity:.6;pointer-events:none;cursor:not-allowed}.info-card.loading{pointer-events:none}.info-card-header{background:var(--surface-ground);border-bottom:var(--border-width-1) solid var(--surface-border);display:flex;align-items:center;justify-content:space-between;gap:var(--size-2)}.info-card-header-actions{display:flex;align-items:center;gap:var(--spacing-xs);padding-right:var(--size-2);flex-shrink:0}.info-card-header-actions:empty{display:none}.info-card-title{color:var(--primary-color);margin:0;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);padding:var(--size-2) var(--size-4);display:flex;align-items:center;gap:var(--size-2);transition:all var(--animation-duration-fast) var(--animation-easing-default)}.info-card-title i{font-size:var(--icon-size-md);flex-shrink:0}.info-card-body{flex:1;display:flex;flex-direction:column}.info-card-content{padding:var(--size-2);min-height:var(--size-48);display:flex;flex-direction:column;transition:opacity var(--animation-duration-normal) var(--animation-easing-default)}.info-card-row{display:flex;align-items:center;padding:var(--size-1) 0;min-height:var(--size-8);animation:fadeIn var(--animation-duration-fast) var(--animation-easing-default);transition:background-color var(--animation-duration-fast) var(--animation-easing-default)}.info-card-row:hover{background-color:var(--surface-hover);border-radius:var(--radius-base)}.info-card-row:last-child{border-bottom:none}.info-card-label{font-weight:var(--font-weight-medium);color:var(--text-color-secondary);font-size:var(--font-size-sm);padding-right:var(--size-2);position:relative;min-width:0;flex:1;line-height:var(--line-height-normal)}.info-card-label:after{content:\"\";position:absolute;right:0;top:50%;width:var(--size-1);height:var(--border-width-1);background-color:var(--surface-border)}.info-card-value{font-weight:var(--font-weight-medium);color:var(--text-color);font-size:var(--font-size-sm);padding-left:var(--size-2);text-align:left;min-width:0;flex:2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:var(--line-height-normal)}.info-card-empty-state{flex:1;display:flex;align-items:center;justify-content:center;text-align:center;color:var(--text-color-secondary);font-style:italic;font-size:var(--font-size-sm);padding:var(--size-6);background:var(--surface-ground);border-radius:var(--radius-lg);margin:var(--size-2);border:var(--border-width-1) dashed var(--surface-border);animation:fadeIn var(--animation-duration-normal) var(--animation-easing-default)}.info-card-actions>*{padding:var(--size-3) var(--size-4);background:var(--surface-ground);border-top:var(--border-width-1) solid var(--surface-border);display:flex;gap:var(--spacing-sm);align-items:center;justify-content:flex-end}.info-card-actions:not(:has(*)){display:none}.info-card-actions.mobile-full-width-buttons>*{display:flex;flex-direction:column;width:100%;gap:var(--spacing-sm)}.info-card-loading{display:flex;flex-direction:column;gap:var(--spacing-sm);padding:var(--size-2);animation:pulse 1.5s ease-in-out infinite}.skeleton-line{height:var(--size-4);background:linear-gradient(90deg,var(--surface-border) 25%,var(--surface-hover) 50%,var(--surface-border) 75%);background-size:200% 100%;animation:shimmer 1.5s ease-in-out infinite;border-radius:var(--spacing-xs)}.skeleton-line.short{width:60%}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}@keyframes fadeIn{0%{opacity:0;transform:translateY(var(--size-1))}to{opacity:1;transform:translateY(0)}}@media(max-width:768px){.info-card-title{font-size:var(--font-size-sm);padding:var(--size-1-5) var(--size-3);gap:var(--size-1-5)}.info-card-title i{font-size:var(--icon-size-sm)}.info-card-header-actions{padding-right:var(--size-1-5)}.info-card-content{padding:var(--size-1-5);min-height:var(--size-36)}.info-card-row{min-height:var(--size-7);padding:var(--size-0-5) 0}.info-card-label,.info-card-value{font-size:var(--font-size-xs)}.info-card-empty-state{font-size:var(--font-size-xs);padding:var(--size-4);margin:var(--size-1-5)}.info-card-actions{padding:var(--size-2) var(--size-3)}}@media(max-width:480px){.info-card-header{flex-wrap:wrap;gap:var(--size-1)}.info-card-title{font-size:var(--font-size-xs);padding:var(--size-1) var(--size-2);gap:var(--size-1)}.info-card-title i{font-size:var(--icon-size-xs)}.info-card-header-actions{padding:0 var(--size-1) var(--size-1) var(--size-1)}.info-card-content{padding:var(--size-1);min-height:auto}.info-card-row{flex-direction:column;align-items:flex-start;gap:var(--size-0-5);padding:var(--size-1-5) 0;min-height:auto}.info-card-row:hover{background-color:transparent}.info-card-label{width:100%;padding-right:0;text-align:left;flex:none;font-weight:var(--font-weight-semibold);color:var(--text-color)}.info-card-label:after{display:none}.info-card-value{width:100%;padding-left:0;text-align:left;flex:none;font-weight:var(--font-weight-normal);white-space:normal}.info-card-empty-state{padding:var(--size-3);margin:var(--size-1)}.info-card-actions{padding:var(--size-1-5) var(--size-2);flex-direction:column;gap:var(--spacing-md)}.info-card-actions>*{width:100%}}\n"] }]
945
- }], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], cssClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssClass", required: false }] }], customStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "customStyle", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }], autoFullWidthOnMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFullWidthOnMobile", required: false }] }] } });
991
+ }, template: "<div\n [class]=\"computedClasses()\"\n [ngStyle]=\"computedStyles()\"\n (click)=\"handleClick($event)\"\n (keydown)=\"handleKeydown($event)\"\n role=\"region\"\n [attr.tabindex]=\"interactive() && !disabled() ? 0 : null\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-disabled]=\"disabled() ? 'true' : null\"\n [attr.aria-busy]=\"loading() ? 'true' : null\"\n>\n @if (title() || hasHeaderActions()) {\n <div class=\"info-card-header\">\n @if (title()) {\n <h3 class=\"info-card-title\">\n @if (icon()) {\n <i\n class=\"ph {{ titleIcon() }}\"\n aria-hidden=\"true\"\n [attr.data-icon]=\"icon()\"\n ></i>\n }\n {{ title() }}\n </h3>\n }\n <div class=\"info-card-header-actions\">\n <ng-content select=\"[card-header-actions]\"></ng-content>\n </div>\n </div>\n }\n\n <div class=\"info-card-body\">\n @if (loading()) {\n <div class=\"info-card-loading\">\n <div class=\"skeleton-line\"></div>\n <div class=\"skeleton-line\"></div>\n <div class=\"skeleton-line short\"></div>\n </div>\n } @else {\n <div\n class=\"info-card-content\"\n role=\"list\"\n >\n @if (shouldShowEmptyState()) {\n <div\n class=\"info-card-empty-state\"\n role=\"status\"\n aria-live=\"polite\"\n [attr.data-testid]=\"'info-card-empty-state'\"\n >\n {{ getEmptyStateMessage() }}\n </div>\n } @else {\n @for (item of data(); track $index) {\n <div\n class=\"info-card-row\"\n role=\"listitem\"\n [attr.data-index]=\"$index\"\n [class]=\"item.customClass || ''\"\n >\n <div\n class=\"info-card-label\"\n [style.width]=\"item.labelWidth || options().labelWidth\"\n [attr.data-label]=\"item.label\"\n >\n {{ item.label }}\n </div>\n <div\n class=\"info-card-value-group\"\n [style.width]=\"item.valueWidth || options().valueWidth\"\n >\n <span\n class=\"info-card-value\"\n [attr.data-value]=\"item.value\"\n [title]=\"item.value?.toString() || ''\"\n >{{ item.value ?? 'Non renseign\u00E9' }}</span>\n @if (isRowCopyable(item) && hasNonEmptyValue(item)) {\n <button\n type=\"button\"\n class=\"info-card-copy-btn\"\n [class.copied]=\"copiedRowIndex() === $index\"\n [attr.aria-label]=\"copyButtonLabel() + ' ' + item.label\"\n (click)=\"copyRowValue(item, $index); $event.stopPropagation()\"\n >\n @if (copiedRowIndex() === $index) {\n <i class=\"ph ph-check\" aria-hidden=\"true\"></i>\n <span class=\"info-card-copy-feedback\" aria-hidden=\"true\">{{ copyFeedbackText() }}</span>\n } @else {\n <i class=\"ph ph-copy\" aria-hidden=\"true\"></i>\n }\n </button>\n }\n </div>\n </div>\n }\n <span\n class=\"info-card-sr-only\"\n role=\"status\"\n aria-live=\"polite\"\n >\n @if (copiedRowIndex() !== null) {\n {{ copyFeedbackText() }}\n }\n </span>\n }\n </div>\n }\n </div>\n\n <div class=\"info-card-actions\" [class]=\"getActionsClasses()\">\n <ng-content select=\"[card-actions]\"></ng-content>\n </div>\n</div>\n", styles: [".info-card{background:var(--surface-card);border-radius:var(--border-radius-lg, .75rem);overflow:hidden;transition:all .2s ease;width:100%;height:100%;display:flex;flex-direction:column;position:relative}.info-card.variant-elevated{box-shadow:0 1px 3px #0000001a,0 1px 2px #0000000f}.info-card.variant-elevated.hoverable:hover{box-shadow:0 4px 6px #0000001a,0 2px 4px #0000000f}.info-card.variant-outlined{border:1px solid var(--surface-border)}.info-card.variant-default{background:var(--surface-section)}.info-card.hoverable:hover{transform:translateY(-2px)}.info-card.interactive{cursor:pointer;-webkit-user-select:none;user-select:none}.info-card.interactive:focus{outline:none;box-shadow:0 0 0 3px rgba(var(--primary-500-rgb, 59, 130, 246),.2)}.info-card.interactive:focus:not(:focus-visible){box-shadow:none}.info-card.interactive:active{transform:translateY(0)}.info-card.disabled{opacity:.6;pointer-events:none;cursor:not-allowed}.info-card.loading{pointer-events:none}.info-card-header{background:var(--surface-ground);border-bottom:var(--border-width-1) solid var(--surface-border);display:flex;align-items:center;justify-content:space-between;gap:var(--size-2)}.info-card-header-actions{display:flex;align-items:center;gap:var(--spacing-xs);padding-right:var(--size-2);flex-shrink:0}.info-card-header-actions:empty{display:none}.info-card-title{color:var(--primary-color);margin:0;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);padding:var(--size-2) var(--size-4);display:flex;align-items:center;gap:var(--size-2);transition:all var(--animation-duration-fast) var(--animation-easing-default)}.info-card-title i{font-size:var(--icon-size-md);flex-shrink:0}.info-card-body{flex:1;display:flex;flex-direction:column}.info-card-content{padding:var(--size-2);min-height:var(--size-48);display:flex;flex-direction:column;transition:opacity var(--animation-duration-normal) var(--animation-easing-default)}.info-card-row{display:flex;align-items:center;padding:var(--size-1) 0;min-height:var(--size-8);animation:fadeIn var(--animation-duration-fast) var(--animation-easing-default);transition:background-color var(--animation-duration-fast) var(--animation-easing-default)}.info-card-row:hover{background-color:var(--surface-hover);border-radius:var(--radius-base)}.info-card-row:last-child{border-bottom:none}.info-card-label{font-weight:var(--font-weight-medium);color:var(--text-color-secondary);font-size:var(--font-size-sm);padding-right:var(--size-2);position:relative;min-width:0;flex:1;line-height:var(--line-height-normal)}.info-card-label:after{content:\"\";position:absolute;right:0;top:50%;width:var(--size-1);height:var(--border-width-1);background-color:var(--surface-border)}.info-card-value-group{display:inline-flex;align-items:center;gap:var(--spacing-xs);padding-left:var(--size-2);min-width:0;flex:2}.info-card-value{font-weight:var(--font-weight-medium);color:var(--text-color);font-size:var(--font-size-sm);text-align:left;min-width:0;flex-shrink:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:var(--line-height-normal)}.info-card-empty-state{flex:1;display:flex;align-items:center;justify-content:center;text-align:center;color:var(--text-color-secondary);font-style:italic;font-size:var(--font-size-sm);padding:var(--size-6);background:var(--surface-ground);border-radius:var(--radius-lg);margin:var(--size-2);border:var(--border-width-1) dashed var(--surface-border);animation:fadeIn var(--animation-duration-normal) var(--animation-easing-default)}.info-card-actions>*{padding:var(--size-3) var(--size-4);background:var(--surface-ground);border-top:var(--border-width-1) solid var(--surface-border);display:flex;gap:var(--spacing-sm);align-items:center;justify-content:flex-end}.info-card-actions:not(:has(*)){display:none}.info-card-actions.mobile-full-width-buttons>*{display:flex;flex-direction:column;width:100%;gap:var(--spacing-sm)}.info-card-loading{display:flex;flex-direction:column;gap:var(--spacing-sm);padding:var(--size-2);animation:pulse 1.5s ease-in-out infinite}.skeleton-line{height:var(--size-4);background:linear-gradient(90deg,var(--surface-border) 25%,var(--surface-hover) 50%,var(--surface-border) 75%);background-size:200% 100%;animation:shimmer 1.5s ease-in-out infinite;border-radius:var(--spacing-xs)}.skeleton-line.short{width:60%}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}@keyframes fadeIn{0%{opacity:0;transform:translateY(var(--size-1))}to{opacity:1;transform:translateY(0)}}.info-card-copy-btn{display:inline-flex;align-items:center;gap:var(--spacing-xs);padding:var(--spacing-xs);border:none;background:transparent;color:var(--text-color-secondary);border-radius:var(--border-radius);cursor:pointer;min-width:24px;min-height:24px;flex-shrink:0;transition:opacity var(--animation-duration-fast) var(--animation-easing-default),color var(--animation-duration-fast) var(--animation-easing-default)}@media(hover:hover){.info-card-copy-btn{opacity:0}.info-card-row:hover .info-card-copy-btn,.info-card-row:focus-within .info-card-copy-btn,.info-card-value-group:hover .info-card-copy-btn,.info-card-value-group:focus-within .info-card-copy-btn{opacity:1}}.info-card-copy-btn:hover{color:var(--primary-color)}.info-card-copy-btn:focus-visible{outline:none;box-shadow:0 0 0 2px var(--primary-color);opacity:1}.info-card-copy-btn.copied{color:var(--success-color);opacity:1}.info-card-copy-btn i{font-size:var(--icon-size-sm)}.info-card-copy-feedback{font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);color:var(--success-color);white-space:nowrap}.info-card-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media(max-width:768px){.info-card-title{font-size:var(--font-size-sm);padding:var(--size-1-5) var(--size-3);gap:var(--size-1-5)}.info-card-title i{font-size:var(--icon-size-sm)}.info-card-header-actions{padding-right:var(--size-1-5)}.info-card-content{padding:var(--size-1-5);min-height:var(--size-36)}.info-card-row{min-height:var(--size-7);padding:var(--size-0-5) 0}.info-card-label,.info-card-value{font-size:var(--font-size-xs)}.info-card-empty-state{font-size:var(--font-size-xs);padding:var(--size-4);margin:var(--size-1-5)}.info-card-actions{padding:var(--size-2) var(--size-3)}}@media(max-width:480px){.info-card-header{flex-wrap:wrap;gap:var(--size-1)}.info-card-title{font-size:var(--font-size-xs);padding:var(--size-1) var(--size-2);gap:var(--size-1)}.info-card-title i{font-size:var(--icon-size-xs)}.info-card-header-actions{padding:0 var(--size-1) var(--size-1) var(--size-1)}.info-card-content{padding:var(--size-1);min-height:auto}.info-card-row{flex-direction:column;align-items:flex-start;gap:var(--size-0-5);padding:var(--size-1-5) 0;min-height:auto}.info-card-row:hover{background-color:transparent}.info-card-label{width:100%;padding-right:0;text-align:left;flex:none;font-weight:var(--font-weight-semibold);color:var(--text-color)}.info-card-label:after{display:none}.info-card-value-group{width:100%;padding-left:0;flex:none}.info-card-value{padding-left:0;text-align:left;flex-shrink:1;font-weight:var(--font-weight-normal);white-space:normal}.info-card-empty-state{padding:var(--size-3);margin:var(--size-1)}.info-card-actions{padding:var(--size-1-5) var(--size-2);flex-direction:column;gap:var(--spacing-md)}.info-card-actions>*{width:100%}}\n"] }]
992
+ }], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], cssClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "cssClass", required: false }] }], customStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "customStyle", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }], copyable: [{ type: i0.Input, args: [{ isSignal: true, alias: "copyable", required: false }] }], copyButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "copyButtonLabel", required: false }] }], copyFeedbackText: [{ type: i0.Input, args: [{ isSignal: true, alias: "copyFeedbackText", required: false }] }], copied: [{ type: i0.Output, args: ["copied"] }], copyFailed: [{ type: i0.Output, args: ["copyFailed"] }], autoFullWidthOnMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoFullWidthOnMobile", required: false }] }] } });
946
993
 
947
994
  const CHECKBOX_CONFIG = new InjectionToken('CHECKBOX_CONFIG', {
948
995
  factory: () => ({
@@ -1961,11 +2008,6 @@ class PshMenuComponent {
1961
2008
  this.expandedItemsSet = computed(() => new Set(this.expandedItemIds()), ...(ngDevMode ? [{ debugName: "expandedItemsSet" }] : /* istanbul ignore next */ []));
1962
2009
  this.state = computed(() => this.getState(), ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
1963
2010
  this.showTooltip = computed(() => this.collapsed() && this.mode() === 'vertical', ...(ngDevMode ? [{ debugName: "showTooltip" }] : /* istanbul ignore next */ []));
1964
- effect(() => {
1965
- if (this.collapsed()) {
1966
- this.expandedItemIds.set([]);
1967
- }
1968
- });
1969
2011
  }
1970
2012
  getState() {
1971
2013
  if (this.collapsed())
@@ -1974,6 +2016,12 @@ class PshMenuComponent {
1974
2016
  return 'collapsible';
1975
2017
  return this.mode();
1976
2018
  }
2019
+ handleItemClick(item, event, isChild) {
2020
+ if (isChild) {
2021
+ event.stopPropagation();
2022
+ }
2023
+ this.toggleItem(item, event);
2024
+ }
1977
2025
  toggleItem(item, event) {
1978
2026
  if (item.disabled)
1979
2027
  return;
@@ -1993,11 +2041,9 @@ class PshMenuComponent {
1993
2041
  }
1994
2042
  }
1995
2043
  isExpanded(item) {
1996
- return !this.collapsed() && this.expandedItemsSet().has(item.id);
2044
+ return this.expandedItemsSet().has(item.id);
1997
2045
  }
1998
2046
  expandItem(itemId) {
1999
- if (this.collapsed())
2000
- return;
2001
2047
  const current = this.expandedItemIds();
2002
2048
  if (!current.includes(itemId)) {
2003
2049
  this.expandedItemIds.set([...current, itemId]);
@@ -2010,8 +2056,6 @@ class PshMenuComponent {
2010
2056
  }
2011
2057
  }
2012
2058
  toggleItemExpansion(itemId) {
2013
- if (this.collapsed())
2014
- return;
2015
2059
  const current = this.expandedItemIds();
2016
2060
  if (current.includes(itemId)) {
2017
2061
  this.expandedItemIds.set(current.filter(id => id !== itemId));
@@ -2021,8 +2065,6 @@ class PshMenuComponent {
2021
2065
  }
2022
2066
  }
2023
2067
  expandAll() {
2024
- if (this.collapsed())
2025
- return;
2026
2068
  const allIds = this.collectItemIdsWithChildren(this.items());
2027
2069
  this.expandedItemIds.set(allIds);
2028
2070
  }
@@ -2133,11 +2175,11 @@ class PshMenuComponent {
2133
2175
  }
2134
2176
  }
2135
2177
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PshMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2136
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: PshMenuComponent, isStandalone: true, selector: "psh-menu", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, ariaLabels: { classPropertyName: "ariaLabels", publicName: "ariaLabels", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, expandedItemIds: { classPropertyName: "expandedItemIds", publicName: "expandedItemIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsed: "collapsedChange", expandedItemIds: "expandedItemIdsChange", itemClick: "itemClick", submenuToggle: "submenuToggle" }, ngImport: i0, template: "<nav \n class=\"menu\"\n [class.vertical]=\"mode() === 'vertical'\"\n [class.horizontal]=\"mode() === 'horizontal'\"\n [class.compact]=\"variant() === 'compact'\"\n [class.expanded]=\"variant() === 'expanded'\"\n [class.collapsed]=\"collapsed()\"\n role=\"navigation\"\n [attr.aria-label]=\"'Navigation menu'\"\n [attr.data-state]=\"state()\"\n>\n @if (collapsible()) {\n <button \n class=\"menu-collapse-button\"\n (click)=\"toggleCollapse()\"\n [attr.aria-expanded]=\"!collapsed()\"\n [attr.aria-label]=\"collapsed() ? ariaLabels()['expand'] : ariaLabels()['collapse']\"\n >\n <i class=\"ph ph-caret-left\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <ul class=\"menu-list\" role=\"menubar\">\n @for (item of items(); track item.id; let i = $index) {\n @if (item.divider) {\n <li class=\"menu-divider\" role=\"separator\"></li>\n } @else {\n <li\n class=\"menu-item\"\n [class.has-children]=\"item.children?.length\"\n [class.expanded]=\"isExpanded(item)\"\n [class.disabled]=\"item.disabled\"\n role=\"none\"\n >\n @if (item.path) {\n @if (showTooltip()) {\n <psh-tooltip [content]=\"item.content\" position=\"right\" [showDelay]=\"100\" [hideDelay]=\"0\">\n <a\n class=\"menu-link\"\n [attr.href]=\"item.path\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"toggleItem(item, $event)\"\n (keydown)=\"handleKeyDown($event, item, i)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n </a>\n </psh-tooltip>\n } @else {\n <a\n class=\"menu-link\"\n [attr.href]=\"item.path\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"toggleItem(item, $event)\"\n (keydown)=\"handleKeyDown($event, item, i)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ item.content }}</span>\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n @if (item.children?.length) {\n <i\n class=\"ph ph-caret-down menu-arrow\"\n [class.expanded]=\"isExpanded(item)\"\n aria-hidden=\"true\"\n ></i>\n }\n </a>\n }\n } @else {\n @if (showTooltip()) {\n <psh-tooltip [content]=\"item.content\" position=\"right\" [showDelay]=\"100\" [hideDelay]=\"0\">\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"toggleItem(item, $event)\"\n (keydown)=\"handleKeyDown($event, item, i)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n [disabled]=\"item.disabled\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n </button>\n </psh-tooltip>\n } @else {\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"toggleItem(item, $event)\"\n (keydown)=\"handleKeyDown($event, item, i)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n [disabled]=\"item.disabled\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ item.content }}</span>\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n @if (item.children?.length) {\n <i\n class=\"ph ph-caret-down menu-arrow\"\n [class.expanded]=\"isExpanded(item)\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n }\n }\n\n @if (item.children?.length) {\n <ul\n class=\"submenu\"\n role=\"menu\"\n [attr.aria-label]=\"item.content + ' submenu'\"\n >\n @for (child of item.children; track child.id) {\n <li class=\"menu-item\" role=\"none\">\n @if (child.path) {\n <a\n class=\"menu-link\"\n [attr.href]=\"child.path\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n [disabled]=\"child.disabled\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </button>\n }\n </li>\n }\n </ul>\n }\n </li>\n }\n }\n </ul>\n</nav>", styles: [".menu{background:var(--surface-card);border-radius:var(--border-radius);transition:width .3s cubic-bezier(.4,0,.2,1);position:relative;overflow:visible;width:100%;min-width:0}.menu.vertical{display:flex;flex-direction:column;min-width:0}.menu.horizontal{display:flex;flex-direction:row;align-items:center;padding:var(--spacing-sm);gap:var(--spacing-sm);overflow-x:auto}.menu.collapsed{width:64px;min-width:64px}.menu.compact .menu-link{padding:var(--spacing-xs) var(--spacing-sm);min-height:36px;gap:var(--spacing-xs)}.menu.compact .menu-link i{font-size:1rem}.menu.compact .menu-list{gap:2px}.menu.compact .submenu .menu-link{padding-left:calc(var(--spacing-sm) * 2);font-size:.9em}.menu.expanded .menu-link{padding:var(--spacing-md) var(--spacing-lg);min-height:52px;gap:var(--spacing-md)}.menu.expanded .menu-link i{font-size:1.4rem;width:1.4rem;height:1.4rem}.menu.expanded .menu-list{gap:var(--spacing-sm)}.menu.expanded .submenu .menu-link{padding-left:calc(var(--spacing-lg) * 2)}.menu-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:var(--spacing-xs);width:100%;min-width:0}.horizontal .menu-list{flex-direction:row;flex-wrap:nowrap;gap:var(--spacing-sm)}.menu-item{position:relative;width:100%;min-width:0}.horizontal .menu-item{width:auto}.menu-link{display:flex;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-sm) var(--spacing-md);color:var(--text-color);text-decoration:none;transition:all .2s ease;cursor:pointer;border-radius:var(--border-radius);min-height:44px;position:relative;width:100%;min-width:0;background:none;border:none;text-align:left;font:inherit}.menu-link:hover:not([aria-disabled=true]){background:var(--surface-hover);color:var(--primary-color);transform:translate(2px)}.menu-item.disabled .menu-link,.menu-link[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}.menu-item.disabled .menu-link:hover{background:transparent;color:var(--text-color);transform:none}.menu-link.active{background:var(--primary-color);color:var(--primary-color-text)}.menu.collapsed .menu-link{padding:var(--spacing-sm);justify-content:center}.menu-arrow{margin-left:auto;transition:transform .3s cubic-bezier(.4,0,.2,1);font-size:1.1rem;color:var(--text-color-secondary);flex-shrink:0}.menu-arrow.expanded{transform:rotate(-180deg)}.menu.collapsed .menu-arrow{display:none}.submenu{overflow:hidden;max-height:0;transition:max-height .3s cubic-bezier(.4,0,.2,1);background:var(--surface-ground);border-radius:var(--border-radius);margin:0 var(--spacing-sm);width:auto;min-width:0}.menu-item.expanded>.submenu{max-height:1000px;margin-top:var(--spacing-xs);margin-bottom:var(--spacing-xs)}.menu.collapsed .submenu{display:none}.submenu .menu-link{padding-left:calc(var(--spacing-md) * 2);font-size:.95em}.submenu .menu-link:hover{transform:translate(4px)}.menu-badge{background:var(--primary-color);color:var(--primary-color-text);padding:2px var(--spacing-xs);border-radius:var(--border-radius);font-size:var(--font-size-xs);margin-left:auto;flex-shrink:0}.menu-divider{height:1px;background:var(--surface-border);margin:var(--spacing-sm) var(--spacing-md);opacity:.5}.menu-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:opacity .3s ease;min-width:0;flex:1}.menu.collapsed .menu-label{opacity:0;width:0}.menu.collapsed psh-tooltip{display:block;width:100%}.menu-link i{font-size:1.2rem;flex-shrink:0;width:1.2rem;height:1.2rem;display:flex;align-items:center;justify-content:center}.menu-collapse-button{position:absolute;top:var(--spacing-sm);right:calc(-1 * var(--spacing-lg));width:28px;height:28px;background:var(--surface-card);border:1px solid var(--surface-border);border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;color:var(--text-color-secondary);z-index:2;box-shadow:var(--shadow-sm)}.menu-collapse-button:hover{background:var(--surface-hover);color:var(--primary-color);transform:scale(1.05);box-shadow:var(--shadow-md)}.menu-collapse-button:focus{outline:none;box-shadow:0 0 0 2px rgba(var(--primary-color-rgb),.2)}.menu-collapse-button i{font-size:1rem;transition:transform .3s ease}.menu.collapsed .menu-collapse-button i{transform:rotate(180deg)}@media(max-width:768px){.menu.horizontal{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;-ms-overflow-style:none}.menu.horizontal::-webkit-scrollbar{display:none}.menu.vertical:not(.collapsed){min-width:200px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: PshTooltipComponent, selector: "psh-tooltip", inputs: ["variant", "position", "showDelay", "hideDelay", "maxWidth", "autoFlip", "content", "disabled", "id"], outputs: ["shown", "hidden"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2178
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: PshMenuComponent, isStandalone: true, selector: "psh-menu", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, ariaLabels: { classPropertyName: "ariaLabels", publicName: "ariaLabels", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, expandedItemIds: { classPropertyName: "expandedItemIds", publicName: "expandedItemIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsed: "collapsedChange", expandedItemIds: "expandedItemIdsChange", itemClick: "itemClick", submenuToggle: "submenuToggle" }, ngImport: i0, template: "<nav\n class=\"menu\"\n [class.vertical]=\"mode() === 'vertical'\"\n [class.horizontal]=\"mode() === 'horizontal'\"\n [class.compact]=\"variant() === 'compact'\"\n [class.expanded]=\"variant() === 'expanded'\"\n [class.collapsed]=\"collapsed()\"\n role=\"navigation\"\n [attr.aria-label]=\"'Navigation menu'\"\n [attr.data-state]=\"state()\"\n>\n @if (collapsible()) {\n <button\n class=\"menu-collapse-button\"\n (click)=\"toggleCollapse()\"\n [attr.aria-expanded]=\"!collapsed()\"\n [attr.aria-label]=\"collapsed() ? ariaLabels()['expand'] : ariaLabels()['collapse']\"\n >\n <i class=\"ph ph-caret-left\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <ul class=\"menu-list\" role=\"menubar\">\n @for (item of items(); track item.id; let i = $index) {\n @if (item.divider) {\n <li class=\"menu-divider\" role=\"separator\"></li>\n } @else {\n <li\n class=\"menu-item\"\n [class.has-children]=\"item.children?.length\"\n [class.expanded]=\"isExpanded(item)\"\n [class.disabled]=\"item.disabled\"\n role=\"none\"\n >\n <ng-container\n *ngTemplateOutlet=\"itemTpl; context: { $implicit: item, index: i, isChild: false }\"\n ></ng-container>\n\n @if (item.children?.length) {\n <ul\n class=\"submenu\"\n role=\"menu\"\n [attr.aria-label]=\"item.content + ' submenu'\"\n >\n @for (child of item.children; track child.id) {\n <li class=\"menu-item\" role=\"none\">\n @if (child.path) {\n @if (showTooltip()) {\n <psh-tooltip [content]=\"child.content\" position=\"right\" [showDelay]=\"100\" [hideDelay]=\"0\">\n <a\n class=\"menu-link\"\n [attr.href]=\"child.path\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n title=\"\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n } @else {\n <span class=\"menu-child-dot\" aria-hidden=\"true\"></span>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </a>\n </psh-tooltip>\n } @else {\n <a\n class=\"menu-link\"\n [attr.href]=\"child.path\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </a>\n }\n } @else {\n @if (showTooltip()) {\n <psh-tooltip [content]=\"child.content\" position=\"right\" [showDelay]=\"100\" [hideDelay]=\"0\">\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n title=\"\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n [disabled]=\"child.disabled\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n } @else {\n <span class=\"menu-child-dot\" aria-hidden=\"true\"></span>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </button>\n </psh-tooltip>\n } @else {\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n [disabled]=\"child.disabled\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </button>\n }\n }\n </li>\n }\n </ul>\n }\n </li>\n }\n }\n </ul>\n</nav>\n\n<ng-template #itemTpl let-item let-index=\"index\" let-isChild=\"isChild\">\n @if (showTooltip()) {\n <psh-tooltip\n class=\"menu-tooltip-wrapper\"\n [content]=\"item.content\"\n position=\"right\"\n [showDelay]=\"300\"\n [hideDelay]=\"0\"\n >\n <ng-container\n *ngTemplateOutlet=\"itemContentTpl; context: { $implicit: item, index: index, isChild: isChild, withLabel: false }\"\n ></ng-container>\n </psh-tooltip>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"itemContentTpl; context: { $implicit: item, index: index, isChild: isChild, withLabel: true }\"\n ></ng-container>\n }\n</ng-template>\n\n<ng-template #itemContentTpl let-item let-index=\"index\" let-isChild=\"isChild\" let-withLabel=\"withLabel\">\n @if (item.path) {\n <a\n class=\"menu-link\"\n [attr.href]=\"item.path\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"handleItemClick(item, $event, isChild)\"\n (keydown)=\"handleKeyDown($event, item, index)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n @if (withLabel) {\n <span class=\"menu-label\">{{ item.content }}</span>\n }\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n @if (withLabel && item.children?.length) {\n <i\n class=\"ph ph-caret-down menu-arrow\"\n [class.expanded]=\"isExpanded(item)\"\n aria-hidden=\"true\"\n ></i>\n }\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"handleItemClick(item, $event, isChild)\"\n (keydown)=\"handleKeyDown($event, item, index)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n [disabled]=\"item.disabled\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n @if (withLabel) {\n <span class=\"menu-label\">{{ item.content }}</span>\n }\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n @if (withLabel && item.children?.length) {\n <i\n class=\"ph ph-caret-down menu-arrow\"\n [class.expanded]=\"isExpanded(item)\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n }\n</ng-template>\n", styles: [".menu{background:var(--surface-card);border-radius:var(--border-radius);transition:width .3s cubic-bezier(.4,0,.2,1);position:relative;overflow:visible;width:100%;min-width:0}.menu.vertical{display:flex;flex-direction:column;min-width:0}.menu.horizontal{display:flex;flex-direction:row;align-items:center;padding:var(--spacing-sm);gap:var(--spacing-sm);overflow-x:auto}.menu.collapsed{width:64px;min-width:64px}.menu.compact .menu-link{padding:var(--spacing-xs) var(--spacing-sm);min-height:36px;gap:var(--spacing-xs)}.menu.compact .menu-link i{font-size:1rem}.menu.compact .menu-list{gap:2px}.menu.compact .submenu .menu-link{padding-left:calc(var(--spacing-sm) * 2);font-size:.9em}.menu.expanded .menu-link{padding:var(--spacing-md) var(--spacing-lg);min-height:52px;gap:var(--spacing-md)}.menu.expanded .menu-link i{font-size:1.4rem;width:1.4rem;height:1.4rem}.menu.expanded .menu-list{gap:var(--spacing-sm)}.menu.expanded .submenu .menu-link{padding-left:calc(var(--spacing-lg) * 2)}.menu-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:var(--spacing-xs);width:100%;min-width:0}.horizontal .menu-list{flex-direction:row;flex-wrap:nowrap;gap:var(--spacing-sm)}.menu-item{position:relative;width:100%;min-width:0}.horizontal .menu-item{width:auto}.menu-link{display:flex;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-sm) var(--spacing-md);color:var(--text-color);text-decoration:none;transition:all .2s ease;cursor:pointer;border-radius:var(--border-radius);min-height:44px;position:relative;width:100%;min-width:0;background:none;border:none;text-align:left;font:inherit}.menu-link:hover:not([aria-disabled=true]){background:var(--surface-hover);color:var(--primary-color);transform:translate(2px)}.menu-item.disabled .menu-link,.menu-link[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}.menu-item.disabled .menu-link:hover{background:transparent;color:var(--text-color);transform:none}.menu-link.active{background:var(--primary-color);color:var(--primary-color-text)}.menu.collapsed .menu-link{padding:var(--spacing-sm);justify-content:center}.menu-arrow{margin-left:auto;transition:transform .3s cubic-bezier(.4,0,.2,1);font-size:1.1rem;color:var(--text-color-secondary);flex-shrink:0}.menu-arrow.expanded{transform:rotate(-180deg)}.menu.collapsed .menu-arrow{display:none}.submenu{overflow:hidden;max-height:0;transition:max-height .3s cubic-bezier(.4,0,.2,1);background:var(--surface-ground);border-radius:var(--border-radius);margin:0 var(--spacing-sm);width:auto;min-width:0}.menu-item.expanded>.submenu{max-height:1000px;margin-top:var(--spacing-xs);margin-bottom:var(--spacing-xs)}.menu.collapsed .submenu{margin:0 auto;background:transparent;border-radius:var(--border-radius);width:44px;padding:0;position:relative;overflow:visible;max-height:0;display:none}.menu.collapsed .menu-item.expanded>.submenu{display:block;max-height:none;margin:var(--spacing-xs) auto;padding:var(--spacing-xs) 0}.menu.collapsed .submenu:before{content:\"\";position:absolute;left:50%;top:0;bottom:0;width:2px;background:var(--surface-border);transform:translate(-50%);opacity:.6}.menu.collapsed .submenu .menu-item{position:relative;z-index:1}.menu.collapsed .submenu .menu-link{padding:0;justify-content:center;min-height:32px;width:32px;height:32px;margin:2px auto;background:var(--surface-card);border:1px solid var(--surface-border)}.menu.collapsed .submenu .menu-link:hover:not([aria-disabled=true]){background:var(--surface-hover);border-color:var(--primary-color);transform:none}.menu.collapsed .submenu .menu-link.active{background:var(--primary-color);color:var(--primary-color-text);border-color:var(--primary-color)}.menu.collapsed .submenu .menu-link i{font-size:.95rem;width:auto;height:auto}.menu.collapsed .submenu .menu-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;opacity:0}.menu.collapsed .submenu .menu-badge{position:absolute;top:-4px;right:-4px;margin:0;padding:0 4px;font-size:9px;line-height:14px;min-width:14px;height:14px;text-align:center;border-radius:7px}.menu.collapsed .submenu psh-tooltip{display:block;width:100%;position:relative;z-index:10}.menu.collapsed psh-tooltip .tooltip{z-index:1000}.menu-child-dot{width:8px;height:8px;border-radius:50%;background:var(--text-color-secondary);display:inline-block;flex-shrink:0;opacity:.7}.menu.collapsed .menu-item.expanded>psh-tooltip .menu-link,.menu.collapsed .menu-item.expanded>.menu-link{background:var(--surface-hover)}.menu.collapsed .menu-link:hover:not([aria-disabled=true]){transform:none}.submenu .menu-link{padding-left:calc(var(--spacing-md) * 2);font-size:.95em}.submenu .menu-link:hover{transform:translate(4px)}.menu-badge{background:var(--primary-color);color:var(--primary-color-text);padding:2px var(--spacing-xs);border-radius:var(--border-radius);font-size:var(--font-size-xs);margin-left:auto;flex-shrink:0}.menu-divider{height:1px;background:var(--surface-border);margin:var(--spacing-sm) var(--spacing-md);opacity:.5}.menu-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:opacity .3s ease;min-width:0;flex:1}.menu.collapsed .menu-label{opacity:0;width:0}.menu.collapsed psh-tooltip,.menu psh-tooltip.menu-tooltip-wrapper{display:block;width:100%}.submenu psh-tooltip.menu-tooltip-wrapper{display:block;width:100%}.menu-link i{font-size:1.2rem;flex-shrink:0;width:1.2rem;height:1.2rem;display:flex;align-items:center;justify-content:center}.menu-collapse-button{position:absolute;top:var(--spacing-sm);right:calc(-1 * var(--spacing-lg));width:28px;height:28px;background:var(--surface-card);border:1px solid var(--surface-border);border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;color:var(--text-color-secondary);z-index:2;box-shadow:var(--shadow-sm)}.menu-collapse-button:hover{background:var(--surface-hover);color:var(--primary-color);transform:scale(1.05);box-shadow:var(--shadow-md)}.menu-collapse-button:focus{outline:none;box-shadow:0 0 0 2px rgba(var(--primary-color-rgb),.2)}.menu-collapse-button i{font-size:1rem;transition:transform .3s ease}.menu.collapsed .menu-collapse-button i{transform:rotate(180deg)}@media(max-width:768px){.menu.horizontal{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;-ms-overflow-style:none}.menu.horizontal::-webkit-scrollbar{display:none}.menu.vertical:not(.collapsed){min-width:200px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PshTooltipComponent, selector: "psh-tooltip", inputs: ["variant", "position", "showDelay", "hideDelay", "maxWidth", "autoFlip", "content", "disabled", "id"], outputs: ["shown", "hidden"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2137
2179
  }
2138
2180
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PshMenuComponent, decorators: [{
2139
2181
  type: Component,
2140
- args: [{ selector: 'psh-menu', imports: [CommonModule, PshTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav \n class=\"menu\"\n [class.vertical]=\"mode() === 'vertical'\"\n [class.horizontal]=\"mode() === 'horizontal'\"\n [class.compact]=\"variant() === 'compact'\"\n [class.expanded]=\"variant() === 'expanded'\"\n [class.collapsed]=\"collapsed()\"\n role=\"navigation\"\n [attr.aria-label]=\"'Navigation menu'\"\n [attr.data-state]=\"state()\"\n>\n @if (collapsible()) {\n <button \n class=\"menu-collapse-button\"\n (click)=\"toggleCollapse()\"\n [attr.aria-expanded]=\"!collapsed()\"\n [attr.aria-label]=\"collapsed() ? ariaLabels()['expand'] : ariaLabels()['collapse']\"\n >\n <i class=\"ph ph-caret-left\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <ul class=\"menu-list\" role=\"menubar\">\n @for (item of items(); track item.id; let i = $index) {\n @if (item.divider) {\n <li class=\"menu-divider\" role=\"separator\"></li>\n } @else {\n <li\n class=\"menu-item\"\n [class.has-children]=\"item.children?.length\"\n [class.expanded]=\"isExpanded(item)\"\n [class.disabled]=\"item.disabled\"\n role=\"none\"\n >\n @if (item.path) {\n @if (showTooltip()) {\n <psh-tooltip [content]=\"item.content\" position=\"right\" [showDelay]=\"100\" [hideDelay]=\"0\">\n <a\n class=\"menu-link\"\n [attr.href]=\"item.path\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"toggleItem(item, $event)\"\n (keydown)=\"handleKeyDown($event, item, i)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n </a>\n </psh-tooltip>\n } @else {\n <a\n class=\"menu-link\"\n [attr.href]=\"item.path\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"toggleItem(item, $event)\"\n (keydown)=\"handleKeyDown($event, item, i)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ item.content }}</span>\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n @if (item.children?.length) {\n <i\n class=\"ph ph-caret-down menu-arrow\"\n [class.expanded]=\"isExpanded(item)\"\n aria-hidden=\"true\"\n ></i>\n }\n </a>\n }\n } @else {\n @if (showTooltip()) {\n <psh-tooltip [content]=\"item.content\" position=\"right\" [showDelay]=\"100\" [hideDelay]=\"0\">\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"toggleItem(item, $event)\"\n (keydown)=\"handleKeyDown($event, item, i)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n [disabled]=\"item.disabled\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n </button>\n </psh-tooltip>\n } @else {\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"toggleItem(item, $event)\"\n (keydown)=\"handleKeyDown($event, item, i)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n [disabled]=\"item.disabled\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ item.content }}</span>\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n @if (item.children?.length) {\n <i\n class=\"ph ph-caret-down menu-arrow\"\n [class.expanded]=\"isExpanded(item)\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n }\n }\n\n @if (item.children?.length) {\n <ul\n class=\"submenu\"\n role=\"menu\"\n [attr.aria-label]=\"item.content + ' submenu'\"\n >\n @for (child of item.children; track child.id) {\n <li class=\"menu-item\" role=\"none\">\n @if (child.path) {\n <a\n class=\"menu-link\"\n [attr.href]=\"child.path\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n [disabled]=\"child.disabled\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </button>\n }\n </li>\n }\n </ul>\n }\n </li>\n }\n }\n </ul>\n</nav>", styles: [".menu{background:var(--surface-card);border-radius:var(--border-radius);transition:width .3s cubic-bezier(.4,0,.2,1);position:relative;overflow:visible;width:100%;min-width:0}.menu.vertical{display:flex;flex-direction:column;min-width:0}.menu.horizontal{display:flex;flex-direction:row;align-items:center;padding:var(--spacing-sm);gap:var(--spacing-sm);overflow-x:auto}.menu.collapsed{width:64px;min-width:64px}.menu.compact .menu-link{padding:var(--spacing-xs) var(--spacing-sm);min-height:36px;gap:var(--spacing-xs)}.menu.compact .menu-link i{font-size:1rem}.menu.compact .menu-list{gap:2px}.menu.compact .submenu .menu-link{padding-left:calc(var(--spacing-sm) * 2);font-size:.9em}.menu.expanded .menu-link{padding:var(--spacing-md) var(--spacing-lg);min-height:52px;gap:var(--spacing-md)}.menu.expanded .menu-link i{font-size:1.4rem;width:1.4rem;height:1.4rem}.menu.expanded .menu-list{gap:var(--spacing-sm)}.menu.expanded .submenu .menu-link{padding-left:calc(var(--spacing-lg) * 2)}.menu-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:var(--spacing-xs);width:100%;min-width:0}.horizontal .menu-list{flex-direction:row;flex-wrap:nowrap;gap:var(--spacing-sm)}.menu-item{position:relative;width:100%;min-width:0}.horizontal .menu-item{width:auto}.menu-link{display:flex;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-sm) var(--spacing-md);color:var(--text-color);text-decoration:none;transition:all .2s ease;cursor:pointer;border-radius:var(--border-radius);min-height:44px;position:relative;width:100%;min-width:0;background:none;border:none;text-align:left;font:inherit}.menu-link:hover:not([aria-disabled=true]){background:var(--surface-hover);color:var(--primary-color);transform:translate(2px)}.menu-item.disabled .menu-link,.menu-link[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}.menu-item.disabled .menu-link:hover{background:transparent;color:var(--text-color);transform:none}.menu-link.active{background:var(--primary-color);color:var(--primary-color-text)}.menu.collapsed .menu-link{padding:var(--spacing-sm);justify-content:center}.menu-arrow{margin-left:auto;transition:transform .3s cubic-bezier(.4,0,.2,1);font-size:1.1rem;color:var(--text-color-secondary);flex-shrink:0}.menu-arrow.expanded{transform:rotate(-180deg)}.menu.collapsed .menu-arrow{display:none}.submenu{overflow:hidden;max-height:0;transition:max-height .3s cubic-bezier(.4,0,.2,1);background:var(--surface-ground);border-radius:var(--border-radius);margin:0 var(--spacing-sm);width:auto;min-width:0}.menu-item.expanded>.submenu{max-height:1000px;margin-top:var(--spacing-xs);margin-bottom:var(--spacing-xs)}.menu.collapsed .submenu{display:none}.submenu .menu-link{padding-left:calc(var(--spacing-md) * 2);font-size:.95em}.submenu .menu-link:hover{transform:translate(4px)}.menu-badge{background:var(--primary-color);color:var(--primary-color-text);padding:2px var(--spacing-xs);border-radius:var(--border-radius);font-size:var(--font-size-xs);margin-left:auto;flex-shrink:0}.menu-divider{height:1px;background:var(--surface-border);margin:var(--spacing-sm) var(--spacing-md);opacity:.5}.menu-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:opacity .3s ease;min-width:0;flex:1}.menu.collapsed .menu-label{opacity:0;width:0}.menu.collapsed psh-tooltip{display:block;width:100%}.menu-link i{font-size:1.2rem;flex-shrink:0;width:1.2rem;height:1.2rem;display:flex;align-items:center;justify-content:center}.menu-collapse-button{position:absolute;top:var(--spacing-sm);right:calc(-1 * var(--spacing-lg));width:28px;height:28px;background:var(--surface-card);border:1px solid var(--surface-border);border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;color:var(--text-color-secondary);z-index:2;box-shadow:var(--shadow-sm)}.menu-collapse-button:hover{background:var(--surface-hover);color:var(--primary-color);transform:scale(1.05);box-shadow:var(--shadow-md)}.menu-collapse-button:focus{outline:none;box-shadow:0 0 0 2px rgba(var(--primary-color-rgb),.2)}.menu-collapse-button i{font-size:1rem;transition:transform .3s ease}.menu.collapsed .menu-collapse-button i{transform:rotate(180deg)}@media(max-width:768px){.menu.horizontal{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;-ms-overflow-style:none}.menu.horizontal::-webkit-scrollbar{display:none}.menu.vertical:not(.collapsed){min-width:200px}}\n"] }]
2182
+ args: [{ selector: 'psh-menu', imports: [CommonModule, PshTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav\n class=\"menu\"\n [class.vertical]=\"mode() === 'vertical'\"\n [class.horizontal]=\"mode() === 'horizontal'\"\n [class.compact]=\"variant() === 'compact'\"\n [class.expanded]=\"variant() === 'expanded'\"\n [class.collapsed]=\"collapsed()\"\n role=\"navigation\"\n [attr.aria-label]=\"'Navigation menu'\"\n [attr.data-state]=\"state()\"\n>\n @if (collapsible()) {\n <button\n class=\"menu-collapse-button\"\n (click)=\"toggleCollapse()\"\n [attr.aria-expanded]=\"!collapsed()\"\n [attr.aria-label]=\"collapsed() ? ariaLabels()['expand'] : ariaLabels()['collapse']\"\n >\n <i class=\"ph ph-caret-left\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <ul class=\"menu-list\" role=\"menubar\">\n @for (item of items(); track item.id; let i = $index) {\n @if (item.divider) {\n <li class=\"menu-divider\" role=\"separator\"></li>\n } @else {\n <li\n class=\"menu-item\"\n [class.has-children]=\"item.children?.length\"\n [class.expanded]=\"isExpanded(item)\"\n [class.disabled]=\"item.disabled\"\n role=\"none\"\n >\n <ng-container\n *ngTemplateOutlet=\"itemTpl; context: { $implicit: item, index: i, isChild: false }\"\n ></ng-container>\n\n @if (item.children?.length) {\n <ul\n class=\"submenu\"\n role=\"menu\"\n [attr.aria-label]=\"item.content + ' submenu'\"\n >\n @for (child of item.children; track child.id) {\n <li class=\"menu-item\" role=\"none\">\n @if (child.path) {\n @if (showTooltip()) {\n <psh-tooltip [content]=\"child.content\" position=\"right\" [showDelay]=\"100\" [hideDelay]=\"0\">\n <a\n class=\"menu-link\"\n [attr.href]=\"child.path\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n title=\"\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n } @else {\n <span class=\"menu-child-dot\" aria-hidden=\"true\"></span>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </a>\n </psh-tooltip>\n } @else {\n <a\n class=\"menu-link\"\n [attr.href]=\"child.path\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </a>\n }\n } @else {\n @if (showTooltip()) {\n <psh-tooltip [content]=\"child.content\" position=\"right\" [showDelay]=\"100\" [hideDelay]=\"0\">\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n title=\"\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n [disabled]=\"child.disabled\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n } @else {\n <span class=\"menu-child-dot\" aria-hidden=\"true\"></span>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </button>\n </psh-tooltip>\n } @else {\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"child.id\"\n [class.active]=\"child.active\"\n [attr.aria-disabled]=\"child.disabled\"\n [attr.aria-label]=\"getAriaLabel(child)\"\n (click)=\"toggleItem(child, $event)\"\n (keydown.enter)=\"toggleItem(child, $event)\"\n (keydown.space)=\"toggleItem(child, $event)\"\n role=\"menuitem\"\n [attr.tabindex]=\"child.disabled ? -1 : 0\"\n [disabled]=\"child.disabled\"\n >\n @if (child.icon) {\n <i class=\"ph ph-{{ child.icon }}\" aria-hidden=\"true\"></i>\n }\n <span class=\"menu-label\">{{ child.content }}</span>\n @if (child.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ child.badge }}</span>\n }\n </button>\n }\n }\n </li>\n }\n </ul>\n }\n </li>\n }\n }\n </ul>\n</nav>\n\n<ng-template #itemTpl let-item let-index=\"index\" let-isChild=\"isChild\">\n @if (showTooltip()) {\n <psh-tooltip\n class=\"menu-tooltip-wrapper\"\n [content]=\"item.content\"\n position=\"right\"\n [showDelay]=\"300\"\n [hideDelay]=\"0\"\n >\n <ng-container\n *ngTemplateOutlet=\"itemContentTpl; context: { $implicit: item, index: index, isChild: isChild, withLabel: false }\"\n ></ng-container>\n </psh-tooltip>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"itemContentTpl; context: { $implicit: item, index: index, isChild: isChild, withLabel: true }\"\n ></ng-container>\n }\n</ng-template>\n\n<ng-template #itemContentTpl let-item let-index=\"index\" let-isChild=\"isChild\" let-withLabel=\"withLabel\">\n @if (item.path) {\n <a\n class=\"menu-link\"\n [attr.href]=\"item.path\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"handleItemClick(item, $event, isChild)\"\n (keydown)=\"handleKeyDown($event, item, index)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n @if (withLabel) {\n <span class=\"menu-label\">{{ item.content }}</span>\n }\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n @if (withLabel && item.children?.length) {\n <i\n class=\"ph ph-caret-down menu-arrow\"\n [class.expanded]=\"isExpanded(item)\"\n aria-hidden=\"true\"\n ></i>\n }\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"menu-link\"\n [attr.data-menu-item-id]=\"item.id\"\n [class.active]=\"item.active\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.aria-expanded]=\"item.children?.length ? isExpanded(item) : null\"\n [attr.aria-label]=\"getAriaLabel(item)\"\n (click)=\"handleItemClick(item, $event, isChild)\"\n (keydown)=\"handleKeyDown($event, item, index)\"\n role=\"menuitem\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n [disabled]=\"item.disabled\"\n >\n @if (item.icon) {\n <i class=\"ph ph-{{ item.icon }}\" aria-hidden=\"true\"></i>\n }\n @if (withLabel) {\n <span class=\"menu-label\">{{ item.content }}</span>\n }\n @if (item.badge) {\n <span class=\"menu-badge\" role=\"status\">{{ item.badge }}</span>\n }\n @if (withLabel && item.children?.length) {\n <i\n class=\"ph ph-caret-down menu-arrow\"\n [class.expanded]=\"isExpanded(item)\"\n aria-hidden=\"true\"\n ></i>\n }\n </button>\n }\n</ng-template>\n", styles: [".menu{background:var(--surface-card);border-radius:var(--border-radius);transition:width .3s cubic-bezier(.4,0,.2,1);position:relative;overflow:visible;width:100%;min-width:0}.menu.vertical{display:flex;flex-direction:column;min-width:0}.menu.horizontal{display:flex;flex-direction:row;align-items:center;padding:var(--spacing-sm);gap:var(--spacing-sm);overflow-x:auto}.menu.collapsed{width:64px;min-width:64px}.menu.compact .menu-link{padding:var(--spacing-xs) var(--spacing-sm);min-height:36px;gap:var(--spacing-xs)}.menu.compact .menu-link i{font-size:1rem}.menu.compact .menu-list{gap:2px}.menu.compact .submenu .menu-link{padding-left:calc(var(--spacing-sm) * 2);font-size:.9em}.menu.expanded .menu-link{padding:var(--spacing-md) var(--spacing-lg);min-height:52px;gap:var(--spacing-md)}.menu.expanded .menu-link i{font-size:1.4rem;width:1.4rem;height:1.4rem}.menu.expanded .menu-list{gap:var(--spacing-sm)}.menu.expanded .submenu .menu-link{padding-left:calc(var(--spacing-lg) * 2)}.menu-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:var(--spacing-xs);width:100%;min-width:0}.horizontal .menu-list{flex-direction:row;flex-wrap:nowrap;gap:var(--spacing-sm)}.menu-item{position:relative;width:100%;min-width:0}.horizontal .menu-item{width:auto}.menu-link{display:flex;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-sm) var(--spacing-md);color:var(--text-color);text-decoration:none;transition:all .2s ease;cursor:pointer;border-radius:var(--border-radius);min-height:44px;position:relative;width:100%;min-width:0;background:none;border:none;text-align:left;font:inherit}.menu-link:hover:not([aria-disabled=true]){background:var(--surface-hover);color:var(--primary-color);transform:translate(2px)}.menu-item.disabled .menu-link,.menu-link[aria-disabled=true]{opacity:.5;cursor:not-allowed;pointer-events:none}.menu-item.disabled .menu-link:hover{background:transparent;color:var(--text-color);transform:none}.menu-link.active{background:var(--primary-color);color:var(--primary-color-text)}.menu.collapsed .menu-link{padding:var(--spacing-sm);justify-content:center}.menu-arrow{margin-left:auto;transition:transform .3s cubic-bezier(.4,0,.2,1);font-size:1.1rem;color:var(--text-color-secondary);flex-shrink:0}.menu-arrow.expanded{transform:rotate(-180deg)}.menu.collapsed .menu-arrow{display:none}.submenu{overflow:hidden;max-height:0;transition:max-height .3s cubic-bezier(.4,0,.2,1);background:var(--surface-ground);border-radius:var(--border-radius);margin:0 var(--spacing-sm);width:auto;min-width:0}.menu-item.expanded>.submenu{max-height:1000px;margin-top:var(--spacing-xs);margin-bottom:var(--spacing-xs)}.menu.collapsed .submenu{margin:0 auto;background:transparent;border-radius:var(--border-radius);width:44px;padding:0;position:relative;overflow:visible;max-height:0;display:none}.menu.collapsed .menu-item.expanded>.submenu{display:block;max-height:none;margin:var(--spacing-xs) auto;padding:var(--spacing-xs) 0}.menu.collapsed .submenu:before{content:\"\";position:absolute;left:50%;top:0;bottom:0;width:2px;background:var(--surface-border);transform:translate(-50%);opacity:.6}.menu.collapsed .submenu .menu-item{position:relative;z-index:1}.menu.collapsed .submenu .menu-link{padding:0;justify-content:center;min-height:32px;width:32px;height:32px;margin:2px auto;background:var(--surface-card);border:1px solid var(--surface-border)}.menu.collapsed .submenu .menu-link:hover:not([aria-disabled=true]){background:var(--surface-hover);border-color:var(--primary-color);transform:none}.menu.collapsed .submenu .menu-link.active{background:var(--primary-color);color:var(--primary-color-text);border-color:var(--primary-color)}.menu.collapsed .submenu .menu-link i{font-size:.95rem;width:auto;height:auto}.menu.collapsed .submenu .menu-label{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;opacity:0}.menu.collapsed .submenu .menu-badge{position:absolute;top:-4px;right:-4px;margin:0;padding:0 4px;font-size:9px;line-height:14px;min-width:14px;height:14px;text-align:center;border-radius:7px}.menu.collapsed .submenu psh-tooltip{display:block;width:100%;position:relative;z-index:10}.menu.collapsed psh-tooltip .tooltip{z-index:1000}.menu-child-dot{width:8px;height:8px;border-radius:50%;background:var(--text-color-secondary);display:inline-block;flex-shrink:0;opacity:.7}.menu.collapsed .menu-item.expanded>psh-tooltip .menu-link,.menu.collapsed .menu-item.expanded>.menu-link{background:var(--surface-hover)}.menu.collapsed .menu-link:hover:not([aria-disabled=true]){transform:none}.submenu .menu-link{padding-left:calc(var(--spacing-md) * 2);font-size:.95em}.submenu .menu-link:hover{transform:translate(4px)}.menu-badge{background:var(--primary-color);color:var(--primary-color-text);padding:2px var(--spacing-xs);border-radius:var(--border-radius);font-size:var(--font-size-xs);margin-left:auto;flex-shrink:0}.menu-divider{height:1px;background:var(--surface-border);margin:var(--spacing-sm) var(--spacing-md);opacity:.5}.menu-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:opacity .3s ease;min-width:0;flex:1}.menu.collapsed .menu-label{opacity:0;width:0}.menu.collapsed psh-tooltip,.menu psh-tooltip.menu-tooltip-wrapper{display:block;width:100%}.submenu psh-tooltip.menu-tooltip-wrapper{display:block;width:100%}.menu-link i{font-size:1.2rem;flex-shrink:0;width:1.2rem;height:1.2rem;display:flex;align-items:center;justify-content:center}.menu-collapse-button{position:absolute;top:var(--spacing-sm);right:calc(-1 * var(--spacing-lg));width:28px;height:28px;background:var(--surface-card);border:1px solid var(--surface-border);border-radius:var(--border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;color:var(--text-color-secondary);z-index:2;box-shadow:var(--shadow-sm)}.menu-collapse-button:hover{background:var(--surface-hover);color:var(--primary-color);transform:scale(1.05);box-shadow:var(--shadow-md)}.menu-collapse-button:focus{outline:none;box-shadow:0 0 0 2px rgba(var(--primary-color-rgb),.2)}.menu-collapse-button i{font-size:1rem;transition:transform .3s ease}.menu.collapsed .menu-collapse-button i{transform:rotate(180deg)}@media(max-width:768px){.menu.horizontal{overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;-ms-overflow-style:none}.menu.horizontal::-webkit-scrollbar{display:none}.menu.vertical:not(.collapsed){min-width:200px}}\n"] }]
2141
2183
  }], ctorParameters: () => [], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], ariaLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabels", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }, { type: i0.Output, args: ["collapsedChange"] }], expandedItemIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedItemIds", required: false }] }, { type: i0.Output, args: ["expandedItemIdsChange"] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], submenuToggle: [{ type: i0.Output, args: ["submenuToggle"] }] } });
2142
2184
 
2143
2185
  /**