@kanso-protocol/user-menu 0.5.3 → 1.0.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.
@@ -90,7 +90,7 @@ class KpUserMenuComponent {
90
90
  <svg kpMenuItemIcon viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M9 12h12l-3-3m0 6 3-3M15 17v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v1"/></svg>
91
91
  </kp-menu-item>
92
92
  </div>
93
- `, isInline: true, styles: [":host{box-sizing:border-box;display:flex;flex-direction:column;width:var(--kp-user-menu-w, 280px);padding:4px 0;border-radius:12px;background:var(--kp-color-surface-base);border:1px solid var(--kp-color-border-default);box-shadow:var(--kp-elevation-overlay);font-family:var(--kp-font-family-sans, \"Onest\", system-ui, sans-serif)}:host(.kp-user-menu--sm){--kp-user-menu-w: 240px;--kp-user-menu-pad: 8px}:host(.kp-user-menu--md){--kp-user-menu-w: 280px;--kp-user-menu-pad: 12px}.kp-user-menu__info{display:flex;align-items:center;gap:12px;padding:var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px)}.kp-user-menu__text{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}.kp-user-menu__name-row{display:inline-flex;align-items:center;gap:6px}.kp-user-menu__name{font-size:14px;font-weight:500;color:var(--kp-color-text-strong)}.kp-user-menu__plan{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;background:var(--kp-color-primary-default-bg-rest);color:var(--kp-color-foreground-on-saturated);font-size:11px;font-weight:600;line-height:1}.kp-user-menu__email{font-size:12px;color:var(--kp-color-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kp-user-menu__divider{height:1px;background:var(--kp-color-surface-strong)}.kp-user-menu__group{padding:4px;display:flex;flex-direction:column;gap:0}.kp-user-menu__theme{display:flex;align-items:center;gap:8px;padding:var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px)}.kp-user-menu__theme-label{flex:1 1 auto;font-size:14px;color:var(--kp-color-text-default)}.kp-user-menu__row{all:unset;display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;font-size:13px;color:var(--kp-color-text-default);cursor:pointer;transition:background var(--kp-motion-duration-fast) ease}.kp-user-menu__row:hover{background:var(--kp-color-surface-subtle)}.kp-user-menu__row-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;color:var(--kp-color-text-muted)}.kp-user-menu__row-icon svg{width:100%;height:100%}.kp-user-menu__row--danger,.kp-user-menu__row--danger .kp-user-menu__row-icon{color:var(--kp-color-menu-item-fg-danger-rest)}.kp-user-menu__row--danger:hover{background:var(--kp-color-danger-subtle-bg-rest);color:var(--kp-color-menu-item-fg-danger-hover)}\n"], dependencies: [{ kind: "component", type: KpAvatarComponent, selector: "kp-avatar", inputs: ["size", "shape", "appearance", "initials", "src", "alt", "showStatus", "status", "showRing", "ariaLabelOverride"] }, { kind: "component", type: KpMenuItemComponent, selector: "kp-menu-item", inputs: ["size", "label", "description", "shortcut", "hasChevron", "selected", "danger", "disabled", "forceState"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
93
+ `, isInline: true, styles: [":host{box-sizing:border-box;display:flex;flex-direction:column;width:var(--kp-user-menu-w, 280px);padding:4px 0;border-radius:12px;background:var(--kp-color-popover-bg);border:1px solid var(--kp-color-popover-border);box-shadow:var(--kp-elevation-overlay);font-family:var(--kp-font-family-sans, \"Onest\", system-ui, sans-serif)}:host(.kp-user-menu--sm){--kp-user-menu-w: 240px;--kp-user-menu-pad: 8px}:host(.kp-user-menu--md){--kp-user-menu-w: 280px;--kp-user-menu-pad: 12px}.kp-user-menu__info{display:flex;align-items:center;gap:12px;padding:var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px)}.kp-user-menu__text{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}.kp-user-menu__name-row{display:inline-flex;align-items:center;gap:6px}.kp-user-menu__name{font-size:14px;font-weight:500;color:var(--kp-color-text-strong)}.kp-user-menu__plan{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;background:var(--kp-color-primary-default-bg-rest);color:var(--kp-color-foreground-on-saturated);font-size:11px;font-weight:600;line-height:1}.kp-user-menu__email{font-size:12px;color:var(--kp-color-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kp-user-menu__divider{height:1px;background:var(--kp-color-surface-strong)}.kp-user-menu__group{padding:4px;display:flex;flex-direction:column;gap:0}.kp-user-menu__theme{display:flex;align-items:center;gap:8px;padding:var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px)}.kp-user-menu__theme-label{flex:1 1 auto;font-size:14px;color:var(--kp-color-text-default)}.kp-user-menu__row{all:unset;display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;font-size:13px;color:var(--kp-color-text-default);cursor:pointer;transition:background var(--kp-motion-duration-fast) ease}.kp-user-menu__row:hover{background:var(--kp-color-surface-muted)}.kp-user-menu__row-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;color:var(--kp-color-text-muted)}.kp-user-menu__row-icon svg{width:100%;height:100%}.kp-user-menu__row--danger,.kp-user-menu__row--danger .kp-user-menu__row-icon{color:var(--kp-color-menu-item-fg-danger-rest)}.kp-user-menu__row--danger:hover{background:var(--kp-color-danger-subtle-bg-rest);color:var(--kp-color-menu-item-fg-danger-hover)}\n"], dependencies: [{ kind: "component", type: KpAvatarComponent, selector: "kp-avatar", inputs: ["size", "shape", "appearance", "initials", "src", "alt", "showStatus", "status", "showRing", "ariaLabelOverride"] }, { kind: "component", type: KpMenuItemComponent, selector: "kp-menu-item", inputs: ["size", "label", "description", "shortcut", "hasChevron", "selected", "danger", "disabled", "forceState"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
94
94
  }
95
95
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImport: i0, type: KpUserMenuComponent, decorators: [{
96
96
  type: Component,
@@ -138,7 +138,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.7", ngImpor
138
138
  <svg kpMenuItemIcon viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M9 12h12l-3-3m0 6 3-3M15 17v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v1"/></svg>
139
139
  </kp-menu-item>
140
140
  </div>
141
- `, styles: [":host{box-sizing:border-box;display:flex;flex-direction:column;width:var(--kp-user-menu-w, 280px);padding:4px 0;border-radius:12px;background:var(--kp-color-surface-base);border:1px solid var(--kp-color-border-default);box-shadow:var(--kp-elevation-overlay);font-family:var(--kp-font-family-sans, \"Onest\", system-ui, sans-serif)}:host(.kp-user-menu--sm){--kp-user-menu-w: 240px;--kp-user-menu-pad: 8px}:host(.kp-user-menu--md){--kp-user-menu-w: 280px;--kp-user-menu-pad: 12px}.kp-user-menu__info{display:flex;align-items:center;gap:12px;padding:var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px)}.kp-user-menu__text{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}.kp-user-menu__name-row{display:inline-flex;align-items:center;gap:6px}.kp-user-menu__name{font-size:14px;font-weight:500;color:var(--kp-color-text-strong)}.kp-user-menu__plan{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;background:var(--kp-color-primary-default-bg-rest);color:var(--kp-color-foreground-on-saturated);font-size:11px;font-weight:600;line-height:1}.kp-user-menu__email{font-size:12px;color:var(--kp-color-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kp-user-menu__divider{height:1px;background:var(--kp-color-surface-strong)}.kp-user-menu__group{padding:4px;display:flex;flex-direction:column;gap:0}.kp-user-menu__theme{display:flex;align-items:center;gap:8px;padding:var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px)}.kp-user-menu__theme-label{flex:1 1 auto;font-size:14px;color:var(--kp-color-text-default)}.kp-user-menu__row{all:unset;display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;font-size:13px;color:var(--kp-color-text-default);cursor:pointer;transition:background var(--kp-motion-duration-fast) ease}.kp-user-menu__row:hover{background:var(--kp-color-surface-subtle)}.kp-user-menu__row-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;color:var(--kp-color-text-muted)}.kp-user-menu__row-icon svg{width:100%;height:100%}.kp-user-menu__row--danger,.kp-user-menu__row--danger .kp-user-menu__row-icon{color:var(--kp-color-menu-item-fg-danger-rest)}.kp-user-menu__row--danger:hover{background:var(--kp-color-danger-subtle-bg-rest);color:var(--kp-color-menu-item-fg-danger-hover)}\n"] }]
141
+ `, styles: [":host{box-sizing:border-box;display:flex;flex-direction:column;width:var(--kp-user-menu-w, 280px);padding:4px 0;border-radius:12px;background:var(--kp-color-popover-bg);border:1px solid var(--kp-color-popover-border);box-shadow:var(--kp-elevation-overlay);font-family:var(--kp-font-family-sans, \"Onest\", system-ui, sans-serif)}:host(.kp-user-menu--sm){--kp-user-menu-w: 240px;--kp-user-menu-pad: 8px}:host(.kp-user-menu--md){--kp-user-menu-w: 280px;--kp-user-menu-pad: 12px}.kp-user-menu__info{display:flex;align-items:center;gap:12px;padding:var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px)}.kp-user-menu__text{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}.kp-user-menu__name-row{display:inline-flex;align-items:center;gap:6px}.kp-user-menu__name{font-size:14px;font-weight:500;color:var(--kp-color-text-strong)}.kp-user-menu__plan{display:inline-flex;align-items:center;padding:2px 8px;border-radius:999px;background:var(--kp-color-primary-default-bg-rest);color:var(--kp-color-foreground-on-saturated);font-size:11px;font-weight:600;line-height:1}.kp-user-menu__email{font-size:12px;color:var(--kp-color-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.kp-user-menu__divider{height:1px;background:var(--kp-color-surface-strong)}.kp-user-menu__group{padding:4px;display:flex;flex-direction:column;gap:0}.kp-user-menu__theme{display:flex;align-items:center;gap:8px;padding:var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px)}.kp-user-menu__theme-label{flex:1 1 auto;font-size:14px;color:var(--kp-color-text-default)}.kp-user-menu__row{all:unset;display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;font-size:13px;color:var(--kp-color-text-default);cursor:pointer;transition:background var(--kp-motion-duration-fast) ease}.kp-user-menu__row:hover{background:var(--kp-color-surface-muted)}.kp-user-menu__row-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;color:var(--kp-color-text-muted)}.kp-user-menu__row-icon svg{width:100%;height:100%}.kp-user-menu__row--danger,.kp-user-menu__row--danger .kp-user-menu__row-icon{color:var(--kp-color-menu-item-fg-danger-rest)}.kp-user-menu__row--danger:hover{background:var(--kp-color-danger-subtle-bg-rest);color:var(--kp-color-menu-item-fg-danger-hover)}\n"] }]
142
142
  }], propDecorators: { size: [{
143
143
  type: Input
144
144
  }], userName: [{
@@ -1 +1 @@
1
- {"version":3,"file":"kanso-protocol-user-menu.mjs","sources":["../../../../../packages/patterns/user-menu/src/user-menu.component.ts","../../../../../packages/patterns/user-menu/src/kanso-protocol-user-menu.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n Output,\n} from '@angular/core';\nimport { KpAvatarComponent } from '@kanso-protocol/avatar';\nimport { KpMenuItemComponent } from '@kanso-protocol/menu';\n\nexport type KpUserMenuSize = 'sm' | 'md';\n\nexport interface KpUserMenuItem {\n id: string;\n label: string;\n danger?: boolean;\n}\n\n/**\n * Kanso Protocol — UserMenu\n *\n * Preset dropdown shown from the user Avatar in Header. User block\n * at top, main menu, optional theme toggle + help links, Sign out.\n *\n * Slots:\n * - `[kpUserMenuItems]` — main menu items (Profile / Settings / Billing / Team)\n * - `[kpUserMenuHelp]` — help links\n * - `[kpUserMenuTheme]` — theme toggle row (e.g. a SegmentedControl)\n *\n * @example\n * <kp-user-menu\n * userName=\"Greg Black\"\n * userInitials=\"GB\"\n * userEmail=\"greg@example.com\"\n * [showPlanBadge]=\"true\"\n * planName=\"Pro\"\n * >\n * <div kpUserMenuItems>\n * <kp-menu-item icon=\"user\" label=\"Profile\" (click$)=\"goto('profile')\"/>\n * ...\n * </div>\n * </kp-user-menu>\n */\n@Component({\n selector: 'kp-user-menu',\n imports: [KpAvatarComponent, KpMenuItemComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n // Host is a floating panel containing menuitems alongside non-menu chrome\n // (user info card, theme toggle, divider). role=\"menu\" is scoped to each\n // menuitem-bearing group below; the host itself stays a generic container.\n host: { '[class]': 'hostClasses' },\n template: `\n <div class=\"kp-user-menu__info\">\n <kp-avatar [size]=\"avatarSize\" [initials]=\"userInitials || null\" [showStatus]=\"true\" status=\"online\"/>\n <div class=\"kp-user-menu__text\">\n <span class=\"kp-user-menu__name-row\">\n <span class=\"kp-user-menu__name\">{{ userName }}</span>\n @if (showPlanBadge) {\n <span class=\"kp-user-menu__plan\">{{ planName }}</span>\n }\n </span>\n @if (showEmail && userEmail) {\n <span class=\"kp-user-menu__email\">{{ userEmail }}</span>\n }\n </div>\n </div>\n\n <div class=\"kp-user-menu__divider\" aria-hidden=\"true\"></div>\n\n <div class=\"kp-user-menu__group\" role=\"menu\">\n <ng-content select=\"[kpUserMenuItems]\"/>\n </div>\n\n <div class=\"kp-user-menu__divider\" aria-hidden=\"true\"></div>\n\n @if (showThemeToggle) {\n <div class=\"kp-user-menu__theme\">\n <span class=\"kp-user-menu__theme-label\">Theme</span>\n <ng-content select=\"[kpUserMenuTheme]\"/>\n </div>\n <div class=\"kp-user-menu__divider\" aria-hidden=\"true\"></div>\n }\n\n @if (showHelpLink) {\n <div class=\"kp-user-menu__group\" role=\"menu\">\n <ng-content select=\"[kpUserMenuHelp]\"/>\n </div>\n <div class=\"kp-user-menu__divider\" aria-hidden=\"true\"></div>\n }\n\n <div class=\"kp-user-menu__group\" role=\"menu\">\n <kp-menu-item label=\"Sign out\" [danger]=\"true\" (click)=\"signOut.emit()\">\n <svg kpMenuItemIcon viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 12h12l-3-3m0 6 3-3M15 17v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v1\"/></svg>\n </kp-menu-item>\n </div>\n `,\n styles: [`\n :host {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n width: var(--kp-user-menu-w, 280px);\n padding: 4px 0;\n border-radius: 12px;\n background: var(--kp-color-surface-base);\n border: 1px solid var(--kp-color-border-default);\n box-shadow: var(--kp-elevation-overlay);\n font-family: var(--kp-font-family-sans, 'Onest', system-ui, sans-serif);\n }\n :host(.kp-user-menu--sm) { --kp-user-menu-w: 240px; --kp-user-menu-pad: 8px; }\n :host(.kp-user-menu--md) { --kp-user-menu-w: 280px; --kp-user-menu-pad: 12px; }\n\n .kp-user-menu__info {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px);\n }\n .kp-user-menu__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }\n .kp-user-menu__name-row { display: inline-flex; align-items: center; gap: 6px; }\n .kp-user-menu__name { font-size: 14px; font-weight: 500; color: var(--kp-color-text-strong); }\n .kp-user-menu__plan {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: 999px;\n background: var(--kp-color-primary-default-bg-rest);\n color: var(--kp-color-foreground-on-saturated);\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n }\n .kp-user-menu__email { font-size: 12px; color: var(--kp-color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n\n .kp-user-menu__divider { height: 1px; background: var(--kp-color-surface-strong); }\n\n .kp-user-menu__group { padding: 4px; display: flex; flex-direction: column; gap: 0; }\n\n .kp-user-menu__theme {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px);\n }\n .kp-user-menu__theme-label { flex: 1 1 auto; font-size: 14px; color: var(--kp-color-text-default); }\n\n .kp-user-menu__row {\n all: unset;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border-radius: 6px;\n font-size: 13px;\n color: var(--kp-color-text-default);\n cursor: pointer;\n transition: background var(--kp-motion-duration-fast) ease;\n }\n /* Match DropdownMenu menu-item hover exactly: bg → surface-subtle,\n fg unchanged. The user-menu-row was previously using\n surface-muted (one step darker) which read differently from\n regular menu items. Architectural follow-up: replace\n .kp-user-menu__row with <kp-menu-item>. */\n .kp-user-menu__row:hover { background: var(--kp-color-surface-subtle); }\n .kp-user-menu__row-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n color: var(--kp-color-text-muted);\n }\n .kp-user-menu__row-icon svg { width: 100%; height: 100%; }\n\n .kp-user-menu__row--danger {\n color: var(--kp-color-menu-item-fg-danger-rest);\n }\n .kp-user-menu__row--danger .kp-user-menu__row-icon { color: var(--kp-color-menu-item-fg-danger-rest); }\n .kp-user-menu__row--danger:hover { background: var(--kp-color-danger-subtle-bg-rest); color: var(--kp-color-menu-item-fg-danger-hover); }\n `],\n})\nexport class KpUserMenuComponent {\n @Input() size: KpUserMenuSize = 'md';\n\n @Input() userName: string | null = 'Greg Black';\n @Input() userEmail: string | null = 'greg@example.com';\n @Input() userInitials: string | null = 'GB';\n\n @Input() showEmail = true;\n @Input() showPlanBadge = false;\n @Input() planName = 'Pro';\n @Input() showThemeToggle = false;\n @Input() showHelpLink = true;\n\n @Output() signOut = new EventEmitter<void>();\n\n get avatarSize(): 'md' | 'lg' {\n return this.size === 'md' ? 'lg' : 'md';\n }\n\n get hostClasses(): string {\n return `kp-user-menu kp-user-menu--${this.size}`;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;AAkBA;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;MA2IU,mBAAmB,CAAA;IACrB,IAAI,GAAmB,IAAI;IAE3B,QAAQ,GAAkB,YAAY;IACtC,SAAS,GAAkB,kBAAkB;IAC7C,YAAY,GAAkB,IAAI;IAElC,SAAS,GAAG,IAAI;IAChB,aAAa,GAAG,KAAK;IACrB,QAAQ,GAAG,KAAK;IAChB,eAAe,GAAG,KAAK;IACvB,YAAY,GAAG,IAAI;AAElB,IAAA,OAAO,GAAG,IAAI,YAAY,EAAQ;AAE5C,IAAA,IAAI,UAAU,GAAA;AACZ,QAAA,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI;IACzC;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,CAAA,2BAAA,EAA8B,IAAI,CAAC,IAAI,EAAE;IAClD;uGArBW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,QAAA,EAAA,UAAA,EAAA,SAAA,EAAA,WAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,WAAA,EAAA,aAAA,EAAA,eAAA,EAAA,QAAA,EAAA,UAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,OAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,aAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlIpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,mzEAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAlDS,iBAAiB,kLAAE,mBAAmB,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,OAAA,EAAA,aAAA,EAAA,UAAA,EAAA,YAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,YAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAwIrC,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBA1I/B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,cAAc,WACf,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,EAAA,eAAA,EAChC,uBAAuB,CAAC,MAAM,QAIzC,EAAE,SAAS,EAAE,aAAa,EAAE,EAAA,QAAA,EACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,mzEAAA,CAAA,EAAA;;sBAuFA;;sBAEA;;sBACA;;sBACA;;sBAEA;;sBACA;;sBACA;;sBACA;;sBACA;;sBAEA;;;AClMH;;AAEG;;;;"}
1
+ {"version":3,"file":"kanso-protocol-user-menu.mjs","sources":["../../../../../packages/patterns/user-menu/src/user-menu.component.ts","../../../../../packages/patterns/user-menu/src/kanso-protocol-user-menu.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n Output,\n} from '@angular/core';\nimport { KpAvatarComponent } from '@kanso-protocol/avatar';\nimport { KpMenuItemComponent } from '@kanso-protocol/menu';\n\nexport type KpUserMenuSize = 'sm' | 'md';\n\nexport interface KpUserMenuItem {\n id: string;\n label: string;\n danger?: boolean;\n}\n\n/**\n * Kanso Protocol — UserMenu\n *\n * Preset dropdown shown from the user Avatar in Header. User block\n * at top, main menu, optional theme toggle + help links, Sign out.\n *\n * Slots:\n * - `[kpUserMenuItems]` — main menu items (Profile / Settings / Billing / Team)\n * - `[kpUserMenuHelp]` — help links\n * - `[kpUserMenuTheme]` — theme toggle row (e.g. a SegmentedControl)\n *\n * @example\n * <kp-user-menu\n * userName=\"Greg Black\"\n * userInitials=\"GB\"\n * userEmail=\"greg@example.com\"\n * [showPlanBadge]=\"true\"\n * planName=\"Pro\"\n * >\n * <div kpUserMenuItems>\n * <kp-menu-item icon=\"user\" label=\"Profile\" (click$)=\"goto('profile')\"/>\n * ...\n * </div>\n * </kp-user-menu>\n */\n@Component({\n selector: 'kp-user-menu',\n imports: [KpAvatarComponent, KpMenuItemComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n // Host is a floating panel containing menuitems alongside non-menu chrome\n // (user info card, theme toggle, divider). role=\"menu\" is scoped to each\n // menuitem-bearing group below; the host itself stays a generic container.\n host: { '[class]': 'hostClasses' },\n template: `\n <div class=\"kp-user-menu__info\">\n <kp-avatar [size]=\"avatarSize\" [initials]=\"userInitials || null\" [showStatus]=\"true\" status=\"online\"/>\n <div class=\"kp-user-menu__text\">\n <span class=\"kp-user-menu__name-row\">\n <span class=\"kp-user-menu__name\">{{ userName }}</span>\n @if (showPlanBadge) {\n <span class=\"kp-user-menu__plan\">{{ planName }}</span>\n }\n </span>\n @if (showEmail && userEmail) {\n <span class=\"kp-user-menu__email\">{{ userEmail }}</span>\n }\n </div>\n </div>\n\n <div class=\"kp-user-menu__divider\" aria-hidden=\"true\"></div>\n\n <div class=\"kp-user-menu__group\" role=\"menu\">\n <ng-content select=\"[kpUserMenuItems]\"/>\n </div>\n\n <div class=\"kp-user-menu__divider\" aria-hidden=\"true\"></div>\n\n @if (showThemeToggle) {\n <div class=\"kp-user-menu__theme\">\n <span class=\"kp-user-menu__theme-label\">Theme</span>\n <ng-content select=\"[kpUserMenuTheme]\"/>\n </div>\n <div class=\"kp-user-menu__divider\" aria-hidden=\"true\"></div>\n }\n\n @if (showHelpLink) {\n <div class=\"kp-user-menu__group\" role=\"menu\">\n <ng-content select=\"[kpUserMenuHelp]\"/>\n </div>\n <div class=\"kp-user-menu__divider\" aria-hidden=\"true\"></div>\n }\n\n <div class=\"kp-user-menu__group\" role=\"menu\">\n <kp-menu-item label=\"Sign out\" [danger]=\"true\" (click)=\"signOut.emit()\">\n <svg kpMenuItemIcon viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M9 12h12l-3-3m0 6 3-3M15 17v1a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v1\"/></svg>\n </kp-menu-item>\n </div>\n `,\n styles: [`\n :host {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n width: var(--kp-user-menu-w, 280px);\n padding: 4px 0;\n border-radius: 12px;\n background: var(--kp-color-popover-bg);\n border: 1px solid var(--kp-color-popover-border);\n box-shadow: var(--kp-elevation-overlay);\n font-family: var(--kp-font-family-sans, 'Onest', system-ui, sans-serif);\n }\n :host(.kp-user-menu--sm) { --kp-user-menu-w: 240px; --kp-user-menu-pad: 8px; }\n :host(.kp-user-menu--md) { --kp-user-menu-w: 280px; --kp-user-menu-pad: 12px; }\n\n .kp-user-menu__info {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px);\n }\n .kp-user-menu__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }\n .kp-user-menu__name-row { display: inline-flex; align-items: center; gap: 6px; }\n .kp-user-menu__name { font-size: 14px; font-weight: 500; color: var(--kp-color-text-strong); }\n .kp-user-menu__plan {\n display: inline-flex;\n align-items: center;\n padding: 2px 8px;\n border-radius: 999px;\n background: var(--kp-color-primary-default-bg-rest);\n color: var(--kp-color-foreground-on-saturated);\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n }\n .kp-user-menu__email { font-size: 12px; color: var(--kp-color-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n\n .kp-user-menu__divider { height: 1px; background: var(--kp-color-surface-strong); }\n\n .kp-user-menu__group { padding: 4px; display: flex; flex-direction: column; gap: 0; }\n\n .kp-user-menu__theme {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: var(--kp-user-menu-pad, 12px) calc(var(--kp-user-menu-pad, 12px) + 4px);\n }\n .kp-user-menu__theme-label { flex: 1 1 auto; font-size: 14px; color: var(--kp-color-text-default); }\n\n .kp-user-menu__row {\n all: unset;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border-radius: 6px;\n font-size: 13px;\n color: var(--kp-color-text-default);\n cursor: pointer;\n transition: background var(--kp-motion-duration-fast) ease;\n }\n /* Match DropdownMenu menu-item hover exactly: bg → surface-subtle,\n fg unchanged. The user-menu-row was previously using\n surface-muted (one step darker) which read differently from\n regular menu items. Architectural follow-up: replace\n .kp-user-menu__row with <kp-menu-item>. */\n .kp-user-menu__row:hover { background: var(--kp-color-surface-muted); }\n .kp-user-menu__row-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n color: var(--kp-color-text-muted);\n }\n .kp-user-menu__row-icon svg { width: 100%; height: 100%; }\n\n .kp-user-menu__row--danger {\n color: var(--kp-color-menu-item-fg-danger-rest);\n }\n .kp-user-menu__row--danger .kp-user-menu__row-icon { color: var(--kp-color-menu-item-fg-danger-rest); }\n .kp-user-menu__row--danger:hover { background: var(--kp-color-danger-subtle-bg-rest); color: var(--kp-color-menu-item-fg-danger-hover); }\n `],\n})\nexport class KpUserMenuComponent {\n @Input() size: KpUserMenuSize = 'md';\n\n @Input() userName: string | null = 'Greg Black';\n @Input() userEmail: string | null = 'greg@example.com';\n @Input() userInitials: string | null = 'GB';\n\n @Input() showEmail = true;\n @Input() showPlanBadge = false;\n @Input() planName = 'Pro';\n @Input() showThemeToggle = false;\n @Input() showHelpLink = true;\n\n @Output() signOut = new EventEmitter<void>();\n\n get avatarSize(): 'md' | 'lg' {\n return this.size === 'md' ? 'lg' : 'md';\n }\n\n get hostClasses(): string {\n return `kp-user-menu kp-user-menu--${this.size}`;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;AAkBA;;;;;;;;;;;;;;;;;;;;;;;;AAwBG;MA2IU,mBAAmB,CAAA;IACrB,IAAI,GAAmB,IAAI;IAE3B,QAAQ,GAAkB,YAAY;IACtC,SAAS,GAAkB,kBAAkB;IAC7C,YAAY,GAAkB,IAAI;IAElC,SAAS,GAAG,IAAI;IAChB,aAAa,GAAG,KAAK;IACrB,QAAQ,GAAG,KAAK;IAChB,eAAe,GAAG,KAAK;IACvB,YAAY,GAAG,IAAI;AAElB,IAAA,OAAO,GAAG,IAAI,YAAY,EAAQ;AAE5C,IAAA,IAAI,UAAU,GAAA;AACZ,QAAA,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI;IACzC;AAEA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,CAAA,2BAAA,EAA8B,IAAI,CAAC,IAAI,EAAE;IAClD;uGArBW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,QAAA,EAAA,UAAA,EAAA,SAAA,EAAA,WAAA,EAAA,YAAA,EAAA,cAAA,EAAA,SAAA,EAAA,WAAA,EAAA,aAAA,EAAA,eAAA,EAAA,QAAA,EAAA,UAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,OAAA,EAAA,EAAA,OAAA,EAAA,SAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,OAAA,EAAA,aAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAlIpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CT,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,gzEAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAlDS,iBAAiB,kLAAE,mBAAmB,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,OAAA,EAAA,aAAA,EAAA,UAAA,EAAA,YAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,YAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAwIrC,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBA1I/B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,cAAc,WACf,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,EAAA,eAAA,EAChC,uBAAuB,CAAC,MAAM,QAIzC,EAAE,SAAS,EAAE,aAAa,EAAE,EAAA,QAAA,EACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,gzEAAA,CAAA,EAAA;;sBAuFA;;sBAEA;;sBACA;;sBACA;;sBAEA;;sBACA;;sBACA;;sBACA;;sBACA;;sBAEA;;;AClMH;;AAEG;;;;"}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@kanso-protocol/user-menu",
3
- "version": "0.5.3",
3
+ "version": "1.0.1",
4
4
  "license": "MIT",
5
5
  "peerDependencies": {
6
- "@angular/core": "^18.0.0",
7
- "@angular/common": "^18.0.0",
8
- "@kanso-protocol/core": ">=0.5.3",
9
- "@kanso-protocol/avatar": ">=0.5.3",
10
- "@kanso-protocol/menu": ">=0.5.3"
6
+ "@angular/core": ">=21.0.0",
7
+ "@angular/common": ">=21.0.0",
8
+ "@kanso-protocol/core": ">=1.0.1",
9
+ "@kanso-protocol/avatar": ">=1.0.1",
10
+ "@kanso-protocol/menu": ">=1.0.1"
11
11
  },
12
12
  "description": "Kanso Protocol — user-menu (pattern).",
13
13
  "author": "GregNBlack",