ps-helix 5.0.0 → 5.1.1
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 +3 -3
- package/fesm2022/ps-helix.mjs +3 -14
- package/fesm2022/ps-helix.mjs.map +1 -1
- package/package.json +1 -1
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
|
-
[](https://www.npmjs.com/package/ps-helix)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://angular.dev/)
|
|
8
8
|
[](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.
|
|
109
|
+
"ps-helix": "^5.1.0"
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
```
|
|
@@ -1182,7 +1182,7 @@ Copyright (c) 2025 PACK Solutions
|
|
|
1182
1182
|
|
|
1183
1183
|
---
|
|
1184
1184
|
|
|
1185
|
-
**Version**: 5.
|
|
1185
|
+
**Version**: 5.1.0
|
|
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
|
package/fesm2022/ps-helix.mjs
CHANGED
|
@@ -1961,11 +1961,6 @@ class PshMenuComponent {
|
|
|
1961
1961
|
this.expandedItemsSet = computed(() => new Set(this.expandedItemIds()), ...(ngDevMode ? [{ debugName: "expandedItemsSet" }] : /* istanbul ignore next */ []));
|
|
1962
1962
|
this.state = computed(() => this.getState(), ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
|
|
1963
1963
|
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
1964
|
}
|
|
1970
1965
|
getState() {
|
|
1971
1966
|
if (this.collapsed())
|
|
@@ -1993,11 +1988,9 @@ class PshMenuComponent {
|
|
|
1993
1988
|
}
|
|
1994
1989
|
}
|
|
1995
1990
|
isExpanded(item) {
|
|
1996
|
-
return
|
|
1991
|
+
return this.expandedItemsSet().has(item.id);
|
|
1997
1992
|
}
|
|
1998
1993
|
expandItem(itemId) {
|
|
1999
|
-
if (this.collapsed())
|
|
2000
|
-
return;
|
|
2001
1994
|
const current = this.expandedItemIds();
|
|
2002
1995
|
if (!current.includes(itemId)) {
|
|
2003
1996
|
this.expandedItemIds.set([...current, itemId]);
|
|
@@ -2010,8 +2003,6 @@ class PshMenuComponent {
|
|
|
2010
2003
|
}
|
|
2011
2004
|
}
|
|
2012
2005
|
toggleItemExpansion(itemId) {
|
|
2013
|
-
if (this.collapsed())
|
|
2014
|
-
return;
|
|
2015
2006
|
const current = this.expandedItemIds();
|
|
2016
2007
|
if (current.includes(itemId)) {
|
|
2017
2008
|
this.expandedItemIds.set(current.filter(id => id !== itemId));
|
|
@@ -2021,8 +2012,6 @@ class PshMenuComponent {
|
|
|
2021
2012
|
}
|
|
2022
2013
|
}
|
|
2023
2014
|
expandAll() {
|
|
2024
|
-
if (this.collapsed())
|
|
2025
|
-
return;
|
|
2026
2015
|
const allIds = this.collectItemIdsWithChildren(this.items());
|
|
2027
2016
|
this.expandedItemIds.set(allIds);
|
|
2028
2017
|
}
|
|
@@ -2133,11 +2122,11 @@ class PshMenuComponent {
|
|
|
2133
2122
|
}
|
|
2134
2123
|
}
|
|
2135
2124
|
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 }); }
|
|
2125
|
+
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 @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>", 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{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 }); }
|
|
2137
2126
|
}
|
|
2138
2127
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PshMenuComponent, decorators: [{
|
|
2139
2128
|
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"] }]
|
|
2129
|
+
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 @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>", 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{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
2130
|
}], 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
2131
|
|
|
2143
2132
|
/**
|