@lifecorner/angular-ui-kit 3.25.1 → 3.27.0
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/fesm2022/lifecorner-angular-ui-kit-button.mjs +18 -2
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-callout.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-callout.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-chat.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-chat.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-color-picker.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-color-picker.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-date-range-picker.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-date-range-picker.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs +47 -9
- package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-document-viewer.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-document-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-file-upload.mjs +8 -4
- package/fesm2022/lifecorner-angular-ui-kit-file-upload.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-filter-bar.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-filter-bar.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-gallery.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-gantt-chart.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-gantt-chart.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs +3 -2
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-input.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-input.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-kanban-board.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-kanban-board.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-number-input.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-number-input.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-rich-text-editor.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-rich-text-editor.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-scatter-plot.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-scatter-plot.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-search-input.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-search-input.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-split-pane.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-split-pane.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs +3 -2
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-tabs.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-tabs.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-toggle-group.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-toggle-group.mjs.map +1 -1
- package/package.json +1 -1
- package/src/styles/_reset.scss +4 -2
- package/src/styles/focus-indicators.spec.ts +199 -0
- package/types/lifecorner-angular-ui-kit-button.d.ts +20 -0
- package/types/lifecorner-angular-ui-kit-dependency-viewer.d.ts +33 -4
- package/types/lifecorner-angular-ui-kit-description-list.d.ts +4 -0
- package/types/lifecorner-angular-ui-kit-file-upload.d.ts +11 -1
|
@@ -462,7 +462,7 @@ var HeaderComponent = class HeaderComponent {
|
|
|
462
462
|
}],
|
|
463
463
|
ngImport: i0,
|
|
464
464
|
template: "<header\n class=\"lc-header\"\n [class.lc-header--dark]=\"theme() === 'dark'\"\n [class.lc-header--light]=\"theme() === 'light'\"\n [class.lc-header--size-sm]=\"size() === 'sm'\"\n [class.lc-header--size-md]=\"size() === 'md'\"\n [class.lc-header--size-lg]=\"size() === 'lg'\"\n [class.lc-header--size-xl]=\"size() === 'xl'\"\n [class.lc-header--has-nav]=\"navItems().length > 0\"\n [class.lc-header--static]=\"!sticky()\"\n [class.lc-header--transparent]=\"variant() === 'transparent'\"\n>\n <!-- Hamburger menu icon (mobile only) -->\n @if (showHamburger()) {\n <lc-button\n #hamburger\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"hamburgerAriaLabel()\"\n (clicked)=\"onHamburgerClick()\"\n class=\"lc-header__hamburger\"\n >\n <lc-icon name=\"bars-3\" size=\"sm\" [decorative]=\"true\" />\n </lc-button>\n }\n\n <!-- Logo (clickable, navigates to home) -->\n <div class=\"lc-header__brand\">\n @if (showLogo()) {\n @if (homeHref()) {\n <!-- Plain link: works without the router and without JavaScript. -->\n <a [href]=\"homeHref()\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n } @else {\n <a routerLink=\"/\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n }\n }\n\n @if (title()) {\n <div class=\"lc-header__title-group\">\n @switch (titleTag()) {\n @case ('h1') {\n <h1 class=\"lc-header__title\">{{ title() }}</h1>\n }\n @case ('h2') {\n <h2 class=\"lc-header__title\">{{ title() }}</h2>\n }\n @case ('h3') {\n <h3 class=\"lc-header__title\">{{ title() }}</h3>\n }\n @case ('p') {\n <p class=\"lc-header__title\">{{ title() }}</p>\n }\n @case ('div') {\n <div class=\"lc-header__title\">{{ title() }}</div>\n }\n @default {\n <span class=\"lc-header__title\">{{ title() }}</span>\n }\n }\n @if (subtitle()) {\n <span class=\"lc-header__subtitle\" [attr.title]=\"subtitle()\">{{ subtitle() }}</span>\n }\n </div>\n }\n </div>\n\n <!-- Main navigation: inline from 1024 px, its own wrapping row below. -->\n @if (navItems().length > 0) {\n <nav class=\"lc-header__nav\" [attr.aria-label]=\"navAriaLabel()\">\n <ul class=\"lc-header__nav-list\">\n @for (item of navItems(); track $index) {\n <li class=\"lc-header__nav-item\">\n <a\n class=\"lc-header__nav-link\"\n [href]=\"item.href\"\n [attr.aria-current]=\"item.current ? 'page' : null\"\n >{{ item.label }}</a>\n </li>\n }\n </ul>\n </nav>\n }\n\n <!-- Zero-width spacer on the brand's row: keeps 3.10's two gaps before the end\n group and the first row's height; grows in a has-nav header from 1024 px. -->\n <div class=\"lc-header__spacer\"></div>\n\n <!-- End of the bar: the end slot (e.g. a language link), theme toggle, context\n info and account menu as one group. It goes to the end of a second row\n when it doesn't fit beside the brand (AS-31). No role; the DOM order and\n so the focus order stay brand → nav → end. -->\n <div class=\"lc-header__end\">\n <ng-content select=\"[slot='end']\" />\n\n <!-- Theme toggle button -->\n @if (showThemeButton()) {\n <lc-button\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"themeService.isDark() ? themeToLightAriaLabel() : themeToDarkAriaLabel()\"\n (clicked)=\"onThemeButtonClick()\"\n class=\"lc-header__theme-toggle\"\n >\n <lc-icon [name]=\"themeService.isDark() ? 'sun' : 'moon'\" size=\"sm\" [decorative]=\"true\" />\n </lc-button>\n }\n\n <!-- Context info (e.g. tenant, organization, project) -->\n @if (contextName()) {\n <button\n type=\"button\"\n class=\"lc-header__context-info\"\n [attr.aria-label]=\"contextButtonAriaLabel()\"\n (click)=\"contextClick.emit()\"\n >\n <!-- A real space between label and name: the visible text reads\n \"Tenant Acme Corp\", not \"TenantAcme Corp\" (WCAG 2.5.3). The\n tooltip sits on the name, so it is not a description of the button. -->\n @if (contextLabel()) {\n <span class=\"lc-header__context-label\">{{ contextLabel() }}</span>&ngsp;\n }\n <span class=\"lc-header__context-name\" [attr.title]=\"contextName()\">{{ contextName() }}</span>\n </button>\n }\n\n <!-- User profile menu -->\n @if (showUserMenu()) {\n <lc-menu\n [items]=\"menuItems()\"\n [isOpen]=\"isDropdownOpen()\"\n position=\"bottom-right\"\n minWidth=\"min(220px, calc(100vw - 2rem))\"\n maxWidth=\"min(18rem, calc(100vw - 2rem))\"\n [size]=\"menuSize()\"\n (itemClick)=\"onMenuItemClick($event)\"\n (closed)=\"closeDropdown()\"\n >\n <!-- Menu header with avatar, name and email -->\n @if (userName() || userEmail()) {\n <div header class=\"lc-header__menu-header\">\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n [fallback]=\"userAvatarFallback()\"\n size=\"md\"\n />\n <div class=\"lc-header__menu-user-info\">\n @if (userName()) {\n <div class=\"lc-header__menu-user-name\">{{ userName() }}</div>\n }\n @if (userEmail()) {\n <div class=\"lc-header__menu-user-email\">{{ userEmail() }}</div>\n }\n </div>\n </div>\n }\n\n @if (userMenuTrigger() === 'avatar') {\n <button\n trigger\n class=\"lc-header__profile-trigger lc-header__profile-trigger--avatar\"\n type=\"button\"\n [attr.aria-label]=\"avatarTriggerAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n [fallback]=\"userAvatarFallback()\"\n [decorative]=\"true\"\n size=\"md\"\n />\n </button>\n } @else {\n <button\n trigger\n class=\"lc-header__profile-trigger\"\n type=\"button\"\n [attr.aria-label]=\"userMenuAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-icon name=\"user\" size=\"sm\" [decorative]=\"true\" />\n <lc-icon name=\"chevron-down\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </lc-menu>\n }\n </div>\n</header>\n\n<ng-template #brandLogo>\n <lc-logo\n [variant]=\"logo() ? 'full' : 'emblem'\"\n [size]=\"logoSize()\"\n [clickable]=\"false\"\n [colorMode]=\"theme() === 'dark' ? 'dark' : theme() === 'light' ? 'light' : 'auto'\"\n [src]=\"logoSrc()\"\n [emblemSrc]=\"logoEmblemSrc()\"\n [darkSrc]=\"logoDarkSrc()\"\n [darkEmblemSrc]=\"logoDarkEmblemSrc()\"\n [alt]=\"logoAlt() || title() || 'Logo'\"\n />\n</ng-template>\n",
|
|
465
|
-
styles: [".lc-header{--lc-header-bg: var(--color-surface);--lc-header-fg: var(--color-text-primary);--lc-header-fg-secondary: var(--color-text-secondary);--lc-header-border: var(--color-border);--lc-header-hover-bg: var(--color-surface-hover);--lc-header-trigger-border: var(--color-border);--lc-header-trigger-fg: var(--color-text-secondary);--lc-header-padding-x: var(--lc-density-padding-lg, var(--spacing-6));display:flex;align-items:center;gap:var(--lc-density-gap-md, var(--spacing-4));flex-wrap:wrap;row-gap:0;padding:0 var(--lc-header-padding-x);background-color:var(--lc-header-bg);border-bottom:1px solid var(--lc-header-border);min-height:64px;position:sticky;top:0;z-index:1000}.lc-header.lc-header--size-sm{min-height:56px;--lc-header-row-height: 56px}.lc-header.lc-header--size-md{min-height:64px;--lc-header-row-height: 64px}.lc-header.lc-header--size-lg{min-height:80px;--lc-header-row-height: 80px}.lc-header.lc-header--size-xl{min-height:112px;--lc-header-row-height: 112px}@media(max-width:768px){.lc-header{--lc-header-padding-x: var(--lc-density-padding-md, var(--spacing-4))}}.lc-header--static{position:relative}.lc-header__nav{display:flex;align-items:center;min-width:0}.lc-header__nav-list{display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--lc-header-nav-gap, var(--spacing-1));margin:0;padding:0;list-style:none}.lc-header__nav-item{display:flex}.lc-header__nav-link{display:inline-flex;align-items:center;min-height:var(--size-min-touch-height, 2.75rem);padding:0 var(--spacing-3);border-radius:var(--border-radius-md);color:var(--lc-header-fg-secondary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-tight);text-decoration:none;transition:color .15s ease,background-color .15s ease}.lc-header__nav-link:hover{color:var(--lc-header-fg);background-color:var(--lc-header-hover-bg)}.lc-header__nav-link:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-header__nav-link[aria-current=page]{color:var(--lc-header-fg);text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:.45em}@media(max-width:1023.98px){.lc-header--has-nav .lc-header__nav{order:1;flex-basis:100%;margin-left:calc(-1 * var(--spacing-3))}}@media(min-width:1024px){.lc-header--has-nav .lc-header__brand{flex:0 1 auto;width:auto;max-width:none}.lc-header--has-nav .lc-header__title-group{flex:0 1 auto}.lc-header--has-nav .lc-header__title{margin-inline-end:0}.lc-header--has-nav .lc-header__subtitle{contain:none}.lc-header--has-nav .lc-header__spacer{flex:1}}.lc-header--dark{--lc-header-bg: #070e15;--lc-header-fg: #f1f6f8;--lc-header-fg-secondary: #c4d2d9;--lc-header-border: rgba(255, 255, 255, .08);--lc-header-hover-bg: rgba(132, 199, 212, .06);--lc-header-trigger-border: rgba(255, 255, 255, .08);--lc-header-trigger-fg: #c4d2d9}.lc-header--light{--lc-header-bg: #ffffff;--lc-header-fg: #111827;--lc-header-fg-secondary: #4b5563;--lc-header-border: #e5e7eb;--lc-header-hover-bg: #f3f4f6;--lc-header-trigger-border: #e5e7eb;--lc-header-trigger-fg: #374151}.lc-header__hamburger{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:24px;margin-left:calc(var(--lc-header-hamburger-slot, 56px) / 2 - var(--lc-header-padding-x) - 12px);margin-right:calc(var(--lc-header-hamburger-gap, .5rem) - var(--lc-density-gap-md, var(--spacing-4)));color:var(--lc-header-trigger-fg)}.lc-header__hamburger .lc-icon{width:24px;height:24px}.lc-header__brand{display:flex;flex:1 1 auto;align-items:center;gap:var(--spacing-3);width:min-content;max-width:calc(100% - var(--lc-density-gap-md, var(--spacing-4)));min-width:0}.lc-header--has-nav .lc-header__brand{min-height:var(--lc-header-row-height, 64px)}.lc-header__logo{display:flex;align-items:center;text-decoration:none;color:var(--lc-header-fg);flex-shrink:0}.lc-header__logo:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:4px;border-radius:var(--border-radius-sm)}.lc-header__logo-img{height:32px;width:auto}.lc-header__title-group{display:flex;flex:1 1 auto;flex-direction:column;gap:.125rem;min-width:0}.lc-header__title{font-size:1.25rem;font-weight:700;color:var(--lc-header-fg);margin:0;margin-inline-end:calc(-1 * var(--lc-density-gap-md, var(--spacing-4)));line-height:1.2;overflow-wrap:break-word;transition:color .2s ease}@media(max-width:640px){.lc-header__title{font-size:1.125rem}}.lc-header__subtitle{display:block;contain:inline-size;max-width:var(--lc-header-subtitle-max-width, 100%);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:.8125rem;line-height:1.3;font-weight:500;color:var(--lc-header-fg-secondary);text-transform:var(--lc-header-subtitle-transform, none);transition:color .2s ease}@media(min-width:1024px){.lc-header__subtitle{font-size:var(--font-size-sm, .875rem)}}.lc-header__spacer{flex:0 0 0;min-height:calc(var(--lc-header-row-height, 64px) - var(--_lc-header-border-width, 1px))}.lc-header__end{display:flex;flex-wrap:wrap;align-items:center;align-self:stretch;justify-content:flex-end;gap:0 var(--lc-density-gap-md, var(--spacing-4));margin-inline-start:auto;min-width:0;max-width:100%}.lc-header__end:empty{display:none}.lc-header__theme-toggle{color:var(--lc-header-trigger-fg)}.lc-header__context-info{display:flex;flex-direction:column;align-items:flex-end;gap:.0625rem;padding:var(--spacing-2) var(--spacing-3);background:transparent;border:none;cursor:pointer;border-radius:var(--border-radius-md);color:var(--lc-header-trigger-fg);transition:background-color .2s ease,color .2s ease;max-width:220px;min-width:0}.lc-header__context-info:hover{background-color:var(--lc-header-hover-bg)}.lc-header__context-info:hover .lc-header__context-name{color:var(--lc-header-fg)}.lc-header__context-info:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}@media(max-width:640px){.lc-header__context-info{display:none}}.lc-header__context-label{font-size:var(--font-size-xs);font-weight:500;color:var(--lc-header-fg-secondary);text-transform:uppercase;letter-spacing:.05em;line-height:1.2}.lc-header__context-name{font-size:var(--font-size-sm);font-weight:600;color:var(--lc-header-fg);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.lc-header--dark .lc-header__theme-toggle lc-icon,.lc-header--dark .lc-header__theme-toggle .lc-icon,.lc-header--dark .lc-header__theme-toggle svg,.lc-header--dark .lc-header__hamburger lc-icon,.lc-header--dark .lc-header__hamburger .lc-icon,.lc-header--dark .lc-header__hamburger svg,.lc-header--dark .lc-header__profile-trigger lc-icon,.lc-header--dark .lc-header__profile-trigger .lc-icon,.lc-header--dark .lc-header__profile-trigger svg,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg{color:var(--lc-header-trigger-fg)}.lc-header--dark lc-button,html.dark .lc-header:not(.lc-header--light) lc-button,:root.dark .lc-header:not(.lc-header--light) lc-button,.dark .lc-header:not(.lc-header--light) lc-button{--lc-button-ghost-fg: var(--lc-header-trigger-fg);--lc-button-ghost-hover-bg: var(--lc-header-hover-bg);--lc-button-ghost-hover-fg: var(--lc-header-fg);--lc-button-ghost-active-bg: var(--lc-header-hover-bg)}.lc-header__profile-trigger{display:flex;align-items:center;gap:var(--lc-density-gap-sm, var(--spacing-2));min-height:var(--size-min-touch-height, 2.75rem);box-sizing:border-box;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--spacing-3);background:transparent;border:1px solid var(--lc-header-trigger-border);border-radius:var(--border-radius-full);cursor:pointer;color:var(--lc-header-trigger-fg);transition:background-color .2s ease,border-color .2s ease}.lc-header__profile-trigger:hover{background-color:var(--lc-header-hover-bg);border-color:var(--lc-header-fg-secondary)}.lc-header__profile-trigger:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-header__profile-trigger--avatar{justify-content:center;width:3rem;height:3rem;min-height:3rem;padding:0;border:0;flex-shrink:0}.lc-header__profile-trigger--avatar:hover{border-color:transparent}.lc-header.lc-header--transparent{--lc-header-bg: transparent;--lc-header-border: transparent;--_lc-header-border-width: 0px;border-bottom-width:0}.lc-menu__header{padding:var(--spacing-3) var(--spacing-4);font-size:var(--font-size-sm);color:var(--color-text-secondary, #6b7280);border-bottom:1px solid var(--color-divider, #e5e7eb);margin-bottom:var(--spacing-1);word-break:break-word}.lc-header__menu-header{display:flex;align-items:flex-start;gap:var(--spacing-3);padding:var(--lc-density-padding-md, var(--spacing-4));border-bottom:1px solid var(--color-divider, #e5e7eb);margin-bottom:var(--spacing-1)}.lc-header__menu-user-info{flex:1;min-width:0}.lc-header__menu-user-name{font-size:var(--font-size-sm);font-weight:600;color:var(--color-text-primary);overflow-wrap:break-word;line-height:1.4}.lc-header__menu-user-email{font-size:var(--font-size-xs);color:var(--color-text-secondary, #6b7280);overflow-wrap:anywhere;line-height:1.4}\n"],
|
|
465
|
+
styles: [".lc-header{--lc-header-bg: var(--color-surface);--lc-header-fg: var(--color-text-primary);--lc-header-fg-secondary: var(--color-text-secondary);--lc-header-border: var(--color-border);--lc-header-hover-bg: var(--color-surface-hover);--lc-header-trigger-border: var(--color-border);--lc-header-trigger-fg: var(--color-text-secondary);--lc-header-padding-x: var(--lc-density-padding-lg, var(--spacing-6));display:flex;align-items:center;gap:var(--lc-density-gap-md, var(--spacing-4));flex-wrap:wrap;row-gap:0;padding:0 var(--lc-header-padding-x);background-color:var(--lc-header-bg);border-bottom:1px solid var(--lc-header-border);min-height:64px;position:sticky;top:0;z-index:1000}.lc-header.lc-header--size-sm{min-height:56px;--lc-header-row-height: 56px}.lc-header.lc-header--size-md{min-height:64px;--lc-header-row-height: 64px}.lc-header.lc-header--size-lg{min-height:80px;--lc-header-row-height: 80px}.lc-header.lc-header--size-xl{min-height:112px;--lc-header-row-height: 112px}@media(max-width:768px){.lc-header{--lc-header-padding-x: var(--lc-density-padding-md, var(--spacing-4))}}.lc-header--static{position:relative}.lc-header__nav{display:flex;align-items:center;min-width:0}.lc-header__nav-list{display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--lc-header-nav-gap, var(--spacing-1));margin:0;padding:0;list-style:none}.lc-header__nav-item{display:flex}.lc-header__nav-link{display:inline-flex;align-items:center;min-height:var(--size-min-touch-height, 2.75rem);padding:0 var(--spacing-3);border-radius:var(--border-radius-md);color:var(--lc-header-fg-secondary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-tight);text-decoration:none;transition:color .15s ease,background-color .15s ease}.lc-header__nav-link:hover{color:var(--lc-header-fg);background-color:var(--lc-header-hover-bg)}.lc-header__nav-link:focus-visible{outline:2px solid var(--_lc-header-ring, var(--color-primary-500));outline-offset:2px}.lc-header__nav-link[aria-current=page]{color:var(--lc-header-fg);text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:.45em}@media(max-width:1023.98px){.lc-header--has-nav .lc-header__nav{order:1;flex-basis:100%;margin-left:calc(-1 * var(--spacing-3))}}@media(min-width:1024px){.lc-header--has-nav .lc-header__brand{flex:0 1 auto;width:auto;max-width:none}.lc-header--has-nav .lc-header__title-group{flex:0 1 auto}.lc-header--has-nav .lc-header__title{margin-inline-end:0}.lc-header--has-nav .lc-header__subtitle{contain:none}.lc-header--has-nav .lc-header__spacer{flex:1}}.lc-header--dark{--lc-header-bg: #070e15;--lc-header-fg: #f1f6f8;--lc-header-fg-secondary: #c4d2d9;--lc-header-border: rgba(255, 255, 255, .08);--lc-header-hover-bg: rgba(132, 199, 212, .06);--lc-header-trigger-border: rgba(255, 255, 255, .08);--lc-header-trigger-fg: #c4d2d9}.lc-header--light{--lc-header-bg: #ffffff;--lc-header-fg: #111827;--lc-header-fg-secondary: #4b5563;--lc-header-border: #e5e7eb;--lc-header-hover-bg: #f3f4f6;--lc-header-trigger-border: #e5e7eb;--lc-header-trigger-fg: #374151;--_lc-header-ring: #208497}.lc-header__hamburger{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:24px;margin-left:calc(var(--lc-header-hamburger-slot, 56px) / 2 - var(--lc-header-padding-x) - 12px);margin-right:calc(var(--lc-header-hamburger-gap, .5rem) - var(--lc-density-gap-md, var(--spacing-4)));color:var(--lc-header-trigger-fg)}.lc-header__hamburger .lc-icon{width:24px;height:24px}.lc-header__brand{display:flex;flex:1 1 auto;align-items:center;gap:var(--spacing-3);width:min-content;max-width:calc(100% - var(--lc-density-gap-md, var(--spacing-4)));min-width:0}.lc-header--has-nav .lc-header__brand{min-height:var(--lc-header-row-height, 64px)}.lc-header__logo{display:flex;align-items:center;text-decoration:none;color:var(--lc-header-fg);flex-shrink:0}.lc-header__logo:focus-visible{outline:2px solid var(--_lc-header-ring, var(--color-primary-500));outline-offset:4px;border-radius:var(--border-radius-sm)}.lc-header__logo-img{height:32px;width:auto}.lc-header__title-group{display:flex;flex:1 1 auto;flex-direction:column;gap:.125rem;min-width:0}.lc-header__title{font-size:1.25rem;font-weight:700;color:var(--lc-header-fg);margin:0;margin-inline-end:calc(-1 * var(--lc-density-gap-md, var(--spacing-4)));line-height:1.2;overflow-wrap:break-word;transition:color .2s ease}@media(max-width:640px){.lc-header__title{font-size:1.125rem}}.lc-header__subtitle{display:block;contain:inline-size;max-width:var(--lc-header-subtitle-max-width, 100%);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:.8125rem;line-height:1.3;font-weight:500;color:var(--lc-header-fg-secondary);text-transform:var(--lc-header-subtitle-transform, none);transition:color .2s ease}@media(min-width:1024px){.lc-header__subtitle{font-size:var(--font-size-sm, .875rem)}}.lc-header__spacer{flex:0 0 0;min-height:calc(var(--lc-header-row-height, 64px) - var(--_lc-header-border-width, 1px))}.lc-header__end{display:flex;flex-wrap:wrap;align-items:center;align-self:stretch;justify-content:flex-end;gap:0 var(--lc-density-gap-md, var(--spacing-4));margin-inline-start:auto;min-width:0;max-width:100%}.lc-header__end:empty{display:none}.lc-header__theme-toggle{color:var(--lc-header-trigger-fg)}.lc-header__context-info{display:flex;flex-direction:column;align-items:flex-end;gap:.0625rem;padding:var(--spacing-2) var(--spacing-3);background:transparent;border:none;cursor:pointer;border-radius:var(--border-radius-md);color:var(--lc-header-trigger-fg);transition:background-color .2s ease,color .2s ease;max-width:220px;min-width:0}.lc-header__context-info:hover{background-color:var(--lc-header-hover-bg)}.lc-header__context-info:hover .lc-header__context-name{color:var(--lc-header-fg)}.lc-header__context-info:focus-visible{outline:2px solid var(--_lc-header-ring, var(--color-primary-500));outline-offset:2px}@media(max-width:640px){.lc-header__context-info{display:none}}.lc-header__context-label{font-size:var(--font-size-xs);font-weight:500;color:var(--lc-header-fg-secondary);text-transform:uppercase;letter-spacing:.05em;line-height:1.2}.lc-header__context-name{font-size:var(--font-size-sm);font-weight:600;color:var(--lc-header-fg);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.lc-header--dark .lc-header__theme-toggle lc-icon,.lc-header--dark .lc-header__theme-toggle .lc-icon,.lc-header--dark .lc-header__theme-toggle svg,.lc-header--dark .lc-header__hamburger lc-icon,.lc-header--dark .lc-header__hamburger .lc-icon,.lc-header--dark .lc-header__hamburger svg,.lc-header--dark .lc-header__profile-trigger lc-icon,.lc-header--dark .lc-header__profile-trigger .lc-icon,.lc-header--dark .lc-header__profile-trigger svg,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg{color:var(--lc-header-trigger-fg)}.lc-header--dark lc-button,html.dark .lc-header:not(.lc-header--light) lc-button,:root.dark .lc-header:not(.lc-header--light) lc-button,.dark .lc-header:not(.lc-header--light) lc-button{--lc-button-ghost-fg: var(--lc-header-trigger-fg);--lc-button-ghost-hover-bg: var(--lc-header-hover-bg);--lc-button-ghost-hover-fg: var(--lc-header-fg);--lc-button-ghost-active-bg: var(--lc-header-hover-bg)}.lc-header__profile-trigger{display:flex;align-items:center;gap:var(--lc-density-gap-sm, var(--spacing-2));min-height:var(--size-min-touch-height, 2.75rem);box-sizing:border-box;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--spacing-3);background:transparent;border:1px solid var(--lc-header-trigger-border);border-radius:var(--border-radius-full);cursor:pointer;color:var(--lc-header-trigger-fg);transition:background-color .2s ease,border-color .2s ease}.lc-header__profile-trigger:hover{background-color:var(--lc-header-hover-bg);border-color:var(--lc-header-fg-secondary)}.lc-header__profile-trigger:focus-visible{outline:2px solid var(--_lc-header-ring, var(--color-primary-500));outline-offset:2px}.lc-header__profile-trigger--avatar{justify-content:center;width:3rem;height:3rem;min-height:3rem;padding:0;border:0;flex-shrink:0}.lc-header__profile-trigger--avatar:hover{border-color:transparent}.lc-header.lc-header--transparent{--lc-header-bg: transparent;--lc-header-border: transparent;--_lc-header-border-width: 0px;border-bottom-width:0}.lc-menu__header{padding:var(--spacing-3) var(--spacing-4);font-size:var(--font-size-sm);color:var(--color-text-secondary, #6b7280);border-bottom:1px solid var(--color-divider, #e5e7eb);margin-bottom:var(--spacing-1);word-break:break-word}.lc-header__menu-header{display:flex;align-items:flex-start;gap:var(--spacing-3);padding:var(--lc-density-padding-md, var(--spacing-4));border-bottom:1px solid var(--color-divider, #e5e7eb);margin-bottom:var(--spacing-1)}.lc-header__menu-user-info{flex:1;min-width:0}.lc-header__menu-user-name{font-size:var(--font-size-sm);font-weight:600;color:var(--color-text-primary);overflow-wrap:break-word;line-height:1.4}.lc-header__menu-user-email{font-size:var(--font-size-xs);color:var(--color-text-secondary, #6b7280);overflow-wrap:anywhere;line-height:1.4}\n"],
|
|
466
466
|
dependencies: [
|
|
467
467
|
{
|
|
468
468
|
kind: "directive",
|
|
@@ -510,6 +510,7 @@ var HeaderComponent = class HeaderComponent {
|
|
|
510
510
|
"iconOnly",
|
|
511
511
|
"fullWidth",
|
|
512
512
|
"ariaLabel",
|
|
513
|
+
"ariaDescribedBy",
|
|
513
514
|
"type",
|
|
514
515
|
"title",
|
|
515
516
|
"disabledReason",
|
|
@@ -631,7 +632,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
631
632
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
632
633
|
host: { class: "lc-header-host" },
|
|
633
634
|
template: "<header\n class=\"lc-header\"\n [class.lc-header--dark]=\"theme() === 'dark'\"\n [class.lc-header--light]=\"theme() === 'light'\"\n [class.lc-header--size-sm]=\"size() === 'sm'\"\n [class.lc-header--size-md]=\"size() === 'md'\"\n [class.lc-header--size-lg]=\"size() === 'lg'\"\n [class.lc-header--size-xl]=\"size() === 'xl'\"\n [class.lc-header--has-nav]=\"navItems().length > 0\"\n [class.lc-header--static]=\"!sticky()\"\n [class.lc-header--transparent]=\"variant() === 'transparent'\"\n>\n <!-- Hamburger menu icon (mobile only) -->\n @if (showHamburger()) {\n <lc-button\n #hamburger\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"hamburgerAriaLabel()\"\n (clicked)=\"onHamburgerClick()\"\n class=\"lc-header__hamburger\"\n >\n <lc-icon name=\"bars-3\" size=\"sm\" [decorative]=\"true\" />\n </lc-button>\n }\n\n <!-- Logo (clickable, navigates to home) -->\n <div class=\"lc-header__brand\">\n @if (showLogo()) {\n @if (homeHref()) {\n <!-- Plain link: works without the router and without JavaScript. -->\n <a [href]=\"homeHref()\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n } @else {\n <a routerLink=\"/\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n }\n }\n\n @if (title()) {\n <div class=\"lc-header__title-group\">\n @switch (titleTag()) {\n @case ('h1') {\n <h1 class=\"lc-header__title\">{{ title() }}</h1>\n }\n @case ('h2') {\n <h2 class=\"lc-header__title\">{{ title() }}</h2>\n }\n @case ('h3') {\n <h3 class=\"lc-header__title\">{{ title() }}</h3>\n }\n @case ('p') {\n <p class=\"lc-header__title\">{{ title() }}</p>\n }\n @case ('div') {\n <div class=\"lc-header__title\">{{ title() }}</div>\n }\n @default {\n <span class=\"lc-header__title\">{{ title() }}</span>\n }\n }\n @if (subtitle()) {\n <span class=\"lc-header__subtitle\" [attr.title]=\"subtitle()\">{{ subtitle() }}</span>\n }\n </div>\n }\n </div>\n\n <!-- Main navigation: inline from 1024 px, its own wrapping row below. -->\n @if (navItems().length > 0) {\n <nav class=\"lc-header__nav\" [attr.aria-label]=\"navAriaLabel()\">\n <ul class=\"lc-header__nav-list\">\n @for (item of navItems(); track $index) {\n <li class=\"lc-header__nav-item\">\n <a\n class=\"lc-header__nav-link\"\n [href]=\"item.href\"\n [attr.aria-current]=\"item.current ? 'page' : null\"\n >{{ item.label }}</a>\n </li>\n }\n </ul>\n </nav>\n }\n\n <!-- Zero-width spacer on the brand's row: keeps 3.10's two gaps before the end\n group and the first row's height; grows in a has-nav header from 1024 px. -->\n <div class=\"lc-header__spacer\"></div>\n\n <!-- End of the bar: the end slot (e.g. a language link), theme toggle, context\n info and account menu as one group. It goes to the end of a second row\n when it doesn't fit beside the brand (AS-31). No role; the DOM order and\n so the focus order stay brand → nav → end. -->\n <div class=\"lc-header__end\">\n <ng-content select=\"[slot='end']\" />\n\n <!-- Theme toggle button -->\n @if (showThemeButton()) {\n <lc-button\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"themeService.isDark() ? themeToLightAriaLabel() : themeToDarkAriaLabel()\"\n (clicked)=\"onThemeButtonClick()\"\n class=\"lc-header__theme-toggle\"\n >\n <lc-icon [name]=\"themeService.isDark() ? 'sun' : 'moon'\" size=\"sm\" [decorative]=\"true\" />\n </lc-button>\n }\n\n <!-- Context info (e.g. tenant, organization, project) -->\n @if (contextName()) {\n <button\n type=\"button\"\n class=\"lc-header__context-info\"\n [attr.aria-label]=\"contextButtonAriaLabel()\"\n (click)=\"contextClick.emit()\"\n >\n <!-- A real space between label and name: the visible text reads\n \"Tenant Acme Corp\", not \"TenantAcme Corp\" (WCAG 2.5.3). The\n tooltip sits on the name, so it is not a description of the button. -->\n @if (contextLabel()) {\n <span class=\"lc-header__context-label\">{{ contextLabel() }}</span>&ngsp;\n }\n <span class=\"lc-header__context-name\" [attr.title]=\"contextName()\">{{ contextName() }}</span>\n </button>\n }\n\n <!-- User profile menu -->\n @if (showUserMenu()) {\n <lc-menu\n [items]=\"menuItems()\"\n [isOpen]=\"isDropdownOpen()\"\n position=\"bottom-right\"\n minWidth=\"min(220px, calc(100vw - 2rem))\"\n maxWidth=\"min(18rem, calc(100vw - 2rem))\"\n [size]=\"menuSize()\"\n (itemClick)=\"onMenuItemClick($event)\"\n (closed)=\"closeDropdown()\"\n >\n <!-- Menu header with avatar, name and email -->\n @if (userName() || userEmail()) {\n <div header class=\"lc-header__menu-header\">\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n [fallback]=\"userAvatarFallback()\"\n size=\"md\"\n />\n <div class=\"lc-header__menu-user-info\">\n @if (userName()) {\n <div class=\"lc-header__menu-user-name\">{{ userName() }}</div>\n }\n @if (userEmail()) {\n <div class=\"lc-header__menu-user-email\">{{ userEmail() }}</div>\n }\n </div>\n </div>\n }\n\n @if (userMenuTrigger() === 'avatar') {\n <button\n trigger\n class=\"lc-header__profile-trigger lc-header__profile-trigger--avatar\"\n type=\"button\"\n [attr.aria-label]=\"avatarTriggerAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n [fallback]=\"userAvatarFallback()\"\n [decorative]=\"true\"\n size=\"md\"\n />\n </button>\n } @else {\n <button\n trigger\n class=\"lc-header__profile-trigger\"\n type=\"button\"\n [attr.aria-label]=\"userMenuAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-icon name=\"user\" size=\"sm\" [decorative]=\"true\" />\n <lc-icon name=\"chevron-down\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </lc-menu>\n }\n </div>\n</header>\n\n<ng-template #brandLogo>\n <lc-logo\n [variant]=\"logo() ? 'full' : 'emblem'\"\n [size]=\"logoSize()\"\n [clickable]=\"false\"\n [colorMode]=\"theme() === 'dark' ? 'dark' : theme() === 'light' ? 'light' : 'auto'\"\n [src]=\"logoSrc()\"\n [emblemSrc]=\"logoEmblemSrc()\"\n [darkSrc]=\"logoDarkSrc()\"\n [darkEmblemSrc]=\"logoDarkEmblemSrc()\"\n [alt]=\"logoAlt() || title() || 'Logo'\"\n />\n</ng-template>\n",
|
|
634
|
-
styles: [".lc-header{--lc-header-bg: var(--color-surface);--lc-header-fg: var(--color-text-primary);--lc-header-fg-secondary: var(--color-text-secondary);--lc-header-border: var(--color-border);--lc-header-hover-bg: var(--color-surface-hover);--lc-header-trigger-border: var(--color-border);--lc-header-trigger-fg: var(--color-text-secondary);--lc-header-padding-x: var(--lc-density-padding-lg, var(--spacing-6));display:flex;align-items:center;gap:var(--lc-density-gap-md, var(--spacing-4));flex-wrap:wrap;row-gap:0;padding:0 var(--lc-header-padding-x);background-color:var(--lc-header-bg);border-bottom:1px solid var(--lc-header-border);min-height:64px;position:sticky;top:0;z-index:1000}.lc-header.lc-header--size-sm{min-height:56px;--lc-header-row-height: 56px}.lc-header.lc-header--size-md{min-height:64px;--lc-header-row-height: 64px}.lc-header.lc-header--size-lg{min-height:80px;--lc-header-row-height: 80px}.lc-header.lc-header--size-xl{min-height:112px;--lc-header-row-height: 112px}@media(max-width:768px){.lc-header{--lc-header-padding-x: var(--lc-density-padding-md, var(--spacing-4))}}.lc-header--static{position:relative}.lc-header__nav{display:flex;align-items:center;min-width:0}.lc-header__nav-list{display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--lc-header-nav-gap, var(--spacing-1));margin:0;padding:0;list-style:none}.lc-header__nav-item{display:flex}.lc-header__nav-link{display:inline-flex;align-items:center;min-height:var(--size-min-touch-height, 2.75rem);padding:0 var(--spacing-3);border-radius:var(--border-radius-md);color:var(--lc-header-fg-secondary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-tight);text-decoration:none;transition:color .15s ease,background-color .15s ease}.lc-header__nav-link:hover{color:var(--lc-header-fg);background-color:var(--lc-header-hover-bg)}.lc-header__nav-link:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-header__nav-link[aria-current=page]{color:var(--lc-header-fg);text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:.45em}@media(max-width:1023.98px){.lc-header--has-nav .lc-header__nav{order:1;flex-basis:100%;margin-left:calc(-1 * var(--spacing-3))}}@media(min-width:1024px){.lc-header--has-nav .lc-header__brand{flex:0 1 auto;width:auto;max-width:none}.lc-header--has-nav .lc-header__title-group{flex:0 1 auto}.lc-header--has-nav .lc-header__title{margin-inline-end:0}.lc-header--has-nav .lc-header__subtitle{contain:none}.lc-header--has-nav .lc-header__spacer{flex:1}}.lc-header--dark{--lc-header-bg: #070e15;--lc-header-fg: #f1f6f8;--lc-header-fg-secondary: #c4d2d9;--lc-header-border: rgba(255, 255, 255, .08);--lc-header-hover-bg: rgba(132, 199, 212, .06);--lc-header-trigger-border: rgba(255, 255, 255, .08);--lc-header-trigger-fg: #c4d2d9}.lc-header--light{--lc-header-bg: #ffffff;--lc-header-fg: #111827;--lc-header-fg-secondary: #4b5563;--lc-header-border: #e5e7eb;--lc-header-hover-bg: #f3f4f6;--lc-header-trigger-border: #e5e7eb;--lc-header-trigger-fg: #374151}.lc-header__hamburger{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:24px;margin-left:calc(var(--lc-header-hamburger-slot, 56px) / 2 - var(--lc-header-padding-x) - 12px);margin-right:calc(var(--lc-header-hamburger-gap, .5rem) - var(--lc-density-gap-md, var(--spacing-4)));color:var(--lc-header-trigger-fg)}.lc-header__hamburger .lc-icon{width:24px;height:24px}.lc-header__brand{display:flex;flex:1 1 auto;align-items:center;gap:var(--spacing-3);width:min-content;max-width:calc(100% - var(--lc-density-gap-md, var(--spacing-4)));min-width:0}.lc-header--has-nav .lc-header__brand{min-height:var(--lc-header-row-height, 64px)}.lc-header__logo{display:flex;align-items:center;text-decoration:none;color:var(--lc-header-fg);flex-shrink:0}.lc-header__logo:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:4px;border-radius:var(--border-radius-sm)}.lc-header__logo-img{height:32px;width:auto}.lc-header__title-group{display:flex;flex:1 1 auto;flex-direction:column;gap:.125rem;min-width:0}.lc-header__title{font-size:1.25rem;font-weight:700;color:var(--lc-header-fg);margin:0;margin-inline-end:calc(-1 * var(--lc-density-gap-md, var(--spacing-4)));line-height:1.2;overflow-wrap:break-word;transition:color .2s ease}@media(max-width:640px){.lc-header__title{font-size:1.125rem}}.lc-header__subtitle{display:block;contain:inline-size;max-width:var(--lc-header-subtitle-max-width, 100%);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:.8125rem;line-height:1.3;font-weight:500;color:var(--lc-header-fg-secondary);text-transform:var(--lc-header-subtitle-transform, none);transition:color .2s ease}@media(min-width:1024px){.lc-header__subtitle{font-size:var(--font-size-sm, .875rem)}}.lc-header__spacer{flex:0 0 0;min-height:calc(var(--lc-header-row-height, 64px) - var(--_lc-header-border-width, 1px))}.lc-header__end{display:flex;flex-wrap:wrap;align-items:center;align-self:stretch;justify-content:flex-end;gap:0 var(--lc-density-gap-md, var(--spacing-4));margin-inline-start:auto;min-width:0;max-width:100%}.lc-header__end:empty{display:none}.lc-header__theme-toggle{color:var(--lc-header-trigger-fg)}.lc-header__context-info{display:flex;flex-direction:column;align-items:flex-end;gap:.0625rem;padding:var(--spacing-2) var(--spacing-3);background:transparent;border:none;cursor:pointer;border-radius:var(--border-radius-md);color:var(--lc-header-trigger-fg);transition:background-color .2s ease,color .2s ease;max-width:220px;min-width:0}.lc-header__context-info:hover{background-color:var(--lc-header-hover-bg)}.lc-header__context-info:hover .lc-header__context-name{color:var(--lc-header-fg)}.lc-header__context-info:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}@media(max-width:640px){.lc-header__context-info{display:none}}.lc-header__context-label{font-size:var(--font-size-xs);font-weight:500;color:var(--lc-header-fg-secondary);text-transform:uppercase;letter-spacing:.05em;line-height:1.2}.lc-header__context-name{font-size:var(--font-size-sm);font-weight:600;color:var(--lc-header-fg);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.lc-header--dark .lc-header__theme-toggle lc-icon,.lc-header--dark .lc-header__theme-toggle .lc-icon,.lc-header--dark .lc-header__theme-toggle svg,.lc-header--dark .lc-header__hamburger lc-icon,.lc-header--dark .lc-header__hamburger .lc-icon,.lc-header--dark .lc-header__hamburger svg,.lc-header--dark .lc-header__profile-trigger lc-icon,.lc-header--dark .lc-header__profile-trigger .lc-icon,.lc-header--dark .lc-header__profile-trigger svg,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg{color:var(--lc-header-trigger-fg)}.lc-header--dark lc-button,html.dark .lc-header:not(.lc-header--light) lc-button,:root.dark .lc-header:not(.lc-header--light) lc-button,.dark .lc-header:not(.lc-header--light) lc-button{--lc-button-ghost-fg: var(--lc-header-trigger-fg);--lc-button-ghost-hover-bg: var(--lc-header-hover-bg);--lc-button-ghost-hover-fg: var(--lc-header-fg);--lc-button-ghost-active-bg: var(--lc-header-hover-bg)}.lc-header__profile-trigger{display:flex;align-items:center;gap:var(--lc-density-gap-sm, var(--spacing-2));min-height:var(--size-min-touch-height, 2.75rem);box-sizing:border-box;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--spacing-3);background:transparent;border:1px solid var(--lc-header-trigger-border);border-radius:var(--border-radius-full);cursor:pointer;color:var(--lc-header-trigger-fg);transition:background-color .2s ease,border-color .2s ease}.lc-header__profile-trigger:hover{background-color:var(--lc-header-hover-bg);border-color:var(--lc-header-fg-secondary)}.lc-header__profile-trigger:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.lc-header__profile-trigger--avatar{justify-content:center;width:3rem;height:3rem;min-height:3rem;padding:0;border:0;flex-shrink:0}.lc-header__profile-trigger--avatar:hover{border-color:transparent}.lc-header.lc-header--transparent{--lc-header-bg: transparent;--lc-header-border: transparent;--_lc-header-border-width: 0px;border-bottom-width:0}.lc-menu__header{padding:var(--spacing-3) var(--spacing-4);font-size:var(--font-size-sm);color:var(--color-text-secondary, #6b7280);border-bottom:1px solid var(--color-divider, #e5e7eb);margin-bottom:var(--spacing-1);word-break:break-word}.lc-header__menu-header{display:flex;align-items:flex-start;gap:var(--spacing-3);padding:var(--lc-density-padding-md, var(--spacing-4));border-bottom:1px solid var(--color-divider, #e5e7eb);margin-bottom:var(--spacing-1)}.lc-header__menu-user-info{flex:1;min-width:0}.lc-header__menu-user-name{font-size:var(--font-size-sm);font-weight:600;color:var(--color-text-primary);overflow-wrap:break-word;line-height:1.4}.lc-header__menu-user-email{font-size:var(--font-size-xs);color:var(--color-text-secondary, #6b7280);overflow-wrap:anywhere;line-height:1.4}\n"]
|
|
635
|
+
styles: [".lc-header{--lc-header-bg: var(--color-surface);--lc-header-fg: var(--color-text-primary);--lc-header-fg-secondary: var(--color-text-secondary);--lc-header-border: var(--color-border);--lc-header-hover-bg: var(--color-surface-hover);--lc-header-trigger-border: var(--color-border);--lc-header-trigger-fg: var(--color-text-secondary);--lc-header-padding-x: var(--lc-density-padding-lg, var(--spacing-6));display:flex;align-items:center;gap:var(--lc-density-gap-md, var(--spacing-4));flex-wrap:wrap;row-gap:0;padding:0 var(--lc-header-padding-x);background-color:var(--lc-header-bg);border-bottom:1px solid var(--lc-header-border);min-height:64px;position:sticky;top:0;z-index:1000}.lc-header.lc-header--size-sm{min-height:56px;--lc-header-row-height: 56px}.lc-header.lc-header--size-md{min-height:64px;--lc-header-row-height: 64px}.lc-header.lc-header--size-lg{min-height:80px;--lc-header-row-height: 80px}.lc-header.lc-header--size-xl{min-height:112px;--lc-header-row-height: 112px}@media(max-width:768px){.lc-header{--lc-header-padding-x: var(--lc-density-padding-md, var(--spacing-4))}}.lc-header--static{position:relative}.lc-header__nav{display:flex;align-items:center;min-width:0}.lc-header__nav-list{display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--lc-header-nav-gap, var(--spacing-1));margin:0;padding:0;list-style:none}.lc-header__nav-item{display:flex}.lc-header__nav-link{display:inline-flex;align-items:center;min-height:var(--size-min-touch-height, 2.75rem);padding:0 var(--spacing-3);border-radius:var(--border-radius-md);color:var(--lc-header-fg-secondary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-tight);text-decoration:none;transition:color .15s ease,background-color .15s ease}.lc-header__nav-link:hover{color:var(--lc-header-fg);background-color:var(--lc-header-hover-bg)}.lc-header__nav-link:focus-visible{outline:2px solid var(--_lc-header-ring, var(--color-primary-500));outline-offset:2px}.lc-header__nav-link[aria-current=page]{color:var(--lc-header-fg);text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:.45em}@media(max-width:1023.98px){.lc-header--has-nav .lc-header__nav{order:1;flex-basis:100%;margin-left:calc(-1 * var(--spacing-3))}}@media(min-width:1024px){.lc-header--has-nav .lc-header__brand{flex:0 1 auto;width:auto;max-width:none}.lc-header--has-nav .lc-header__title-group{flex:0 1 auto}.lc-header--has-nav .lc-header__title{margin-inline-end:0}.lc-header--has-nav .lc-header__subtitle{contain:none}.lc-header--has-nav .lc-header__spacer{flex:1}}.lc-header--dark{--lc-header-bg: #070e15;--lc-header-fg: #f1f6f8;--lc-header-fg-secondary: #c4d2d9;--lc-header-border: rgba(255, 255, 255, .08);--lc-header-hover-bg: rgba(132, 199, 212, .06);--lc-header-trigger-border: rgba(255, 255, 255, .08);--lc-header-trigger-fg: #c4d2d9}.lc-header--light{--lc-header-bg: #ffffff;--lc-header-fg: #111827;--lc-header-fg-secondary: #4b5563;--lc-header-border: #e5e7eb;--lc-header-hover-bg: #f3f4f6;--lc-header-trigger-border: #e5e7eb;--lc-header-trigger-fg: #374151;--_lc-header-ring: #208497}.lc-header__hamburger{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:24px;margin-left:calc(var(--lc-header-hamburger-slot, 56px) / 2 - var(--lc-header-padding-x) - 12px);margin-right:calc(var(--lc-header-hamburger-gap, .5rem) - var(--lc-density-gap-md, var(--spacing-4)));color:var(--lc-header-trigger-fg)}.lc-header__hamburger .lc-icon{width:24px;height:24px}.lc-header__brand{display:flex;flex:1 1 auto;align-items:center;gap:var(--spacing-3);width:min-content;max-width:calc(100% - var(--lc-density-gap-md, var(--spacing-4)));min-width:0}.lc-header--has-nav .lc-header__brand{min-height:var(--lc-header-row-height, 64px)}.lc-header__logo{display:flex;align-items:center;text-decoration:none;color:var(--lc-header-fg);flex-shrink:0}.lc-header__logo:focus-visible{outline:2px solid var(--_lc-header-ring, var(--color-primary-500));outline-offset:4px;border-radius:var(--border-radius-sm)}.lc-header__logo-img{height:32px;width:auto}.lc-header__title-group{display:flex;flex:1 1 auto;flex-direction:column;gap:.125rem;min-width:0}.lc-header__title{font-size:1.25rem;font-weight:700;color:var(--lc-header-fg);margin:0;margin-inline-end:calc(-1 * var(--lc-density-gap-md, var(--spacing-4)));line-height:1.2;overflow-wrap:break-word;transition:color .2s ease}@media(max-width:640px){.lc-header__title{font-size:1.125rem}}.lc-header__subtitle{display:block;contain:inline-size;max-width:var(--lc-header-subtitle-max-width, 100%);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:.8125rem;line-height:1.3;font-weight:500;color:var(--lc-header-fg-secondary);text-transform:var(--lc-header-subtitle-transform, none);transition:color .2s ease}@media(min-width:1024px){.lc-header__subtitle{font-size:var(--font-size-sm, .875rem)}}.lc-header__spacer{flex:0 0 0;min-height:calc(var(--lc-header-row-height, 64px) - var(--_lc-header-border-width, 1px))}.lc-header__end{display:flex;flex-wrap:wrap;align-items:center;align-self:stretch;justify-content:flex-end;gap:0 var(--lc-density-gap-md, var(--spacing-4));margin-inline-start:auto;min-width:0;max-width:100%}.lc-header__end:empty{display:none}.lc-header__theme-toggle{color:var(--lc-header-trigger-fg)}.lc-header__context-info{display:flex;flex-direction:column;align-items:flex-end;gap:.0625rem;padding:var(--spacing-2) var(--spacing-3);background:transparent;border:none;cursor:pointer;border-radius:var(--border-radius-md);color:var(--lc-header-trigger-fg);transition:background-color .2s ease,color .2s ease;max-width:220px;min-width:0}.lc-header__context-info:hover{background-color:var(--lc-header-hover-bg)}.lc-header__context-info:hover .lc-header__context-name{color:var(--lc-header-fg)}.lc-header__context-info:focus-visible{outline:2px solid var(--_lc-header-ring, var(--color-primary-500));outline-offset:2px}@media(max-width:640px){.lc-header__context-info{display:none}}.lc-header__context-label{font-size:var(--font-size-xs);font-weight:500;color:var(--lc-header-fg-secondary);text-transform:uppercase;letter-spacing:.05em;line-height:1.2}.lc-header__context-name{font-size:var(--font-size-sm);font-weight:600;color:var(--lc-header-fg);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.lc-header--dark .lc-header__theme-toggle lc-icon,.lc-header--dark .lc-header__theme-toggle .lc-icon,.lc-header--dark .lc-header__theme-toggle svg,.lc-header--dark .lc-header__hamburger lc-icon,.lc-header--dark .lc-header__hamburger .lc-icon,.lc-header--dark .lc-header__hamburger svg,.lc-header--dark .lc-header__profile-trigger lc-icon,.lc-header--dark .lc-header__profile-trigger .lc-icon,.lc-header--dark .lc-header__profile-trigger svg,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,html.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,:root.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__theme-toggle svg,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__hamburger svg,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger .lc-icon,.dark .lc-header:not(.lc-header--light) .lc-header__profile-trigger svg{color:var(--lc-header-trigger-fg)}.lc-header--dark lc-button,html.dark .lc-header:not(.lc-header--light) lc-button,:root.dark .lc-header:not(.lc-header--light) lc-button,.dark .lc-header:not(.lc-header--light) lc-button{--lc-button-ghost-fg: var(--lc-header-trigger-fg);--lc-button-ghost-hover-bg: var(--lc-header-hover-bg);--lc-button-ghost-hover-fg: var(--lc-header-fg);--lc-button-ghost-active-bg: var(--lc-header-hover-bg)}.lc-header__profile-trigger{display:flex;align-items:center;gap:var(--lc-density-gap-sm, var(--spacing-2));min-height:var(--size-min-touch-height, 2.75rem);box-sizing:border-box;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--spacing-3);background:transparent;border:1px solid var(--lc-header-trigger-border);border-radius:var(--border-radius-full);cursor:pointer;color:var(--lc-header-trigger-fg);transition:background-color .2s ease,border-color .2s ease}.lc-header__profile-trigger:hover{background-color:var(--lc-header-hover-bg);border-color:var(--lc-header-fg-secondary)}.lc-header__profile-trigger:focus-visible{outline:2px solid var(--_lc-header-ring, var(--color-primary-500));outline-offset:2px}.lc-header__profile-trigger--avatar{justify-content:center;width:3rem;height:3rem;min-height:3rem;padding:0;border:0;flex-shrink:0}.lc-header__profile-trigger--avatar:hover{border-color:transparent}.lc-header.lc-header--transparent{--lc-header-bg: transparent;--lc-header-border: transparent;--_lc-header-border-width: 0px;border-bottom-width:0}.lc-menu__header{padding:var(--spacing-3) var(--spacing-4);font-size:var(--font-size-sm);color:var(--color-text-secondary, #6b7280);border-bottom:1px solid var(--color-divider, #e5e7eb);margin-bottom:var(--spacing-1);word-break:break-word}.lc-header__menu-header{display:flex;align-items:flex-start;gap:var(--spacing-3);padding:var(--lc-density-padding-md, var(--spacing-4));border-bottom:1px solid var(--color-divider, #e5e7eb);margin-bottom:var(--spacing-1)}.lc-header__menu-user-info{flex:1;min-width:0}.lc-header__menu-user-name{font-size:var(--font-size-sm);font-weight:600;color:var(--color-text-primary);overflow-wrap:break-word;line-height:1.4}.lc-header__menu-user-email{font-size:var(--font-size-xs);color:var(--color-text-secondary, #6b7280);overflow-wrap:anywhere;line-height:1.4}\n"]
|
|
635
636
|
}]
|
|
636
637
|
}],
|
|
637
638
|
ctorParameters: () => [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-header.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/header/header.component.ts","../../../../libs/angular-ui-kit/src/lib/header/header.component.html"],"sourcesContent":["import {\n Component,\n ElementRef,\n Injector,\n input,\n output,\n signal,\n computed,\n inject,\n viewChild,\n afterRenderEffect,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { RouterModule } from '@angular/router';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\nimport { LogoComponent } from '@lifecorner/angular-ui-kit/logo';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_BARS_3, ICON_CHEVRON_DOWN, ICON_LOGOUT, ICON_MOON, ICON_SUN, ICON_USER } from '@lifecorner/angular-ui-kit/icons';\nimport { AvatarColor, AvatarComponent, AvatarFallback, ɵavatarInitials } from '@lifecorner/angular-ui-kit/avatar';\nimport { MenuComponent, MenuItem } from '@lifecorner/angular-ui-kit/menu';\nimport { ThemeService } from '@lifecorner/angular-ui-kit/theme';\nimport { nameWithText } from '@lifecorner/angular-ui-kit/internal/a11y';\n\n/** A link in the header's main navigation (`navItems`). */\nexport interface HeaderNavItem {\n /** Visible link text. */\n label: string;\n /** Plain URL — rendered as a native `href`, no router involved. */\n href: string;\n /** Marks the page the visitor is on (`aria-current=\"page\"` + underline). */\n current?: boolean;\n}\n\n/** Element used for the header title (`titleTag`). */\nexport type HeaderTitleTag = 'h1' | 'h2' | 'h3' | 'p' | 'span' | 'div';\n\n/**\n * Surface of the header: `default` is the bar on `--color-surface` with a\n * bottom border; `transparent` has no background and no border, for a header\n * that sits on the page (\"Weite\").\n */\nexport type HeaderVariant = 'default' | 'transparent';\n\n/**\n * What the account-menu button shows: `icon` (a user icon and a chevron) or\n * `avatar` (the person's initials avatar, `userName`, `userAvatarSrc`,\n * `userAvatarColor`, in a 48 px round button).\n */\nexport type HeaderUserMenuTrigger = 'icon' | 'avatar';\n\n/**\n * AppHeaderComponent - Global application header for the LifeCorner shell\n *\n * Features:\n * - Clickable logo for home navigation\n * - Optional title and subtitle display\n * - User profile dropdown with avatar, name, email, optional Profile link, and Logout\n * - Optional theme toggle button in header. By default the button toggles the\n * `ThemeService` itself and additionally emits `themeToggleClick`, so the\n * handler must NOT toggle again (that would undo the switch). To own the\n * toggling in the app, set `[autoToggleTheme]=\"false\"` and toggle in the\n * handler.\n * - Hamburger menu toggle for mobile sidebar; bind `sidenavOpen` (and\n * `sidenavId`) so the toggle exposes `aria-expanded` / `aria-controls`.\n * - OnPush change detection for performance\n *\n * Public, prerendered sites (no router, no JavaScript needed):\n * - `homeHref` makes the brand a plain link (instead of `routerLink=\"/\"`).\n * - `navItems` render a labelled main navigation (`<nav aria-label><ul>` with\n * `aria-current=\"page\"` on the current item); below 1024 px it moves to a\n * second row and wraps.\n * - `[slot='end']` takes content at the end of the first row (e.g. a language\n * link), `showUserMenu` hides the account menu, `titleTag` picks the title\n * element (the page keeps its own `<h1>`), `sticky` can be switched off.\n * - The end content (slot, theme button, context, account menu) is one group:\n * when it doesn't fit beside the logo and the title's longest word (200 %\n * text on a phone), it takes the end of a second row instead of covering the\n * brand or widening the page (3.10.1, AS-31). The subtitle ends with \"…\".\n * App shell (\"Weite\", kit 3.3):\n * - `variant=\"transparent\"`: no background and no border, the header sits on\n * the page (pair it with `[sticky]=\"false\"`, a header without a surface\n * cannot stay over scrolling text).\n * - `userMenuTrigger=\"avatar\"`: the account button is the person's initials\n * avatar (`userAvatarColor` for the member colour, `userAvatarSrc` for a\n * photo, `userAvatarFallback=\"person\"` for a person symbol while there is\n * no name) in a 48 px round button; the icon trigger is 44 px high in every\n * density.\n * - The subtitle (e.g. a household name) stays on one line and ends with \"…\";\n * the full text is its `title` and stays in the accessible text. It is shown\n * as typed (no uppercase).\n * - The account menu is at most `min(18rem, 100vw − 2rem)` wide; the name and\n * email in its header wrap instead of being cut.\n * - Every built-in label is an input (`homeAriaLabel`, `hamburgerAriaLabel`,\n * `userMenuAriaLabel`, `navAriaLabel`, `profileLabel`, `logoutLabel`,\n * `themeToDarkAriaLabel`, `themeToLightAriaLabel`, `contextAriaLabel`);\n * the defaults stay English.\n * - The `ThemeService` (which persists to localStorage) is only created when\n * the theme button is shown.\n *\n * @example\n * ```html\n * <lc-header\n * [logo]=\"'/assets/logo.svg'\"\n * [title]=\"'LifeCorner'\"\n * [subtitle]=\"'User Profile'\"\n * [userName]=\"'John Doe'\"\n * [userEmail]=\"'user@example.com'\"\n * [showHamburger]=\"true\"\n * [sidenavOpen]=\"sidenavOpen\"\n * sidenavId=\"app-sidenav\"\n * [showThemeButton]=\"true\"\n * [showProfileMenuItem]=\"true\"\n * (hamburgerClick)=\"toggleSidebar()\"\n * (themeToggleClick)=\"trackThemeToggle()\"\n * (profileClick)=\"navigateToProfile()\"\n * (logoutClick)=\"handleLogout()\"\n * />\n *\n * <!-- App-controlled theme: the header only reports the click -->\n * <lc-header\n * [showThemeButton]=\"true\"\n * [autoToggleTheme]=\"false\"\n * (themeToggleClick)=\"toggleTheme()\"\n * />\n *\n * <!-- Public site: plain links, labelled nav, language link at the end -->\n * <lc-header\n * size=\"sm\"\n * [sticky]=\"false\"\n * [showUserMenu]=\"false\"\n * homeHref=\"/de/\"\n * homeAriaLabel=\"Produkt – Startseite\"\n * navAriaLabel=\"Hauptnavigation\"\n * [navItems]=\"[\n * { label: 'Sicherheit', href: '/de/sicherheit', current: true },\n * { label: 'Roadmap', href: '/de/roadmap' }\n * ]\"\n * >\n * <a slot=\"end\" lcButton variant=\"ghost\" href=\"/en/security\" hreflang=\"en\" lang=\"en\">English</a>\n * </lc-header>\n * ```\n */\n@Component({\n selector: 'lc-header',\n standalone: true,\n imports: [\n NgTemplateOutlet,\n RouterModule,\n ButtonComponent,\n LogoComponent,\n IconComponent,\n AvatarComponent,\n MenuComponent,\n ],\n // Its own glyphs, and the profile menu's (lc-menu renders them in this view).\n viewProviders: [ɵprovideKitIcons([ICON_BARS_3, ICON_SUN, ICON_MOON, ICON_USER, ICON_CHEVRON_DOWN, ICON_LOGOUT])],\n templateUrl: './header.component.html',\n styleUrl: './header.component.scss',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'lc-header-host',\n },\n})\nexport class HeaderComponent {\n readonly theme = input<'light' | 'dark' | 'auto'>('auto');\n readonly logo = input('');\n /**\n * Render the brand block. On its own this shows the emblem; with `logo` set\n * it shows the full lockup. (It used to additionally require `logo` or\n * `title`, so `showLogo` alone rendered an empty 0px-wide brand area with no\n * error — an app could end up with no branding at all and no clue why.)\n */\n readonly showLogo = input(true);\n /** Custom URL for the full brand logo (forwarded to inner `<lc-logo>`). */\n readonly logoSrc = input('');\n /** Custom URL for the emblem-only brand logo. */\n readonly logoEmblemSrc = input('');\n /** Optional dark-theme URL for the full brand logo. */\n readonly logoDarkSrc = input('');\n /** Optional dark-theme URL for the emblem-only brand logo. */\n readonly logoDarkEmblemSrc = input('');\n /** Alt text for the brand logo (forwarded to inner `<lc-logo>`). */\n readonly logoAlt = input('');\n /** Size of the brand logo (forwarded to inner `<lc-logo>`). Defaults to `md`. */\n readonly logoSize = input<'xs' | 'sm' | 'md' | 'lg' | 'xl'>('md');\n /**\n * Overall header height. Useful to align the header with a sidebar brand block.\n * Maps to the same `min-height` scale the sidenav logo area uses:\n * `sm` 56px · `md` 64px (default) · `lg` 80px · `xl` 112px.\n */\n readonly size = input<'sm' | 'md' | 'lg' | 'xl'>('md');\n readonly title = input('');\n /**\n * Surface: `default` (the bar on `--color-surface` with a bottom border) or\n * `transparent` (no background, no border — the header sits on the page).\n */\n readonly variant = input<HeaderVariant>('default');\n /**\n * Element for the title. `h1` keeps the app-shell behaviour; on a site whose\n * pages carry their own `<h1>`, use `span` (or `p`/`div`).\n */\n readonly titleTag = input<HeaderTitleTag>('h1');\n /**\n * Second line under the title (e.g. the household name). One line, cut\n * with \"…\" when it does not fit; the full text is its `title` attribute.\n * Shown as typed.\n */\n readonly subtitle = input('');\n readonly userEmail = input('');\n readonly userName = input('');\n /**\n * What the account-menu button shows: `icon` (user icon and chevron) or\n * `avatar` (the initials of `userName` in a 48 px round button; the button\n * is named `userMenuAriaLabel`, a comma and the initials).\n * @default 'icon'\n */\n readonly userMenuTrigger = input<HeaderUserMenuTrigger>('icon');\n /** Photo for the account avatar (trigger and menu header); initials when empty or broken. */\n readonly userAvatarSrc = input('');\n /** Colour of the account avatar's initials: `default` or a member colour `member-1` … `member-6`. */\n readonly userAvatarColor = input<AvatarColor>('default');\n /**\n * Passed to the trigger avatar and the menu avatar as `fallback` (3.15):\n * `person` shows a person symbol on a neutral disc instead of \"?\" while\n * `userName` is empty.\n * @default 'initials'\n */\n readonly userAvatarFallback = input<AvatarFallback>('initials');\n readonly showHamburger = input(false);\n /**\n * Open state of the sidenav the hamburger controls. When bound, the toggle\n * announces it via `aria-expanded`; leave `undefined` when the header does\n * not know (the attribute is then omitted rather than lying).\n */\n readonly sidenavOpen = input<boolean | undefined>(undefined);\n /** DOM id of the sidenav the hamburger controls (`aria-controls`). */\n readonly sidenavId = input('');\n readonly showThemeButton = input(false);\n /**\n * Whether the theme button toggles the `ThemeService` itself before emitting\n * `themeToggleClick`. Set to `false` when the app owns the theme switch and\n * toggles in the `(themeToggleClick)` handler — otherwise both would toggle\n * and the click would be a no-op.\n */\n readonly autoToggleTheme = input(true);\n readonly contextName = input('');\n readonly contextLabel = input('');\n readonly menuSize = input<'sm' | 'md' | 'lg'>('sm');\n readonly showProfileMenuItem = input(true);\n /** Render the account menu (avatar trigger with Profile/Logout). */\n readonly showUserMenu = input(true);\n /**\n * Plain URL for the brand link. When set, the brand is a native\n * `<a href>` — no router needed (static or prerendered sites). Empty keeps\n * `routerLink=\"/\"`.\n */\n readonly homeHref = input('');\n /**\n * Main navigation links, rendered as `<nav><ul><li><a href>` with\n * `aria-current=\"page\"` on the current one. On screens below 1024 px the\n * navigation takes a second row and wraps.\n */\n readonly navItems = input<readonly HeaderNavItem[]>([]);\n /** Keep the header at the top while scrolling (`position: sticky`). */\n readonly sticky = input(true);\n\n // Labels (defaults are English; translate them in the app).\n /** Accessible name of the brand link. */\n readonly homeAriaLabel = input('Go to home');\n /** Accessible name of the hamburger button. */\n readonly hamburgerAriaLabel = input('Toggle sidebar menu');\n /**\n * Accessible name of the account menu trigger. With `userMenuTrigger=\"avatar\"`\n * the button is named this text, a comma and the initials it shows\n * (`Menü für Johanna Müller, JM`), so a voice-control user can say what they\n * see (WCAG 2.5.3). Nothing is added when `userName` gives no initials, or\n * when the text already contains them as a word. The name is the same with a\n * photo.\n * @default 'Open user menu'\n */\n readonly userMenuAriaLabel = input('Open user menu');\n /** Accessible name of the `<nav>` around `navItems`. */\n readonly navAriaLabel = input('Main navigation');\n /** Label of the theme button while the light theme is active. */\n readonly themeToDarkAriaLabel = input('Switch to dark mode');\n /** Label of the theme button while the dark theme is active. */\n readonly themeToLightAriaLabel = input('Switch to light mode');\n /**\n * Start of the context button's accessible name. The visible `contextLabel`\n * and `contextName` follow it (WCAG 2.5.3 Label in Name), unless the label\n * already contains them: `Context info, Tenant Acme Corp`.\n * @default 'Context info'\n */\n readonly contextAriaLabel = input('Context info');\n /** Label of the Profile entry in the account menu. */\n readonly profileLabel = input('Profile');\n /** Label of the Logout entry in the account menu. */\n readonly logoutLabel = input('Logout');\n\n readonly hamburgerClick = output<void>();\n readonly themeToggleClick = output<void>();\n readonly logoutClick = output<void>();\n readonly profileClick = output<void>();\n readonly contextClick = output<void>();\n\n private readonly injector = inject(Injector);\n private themeServiceInstance: ThemeService | null = null;\n\n /**\n * Resolved on first use, i.e. only when the theme button is shown: creating\n * the ThemeService reads and writes the theme class and localStorage, which a\n * site without a theme switch must not do.\n */\n protected get themeService(): ThemeService {\n return (this.themeServiceInstance ??= this.injector.get(ThemeService));\n }\n\n private readonly hamburger = viewChild('hamburger', { read: ElementRef<HTMLElement> });\n\n constructor() {\n // The hamburger is an <lc-button>; the ARIA state belongs on its native\n // <button> (the element that has the button role), not on the custom\n // element host — so it is reflected after render rather than bound in the\n // template.\n afterRenderEffect(() => {\n const button = this.hamburger()?.nativeElement.querySelector('button');\n if (!button) return;\n const open = this.sidenavOpen();\n const controls = this.sidenavId();\n if (open === undefined) {\n button.removeAttribute('aria-expanded');\n } else {\n button.setAttribute('aria-expanded', String(open));\n }\n if (controls) {\n button.setAttribute('aria-controls', controls);\n } else {\n button.removeAttribute('aria-controls');\n }\n });\n }\n\n /**\n * Name of the avatar trigger (AS-33, WCAG 2.5.3 Label in Name):\n * `userMenuAriaLabel`, a comma and the initials the avatar shows, so the\n * visible text is a word of the name. Built from the same function as the\n * avatar's initials and independent of the photo, so the prerendered name\n * and the page's agree. Nothing is added for the `?` placeholder or when\n * the label already holds the initials as a word (parentheticals dropped,\n * as axe-core 4.14 does); an empty label becomes the initials alone.\n */\n protected readonly avatarTriggerAriaLabel = computed(() => {\n const initials = ɵavatarInitials(this.userName());\n const label = this.userMenuAriaLabel();\n if (!/[\\p{L}\\p{N}]/u.test(initials)) return label;\n // toLowerCase, not toLocaleLowerCase: server and browser must agree.\n const words = label\n .replace(/\\([^()]*\\)/g, ' ')\n .toLowerCase()\n .split(/[^\\p{L}\\p{N}]+/u);\n if (words.includes(initials.toLowerCase())) return label;\n if (label.trim() === '') return initials;\n return `${label}, ${initials}`;\n });\n\n /**\n * Name of the context button (AS-33, WCAG 2.5.3 Label in Name):\n * `contextAriaLabel`, a comma and the visible `contextLabel` and\n * `contextName`, so a voice-control user can say what they see.\n */\n protected readonly contextButtonAriaLabel = computed(() =>\n nameWithText(this.contextAriaLabel(), [this.contextLabel(), this.contextName()].filter(Boolean).join(' ')),\n );\n\n /**\n * Get menu items for profile dropdown\n */\n protected readonly menuItems = computed<MenuItem[]>(() => {\n const items: MenuItem[] = [];\n\n // Add profile link if enabled\n if (this.showProfileMenuItem()) {\n items.push({\n id: 'profile',\n label: this.profileLabel(),\n icon: 'user',\n dividerAfter: true,\n });\n }\n\n // Add logout\n items.push({\n id: 'logout',\n label: this.logoutLabel(),\n icon: 'arrow-right-start-on-rectangle',\n variant: 'danger',\n });\n\n return items;\n });\n\n /**\n * Dropdown open state (using Angular signals)\n */\n private readonly dropdownOpen = signal<boolean>(false);\n\n /**\n * Get dropdown open state\n */\n isDropdownOpen(): boolean {\n return this.dropdownOpen();\n }\n\n /**\n * Toggle profile dropdown visibility\n */\n toggleDropdown(): void {\n this.dropdownOpen.set(!this.dropdownOpen());\n }\n\n /**\n * Close profile dropdown\n */\n closeDropdown(): void {\n this.dropdownOpen.set(false);\n }\n\n /**\n * Handle hamburger click\n */\n onHamburgerClick(): void {\n this.hamburgerClick.emit();\n }\n\n /**\n * Handle theme button click (separate button, not in menu). Toggles the\n * theme unless the app opted out via `autoToggleTheme`, then emits.\n */\n onThemeButtonClick(): void {\n if (this.autoToggleTheme()) {\n this.themeService.toggleTheme();\n }\n this.themeToggleClick.emit();\n }\n\n /**\n * Handle logout click\n */\n onLogoutClick(): void {\n this.logoutClick.emit();\n this.closeDropdown();\n }\n\n /**\n * Handle profile click\n */\n onProfileClick(): void {\n this.profileClick.emit();\n this.closeDropdown();\n }\n\n /**\n * Handle menu item click\n */\n onMenuItemClick(item: MenuItem): void {\n if (item.id === 'logout') {\n this.onLogoutClick();\n } else if (item.id === 'profile') {\n this.onProfileClick();\n }\n }\n}\n","<header\n class=\"lc-header\"\n [class.lc-header--dark]=\"theme() === 'dark'\"\n [class.lc-header--light]=\"theme() === 'light'\"\n [class.lc-header--size-sm]=\"size() === 'sm'\"\n [class.lc-header--size-md]=\"size() === 'md'\"\n [class.lc-header--size-lg]=\"size() === 'lg'\"\n [class.lc-header--size-xl]=\"size() === 'xl'\"\n [class.lc-header--has-nav]=\"navItems().length > 0\"\n [class.lc-header--static]=\"!sticky()\"\n [class.lc-header--transparent]=\"variant() === 'transparent'\"\n>\n <!-- Hamburger menu icon (mobile only) -->\n @if (showHamburger()) {\n <lc-button\n #hamburger\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"hamburgerAriaLabel()\"\n (clicked)=\"onHamburgerClick()\"\n class=\"lc-header__hamburger\"\n >\n <lc-icon name=\"bars-3\" size=\"sm\" [decorative]=\"true\" />\n </lc-button>\n }\n\n <!-- Logo (clickable, navigates to home) -->\n <div class=\"lc-header__brand\">\n @if (showLogo()) {\n @if (homeHref()) {\n <!-- Plain link: works without the router and without JavaScript. -->\n <a [href]=\"homeHref()\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n } @else {\n <a routerLink=\"/\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n }\n }\n\n @if (title()) {\n <div class=\"lc-header__title-group\">\n @switch (titleTag()) {\n @case ('h1') {\n <h1 class=\"lc-header__title\">{{ title() }}</h1>\n }\n @case ('h2') {\n <h2 class=\"lc-header__title\">{{ title() }}</h2>\n }\n @case ('h3') {\n <h3 class=\"lc-header__title\">{{ title() }}</h3>\n }\n @case ('p') {\n <p class=\"lc-header__title\">{{ title() }}</p>\n }\n @case ('div') {\n <div class=\"lc-header__title\">{{ title() }}</div>\n }\n @default {\n <span class=\"lc-header__title\">{{ title() }}</span>\n }\n }\n @if (subtitle()) {\n <span class=\"lc-header__subtitle\" [attr.title]=\"subtitle()\">{{ subtitle() }}</span>\n }\n </div>\n }\n </div>\n\n <!-- Main navigation: inline from 1024 px, its own wrapping row below. -->\n @if (navItems().length > 0) {\n <nav class=\"lc-header__nav\" [attr.aria-label]=\"navAriaLabel()\">\n <ul class=\"lc-header__nav-list\">\n @for (item of navItems(); track $index) {\n <li class=\"lc-header__nav-item\">\n <a\n class=\"lc-header__nav-link\"\n [href]=\"item.href\"\n [attr.aria-current]=\"item.current ? 'page' : null\"\n >{{ item.label }}</a>\n </li>\n }\n </ul>\n </nav>\n }\n\n <!-- Zero-width spacer on the brand's row: keeps 3.10's two gaps before the end\n group and the first row's height; grows in a has-nav header from 1024 px. -->\n <div class=\"lc-header__spacer\"></div>\n\n <!-- End of the bar: the end slot (e.g. a language link), theme toggle, context\n info and account menu as one group. It goes to the end of a second row\n when it doesn't fit beside the brand (AS-31). No role; the DOM order and\n so the focus order stay brand → nav → end. -->\n <div class=\"lc-header__end\">\n <ng-content select=\"[slot='end']\" />\n\n <!-- Theme toggle button -->\n @if (showThemeButton()) {\n <lc-button\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"themeService.isDark() ? themeToLightAriaLabel() : themeToDarkAriaLabel()\"\n (clicked)=\"onThemeButtonClick()\"\n class=\"lc-header__theme-toggle\"\n >\n <lc-icon [name]=\"themeService.isDark() ? 'sun' : 'moon'\" size=\"sm\" [decorative]=\"true\" />\n </lc-button>\n }\n\n <!-- Context info (e.g. tenant, organization, project) -->\n @if (contextName()) {\n <button\n type=\"button\"\n class=\"lc-header__context-info\"\n [attr.aria-label]=\"contextButtonAriaLabel()\"\n (click)=\"contextClick.emit()\"\n >\n <!-- A real space between label and name: the visible text reads\n \"Tenant Acme Corp\", not \"TenantAcme Corp\" (WCAG 2.5.3). The\n tooltip sits on the name, so it is not a description of the button. -->\n @if (contextLabel()) {\n <span class=\"lc-header__context-label\">{{ contextLabel() }}</span>&ngsp;\n }\n <span class=\"lc-header__context-name\" [attr.title]=\"contextName()\">{{ contextName() }}</span>\n </button>\n }\n\n <!-- User profile menu -->\n @if (showUserMenu()) {\n <lc-menu\n [items]=\"menuItems()\"\n [isOpen]=\"isDropdownOpen()\"\n position=\"bottom-right\"\n minWidth=\"min(220px, calc(100vw - 2rem))\"\n maxWidth=\"min(18rem, calc(100vw - 2rem))\"\n [size]=\"menuSize()\"\n (itemClick)=\"onMenuItemClick($event)\"\n (closed)=\"closeDropdown()\"\n >\n <!-- Menu header with avatar, name and email -->\n @if (userName() || userEmail()) {\n <div header class=\"lc-header__menu-header\">\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n [fallback]=\"userAvatarFallback()\"\n size=\"md\"\n />\n <div class=\"lc-header__menu-user-info\">\n @if (userName()) {\n <div class=\"lc-header__menu-user-name\">{{ userName() }}</div>\n }\n @if (userEmail()) {\n <div class=\"lc-header__menu-user-email\">{{ userEmail() }}</div>\n }\n </div>\n </div>\n }\n\n @if (userMenuTrigger() === 'avatar') {\n <button\n trigger\n class=\"lc-header__profile-trigger lc-header__profile-trigger--avatar\"\n type=\"button\"\n [attr.aria-label]=\"avatarTriggerAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n [fallback]=\"userAvatarFallback()\"\n [decorative]=\"true\"\n size=\"md\"\n />\n </button>\n } @else {\n <button\n trigger\n class=\"lc-header__profile-trigger\"\n type=\"button\"\n [attr.aria-label]=\"userMenuAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-icon name=\"user\" size=\"sm\" [decorative]=\"true\" />\n <lc-icon name=\"chevron-down\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </lc-menu>\n }\n </div>\n</header>\n\n<ng-template #brandLogo>\n <lc-logo\n [variant]=\"logo() ? 'full' : 'emblem'\"\n [size]=\"logoSize()\"\n [clickable]=\"false\"\n [colorMode]=\"theme() === 'dark' ? 'dark' : theme() === 'light' ? 'light' : 'auto'\"\n [src]=\"logoSrc()\"\n [emblemSrc]=\"logoEmblemSrc()\"\n [darkSrc]=\"logoDarkSrc()\"\n [darkEmblemSrc]=\"logoDarkEmblemSrc()\"\n [alt]=\"logoAlt() || title() || 'Logo'\"\n />\n</ng-template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-header.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/header/header.component.ts","../../../../libs/angular-ui-kit/src/lib/header/header.component.html"],"sourcesContent":["import {\n Component,\n ElementRef,\n Injector,\n input,\n output,\n signal,\n computed,\n inject,\n viewChild,\n afterRenderEffect,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { RouterModule } from '@angular/router';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\nimport { LogoComponent } from '@lifecorner/angular-ui-kit/logo';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_BARS_3, ICON_CHEVRON_DOWN, ICON_LOGOUT, ICON_MOON, ICON_SUN, ICON_USER } from '@lifecorner/angular-ui-kit/icons';\nimport { AvatarColor, AvatarComponent, AvatarFallback, ɵavatarInitials } from '@lifecorner/angular-ui-kit/avatar';\nimport { MenuComponent, MenuItem } from '@lifecorner/angular-ui-kit/menu';\nimport { ThemeService } from '@lifecorner/angular-ui-kit/theme';\nimport { nameWithText } from '@lifecorner/angular-ui-kit/internal/a11y';\n\n/** A link in the header's main navigation (`navItems`). */\nexport interface HeaderNavItem {\n /** Visible link text. */\n label: string;\n /** Plain URL — rendered as a native `href`, no router involved. */\n href: string;\n /** Marks the page the visitor is on (`aria-current=\"page\"` + underline). */\n current?: boolean;\n}\n\n/** Element used for the header title (`titleTag`). */\nexport type HeaderTitleTag = 'h1' | 'h2' | 'h3' | 'p' | 'span' | 'div';\n\n/**\n * Surface of the header: `default` is the bar on `--color-surface` with a\n * bottom border; `transparent` has no background and no border, for a header\n * that sits on the page (\"Weite\").\n */\nexport type HeaderVariant = 'default' | 'transparent';\n\n/**\n * What the account-menu button shows: `icon` (a user icon and a chevron) or\n * `avatar` (the person's initials avatar, `userName`, `userAvatarSrc`,\n * `userAvatarColor`, in a 48 px round button).\n */\nexport type HeaderUserMenuTrigger = 'icon' | 'avatar';\n\n/**\n * AppHeaderComponent - Global application header for the LifeCorner shell\n *\n * Features:\n * - Clickable logo for home navigation\n * - Optional title and subtitle display\n * - User profile dropdown with avatar, name, email, optional Profile link, and Logout\n * - Optional theme toggle button in header. By default the button toggles the\n * `ThemeService` itself and additionally emits `themeToggleClick`, so the\n * handler must NOT toggle again (that would undo the switch). To own the\n * toggling in the app, set `[autoToggleTheme]=\"false\"` and toggle in the\n * handler.\n * - Hamburger menu toggle for mobile sidebar; bind `sidenavOpen` (and\n * `sidenavId`) so the toggle exposes `aria-expanded` / `aria-controls`.\n * - OnPush change detection for performance\n *\n * Public, prerendered sites (no router, no JavaScript needed):\n * - `homeHref` makes the brand a plain link (instead of `routerLink=\"/\"`).\n * - `navItems` render a labelled main navigation (`<nav aria-label><ul>` with\n * `aria-current=\"page\"` on the current item); below 1024 px it moves to a\n * second row and wraps.\n * - `[slot='end']` takes content at the end of the first row (e.g. a language\n * link), `showUserMenu` hides the account menu, `titleTag` picks the title\n * element (the page keeps its own `<h1>`), `sticky` can be switched off.\n * - The end content (slot, theme button, context, account menu) is one group:\n * when it doesn't fit beside the logo and the title's longest word (200 %\n * text on a phone), it takes the end of a second row instead of covering the\n * brand or widening the page (3.10.1, AS-31). The subtitle ends with \"…\".\n * App shell (\"Weite\", kit 3.3):\n * - `variant=\"transparent\"`: no background and no border, the header sits on\n * the page (pair it with `[sticky]=\"false\"`, a header without a surface\n * cannot stay over scrolling text).\n * - `userMenuTrigger=\"avatar\"`: the account button is the person's initials\n * avatar (`userAvatarColor` for the member colour, `userAvatarSrc` for a\n * photo, `userAvatarFallback=\"person\"` for a person symbol while there is\n * no name) in a 48 px round button; the icon trigger is 44 px high in every\n * density.\n * - The subtitle (e.g. a household name) stays on one line and ends with \"…\";\n * the full text is its `title` and stays in the accessible text. It is shown\n * as typed (no uppercase).\n * - The account menu is at most `min(18rem, 100vw − 2rem)` wide; the name and\n * email in its header wrap instead of being cut.\n * - Every built-in label is an input (`homeAriaLabel`, `hamburgerAriaLabel`,\n * `userMenuAriaLabel`, `navAriaLabel`, `profileLabel`, `logoutLabel`,\n * `themeToDarkAriaLabel`, `themeToLightAriaLabel`, `contextAriaLabel`);\n * the defaults stay English.\n * - The `ThemeService` (which persists to localStorage) is only created when\n * the theme button is shown.\n *\n * @example\n * ```html\n * <lc-header\n * [logo]=\"'/assets/logo.svg'\"\n * [title]=\"'LifeCorner'\"\n * [subtitle]=\"'User Profile'\"\n * [userName]=\"'John Doe'\"\n * [userEmail]=\"'user@example.com'\"\n * [showHamburger]=\"true\"\n * [sidenavOpen]=\"sidenavOpen\"\n * sidenavId=\"app-sidenav\"\n * [showThemeButton]=\"true\"\n * [showProfileMenuItem]=\"true\"\n * (hamburgerClick)=\"toggleSidebar()\"\n * (themeToggleClick)=\"trackThemeToggle()\"\n * (profileClick)=\"navigateToProfile()\"\n * (logoutClick)=\"handleLogout()\"\n * />\n *\n * <!-- App-controlled theme: the header only reports the click -->\n * <lc-header\n * [showThemeButton]=\"true\"\n * [autoToggleTheme]=\"false\"\n * (themeToggleClick)=\"toggleTheme()\"\n * />\n *\n * <!-- Public site: plain links, labelled nav, language link at the end -->\n * <lc-header\n * size=\"sm\"\n * [sticky]=\"false\"\n * [showUserMenu]=\"false\"\n * homeHref=\"/de/\"\n * homeAriaLabel=\"Produkt – Startseite\"\n * navAriaLabel=\"Hauptnavigation\"\n * [navItems]=\"[\n * { label: 'Sicherheit', href: '/de/sicherheit', current: true },\n * { label: 'Roadmap', href: '/de/roadmap' }\n * ]\"\n * >\n * <a slot=\"end\" lcButton variant=\"ghost\" href=\"/en/security\" hreflang=\"en\" lang=\"en\">English</a>\n * </lc-header>\n * ```\n */\n@Component({\n selector: 'lc-header',\n standalone: true,\n imports: [\n NgTemplateOutlet,\n RouterModule,\n ButtonComponent,\n LogoComponent,\n IconComponent,\n AvatarComponent,\n MenuComponent,\n ],\n // Its own glyphs, and the profile menu's (lc-menu renders them in this view).\n viewProviders: [ɵprovideKitIcons([ICON_BARS_3, ICON_SUN, ICON_MOON, ICON_USER, ICON_CHEVRON_DOWN, ICON_LOGOUT])],\n templateUrl: './header.component.html',\n styleUrl: './header.component.scss',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'lc-header-host',\n },\n})\nexport class HeaderComponent {\n readonly theme = input<'light' | 'dark' | 'auto'>('auto');\n readonly logo = input('');\n /**\n * Render the brand block. On its own this shows the emblem; with `logo` set\n * it shows the full lockup. (It used to additionally require `logo` or\n * `title`, so `showLogo` alone rendered an empty 0px-wide brand area with no\n * error — an app could end up with no branding at all and no clue why.)\n */\n readonly showLogo = input(true);\n /** Custom URL for the full brand logo (forwarded to inner `<lc-logo>`). */\n readonly logoSrc = input('');\n /** Custom URL for the emblem-only brand logo. */\n readonly logoEmblemSrc = input('');\n /** Optional dark-theme URL for the full brand logo. */\n readonly logoDarkSrc = input('');\n /** Optional dark-theme URL for the emblem-only brand logo. */\n readonly logoDarkEmblemSrc = input('');\n /** Alt text for the brand logo (forwarded to inner `<lc-logo>`). */\n readonly logoAlt = input('');\n /** Size of the brand logo (forwarded to inner `<lc-logo>`). Defaults to `md`. */\n readonly logoSize = input<'xs' | 'sm' | 'md' | 'lg' | 'xl'>('md');\n /**\n * Overall header height. Useful to align the header with a sidebar brand block.\n * Maps to the same `min-height` scale the sidenav logo area uses:\n * `sm` 56px · `md` 64px (default) · `lg` 80px · `xl` 112px.\n */\n readonly size = input<'sm' | 'md' | 'lg' | 'xl'>('md');\n readonly title = input('');\n /**\n * Surface: `default` (the bar on `--color-surface` with a bottom border) or\n * `transparent` (no background, no border — the header sits on the page).\n */\n readonly variant = input<HeaderVariant>('default');\n /**\n * Element for the title. `h1` keeps the app-shell behaviour; on a site whose\n * pages carry their own `<h1>`, use `span` (or `p`/`div`).\n */\n readonly titleTag = input<HeaderTitleTag>('h1');\n /**\n * Second line under the title (e.g. the household name). One line, cut\n * with \"…\" when it does not fit; the full text is its `title` attribute.\n * Shown as typed.\n */\n readonly subtitle = input('');\n readonly userEmail = input('');\n readonly userName = input('');\n /**\n * What the account-menu button shows: `icon` (user icon and chevron) or\n * `avatar` (the initials of `userName` in a 48 px round button; the button\n * is named `userMenuAriaLabel`, a comma and the initials).\n * @default 'icon'\n */\n readonly userMenuTrigger = input<HeaderUserMenuTrigger>('icon');\n /** Photo for the account avatar (trigger and menu header); initials when empty or broken. */\n readonly userAvatarSrc = input('');\n /** Colour of the account avatar's initials: `default` or a member colour `member-1` … `member-6`. */\n readonly userAvatarColor = input<AvatarColor>('default');\n /**\n * Passed to the trigger avatar and the menu avatar as `fallback` (3.15):\n * `person` shows a person symbol on a neutral disc instead of \"?\" while\n * `userName` is empty.\n * @default 'initials'\n */\n readonly userAvatarFallback = input<AvatarFallback>('initials');\n readonly showHamburger = input(false);\n /**\n * Open state of the sidenav the hamburger controls. When bound, the toggle\n * announces it via `aria-expanded`; leave `undefined` when the header does\n * not know (the attribute is then omitted rather than lying).\n */\n readonly sidenavOpen = input<boolean | undefined>(undefined);\n /** DOM id of the sidenav the hamburger controls (`aria-controls`). */\n readonly sidenavId = input('');\n readonly showThemeButton = input(false);\n /**\n * Whether the theme button toggles the `ThemeService` itself before emitting\n * `themeToggleClick`. Set to `false` when the app owns the theme switch and\n * toggles in the `(themeToggleClick)` handler — otherwise both would toggle\n * and the click would be a no-op.\n */\n readonly autoToggleTheme = input(true);\n readonly contextName = input('');\n readonly contextLabel = input('');\n readonly menuSize = input<'sm' | 'md' | 'lg'>('sm');\n readonly showProfileMenuItem = input(true);\n /** Render the account menu (avatar trigger with Profile/Logout). */\n readonly showUserMenu = input(true);\n /**\n * Plain URL for the brand link. When set, the brand is a native\n * `<a href>` — no router needed (static or prerendered sites). Empty keeps\n * `routerLink=\"/\"`.\n */\n readonly homeHref = input('');\n /**\n * Main navigation links, rendered as `<nav><ul><li><a href>` with\n * `aria-current=\"page\"` on the current one. On screens below 1024 px the\n * navigation takes a second row and wraps.\n */\n readonly navItems = input<readonly HeaderNavItem[]>([]);\n /** Keep the header at the top while scrolling (`position: sticky`). */\n readonly sticky = input(true);\n\n // Labels (defaults are English; translate them in the app).\n /** Accessible name of the brand link. */\n readonly homeAriaLabel = input('Go to home');\n /** Accessible name of the hamburger button. */\n readonly hamburgerAriaLabel = input('Toggle sidebar menu');\n /**\n * Accessible name of the account menu trigger. With `userMenuTrigger=\"avatar\"`\n * the button is named this text, a comma and the initials it shows\n * (`Menü für Johanna Müller, JM`), so a voice-control user can say what they\n * see (WCAG 2.5.3). Nothing is added when `userName` gives no initials, or\n * when the text already contains them as a word. The name is the same with a\n * photo.\n * @default 'Open user menu'\n */\n readonly userMenuAriaLabel = input('Open user menu');\n /** Accessible name of the `<nav>` around `navItems`. */\n readonly navAriaLabel = input('Main navigation');\n /** Label of the theme button while the light theme is active. */\n readonly themeToDarkAriaLabel = input('Switch to dark mode');\n /** Label of the theme button while the dark theme is active. */\n readonly themeToLightAriaLabel = input('Switch to light mode');\n /**\n * Start of the context button's accessible name. The visible `contextLabel`\n * and `contextName` follow it (WCAG 2.5.3 Label in Name), unless the label\n * already contains them: `Context info, Tenant Acme Corp`.\n * @default 'Context info'\n */\n readonly contextAriaLabel = input('Context info');\n /** Label of the Profile entry in the account menu. */\n readonly profileLabel = input('Profile');\n /** Label of the Logout entry in the account menu. */\n readonly logoutLabel = input('Logout');\n\n readonly hamburgerClick = output<void>();\n readonly themeToggleClick = output<void>();\n readonly logoutClick = output<void>();\n readonly profileClick = output<void>();\n readonly contextClick = output<void>();\n\n private readonly injector = inject(Injector);\n private themeServiceInstance: ThemeService | null = null;\n\n /**\n * Resolved on first use, i.e. only when the theme button is shown: creating\n * the ThemeService reads and writes the theme class and localStorage, which a\n * site without a theme switch must not do.\n */\n protected get themeService(): ThemeService {\n return (this.themeServiceInstance ??= this.injector.get(ThemeService));\n }\n\n private readonly hamburger = viewChild('hamburger', { read: ElementRef<HTMLElement> });\n\n constructor() {\n // The hamburger is an <lc-button>; the ARIA state belongs on its native\n // <button> (the element that has the button role), not on the custom\n // element host — so it is reflected after render rather than bound in the\n // template.\n afterRenderEffect(() => {\n const button = this.hamburger()?.nativeElement.querySelector('button');\n if (!button) return;\n const open = this.sidenavOpen();\n const controls = this.sidenavId();\n if (open === undefined) {\n button.removeAttribute('aria-expanded');\n } else {\n button.setAttribute('aria-expanded', String(open));\n }\n if (controls) {\n button.setAttribute('aria-controls', controls);\n } else {\n button.removeAttribute('aria-controls');\n }\n });\n }\n\n /**\n * Name of the avatar trigger (AS-33, WCAG 2.5.3 Label in Name):\n * `userMenuAriaLabel`, a comma and the initials the avatar shows, so the\n * visible text is a word of the name. Built from the same function as the\n * avatar's initials and independent of the photo, so the prerendered name\n * and the page's agree. Nothing is added for the `?` placeholder or when\n * the label already holds the initials as a word (parentheticals dropped,\n * as axe-core 4.14 does); an empty label becomes the initials alone.\n */\n protected readonly avatarTriggerAriaLabel = computed(() => {\n const initials = ɵavatarInitials(this.userName());\n const label = this.userMenuAriaLabel();\n if (!/[\\p{L}\\p{N}]/u.test(initials)) return label;\n // toLowerCase, not toLocaleLowerCase: server and browser must agree.\n const words = label\n .replace(/\\([^()]*\\)/g, ' ')\n .toLowerCase()\n .split(/[^\\p{L}\\p{N}]+/u);\n if (words.includes(initials.toLowerCase())) return label;\n if (label.trim() === '') return initials;\n return `${label}, ${initials}`;\n });\n\n /**\n * Name of the context button (AS-33, WCAG 2.5.3 Label in Name):\n * `contextAriaLabel`, a comma and the visible `contextLabel` and\n * `contextName`, so a voice-control user can say what they see.\n */\n protected readonly contextButtonAriaLabel = computed(() =>\n nameWithText(this.contextAriaLabel(), [this.contextLabel(), this.contextName()].filter(Boolean).join(' ')),\n );\n\n /**\n * Get menu items for profile dropdown\n */\n protected readonly menuItems = computed<MenuItem[]>(() => {\n const items: MenuItem[] = [];\n\n // Add profile link if enabled\n if (this.showProfileMenuItem()) {\n items.push({\n id: 'profile',\n label: this.profileLabel(),\n icon: 'user',\n dividerAfter: true,\n });\n }\n\n // Add logout\n items.push({\n id: 'logout',\n label: this.logoutLabel(),\n icon: 'arrow-right-start-on-rectangle',\n variant: 'danger',\n });\n\n return items;\n });\n\n /**\n * Dropdown open state (using Angular signals)\n */\n private readonly dropdownOpen = signal<boolean>(false);\n\n /**\n * Get dropdown open state\n */\n isDropdownOpen(): boolean {\n return this.dropdownOpen();\n }\n\n /**\n * Toggle profile dropdown visibility\n */\n toggleDropdown(): void {\n this.dropdownOpen.set(!this.dropdownOpen());\n }\n\n /**\n * Close profile dropdown\n */\n closeDropdown(): void {\n this.dropdownOpen.set(false);\n }\n\n /**\n * Handle hamburger click\n */\n onHamburgerClick(): void {\n this.hamburgerClick.emit();\n }\n\n /**\n * Handle theme button click (separate button, not in menu). Toggles the\n * theme unless the app opted out via `autoToggleTheme`, then emits.\n */\n onThemeButtonClick(): void {\n if (this.autoToggleTheme()) {\n this.themeService.toggleTheme();\n }\n this.themeToggleClick.emit();\n }\n\n /**\n * Handle logout click\n */\n onLogoutClick(): void {\n this.logoutClick.emit();\n this.closeDropdown();\n }\n\n /**\n * Handle profile click\n */\n onProfileClick(): void {\n this.profileClick.emit();\n this.closeDropdown();\n }\n\n /**\n * Handle menu item click\n */\n onMenuItemClick(item: MenuItem): void {\n if (item.id === 'logout') {\n this.onLogoutClick();\n } else if (item.id === 'profile') {\n this.onProfileClick();\n }\n }\n}\n","<header\n class=\"lc-header\"\n [class.lc-header--dark]=\"theme() === 'dark'\"\n [class.lc-header--light]=\"theme() === 'light'\"\n [class.lc-header--size-sm]=\"size() === 'sm'\"\n [class.lc-header--size-md]=\"size() === 'md'\"\n [class.lc-header--size-lg]=\"size() === 'lg'\"\n [class.lc-header--size-xl]=\"size() === 'xl'\"\n [class.lc-header--has-nav]=\"navItems().length > 0\"\n [class.lc-header--static]=\"!sticky()\"\n [class.lc-header--transparent]=\"variant() === 'transparent'\"\n>\n <!-- Hamburger menu icon (mobile only) -->\n @if (showHamburger()) {\n <lc-button\n #hamburger\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"hamburgerAriaLabel()\"\n (clicked)=\"onHamburgerClick()\"\n class=\"lc-header__hamburger\"\n >\n <lc-icon name=\"bars-3\" size=\"sm\" [decorative]=\"true\" />\n </lc-button>\n }\n\n <!-- Logo (clickable, navigates to home) -->\n <div class=\"lc-header__brand\">\n @if (showLogo()) {\n @if (homeHref()) {\n <!-- Plain link: works without the router and without JavaScript. -->\n <a [href]=\"homeHref()\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n } @else {\n <a routerLink=\"/\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n }\n }\n\n @if (title()) {\n <div class=\"lc-header__title-group\">\n @switch (titleTag()) {\n @case ('h1') {\n <h1 class=\"lc-header__title\">{{ title() }}</h1>\n }\n @case ('h2') {\n <h2 class=\"lc-header__title\">{{ title() }}</h2>\n }\n @case ('h3') {\n <h3 class=\"lc-header__title\">{{ title() }}</h3>\n }\n @case ('p') {\n <p class=\"lc-header__title\">{{ title() }}</p>\n }\n @case ('div') {\n <div class=\"lc-header__title\">{{ title() }}</div>\n }\n @default {\n <span class=\"lc-header__title\">{{ title() }}</span>\n }\n }\n @if (subtitle()) {\n <span class=\"lc-header__subtitle\" [attr.title]=\"subtitle()\">{{ subtitle() }}</span>\n }\n </div>\n }\n </div>\n\n <!-- Main navigation: inline from 1024 px, its own wrapping row below. -->\n @if (navItems().length > 0) {\n <nav class=\"lc-header__nav\" [attr.aria-label]=\"navAriaLabel()\">\n <ul class=\"lc-header__nav-list\">\n @for (item of navItems(); track $index) {\n <li class=\"lc-header__nav-item\">\n <a\n class=\"lc-header__nav-link\"\n [href]=\"item.href\"\n [attr.aria-current]=\"item.current ? 'page' : null\"\n >{{ item.label }}</a>\n </li>\n }\n </ul>\n </nav>\n }\n\n <!-- Zero-width spacer on the brand's row: keeps 3.10's two gaps before the end\n group and the first row's height; grows in a has-nav header from 1024 px. -->\n <div class=\"lc-header__spacer\"></div>\n\n <!-- End of the bar: the end slot (e.g. a language link), theme toggle, context\n info and account menu as one group. It goes to the end of a second row\n when it doesn't fit beside the brand (AS-31). No role; the DOM order and\n so the focus order stay brand → nav → end. -->\n <div class=\"lc-header__end\">\n <ng-content select=\"[slot='end']\" />\n\n <!-- Theme toggle button -->\n @if (showThemeButton()) {\n <lc-button\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"themeService.isDark() ? themeToLightAriaLabel() : themeToDarkAriaLabel()\"\n (clicked)=\"onThemeButtonClick()\"\n class=\"lc-header__theme-toggle\"\n >\n <lc-icon [name]=\"themeService.isDark() ? 'sun' : 'moon'\" size=\"sm\" [decorative]=\"true\" />\n </lc-button>\n }\n\n <!-- Context info (e.g. tenant, organization, project) -->\n @if (contextName()) {\n <button\n type=\"button\"\n class=\"lc-header__context-info\"\n [attr.aria-label]=\"contextButtonAriaLabel()\"\n (click)=\"contextClick.emit()\"\n >\n <!-- A real space between label and name: the visible text reads\n \"Tenant Acme Corp\", not \"TenantAcme Corp\" (WCAG 2.5.3). The\n tooltip sits on the name, so it is not a description of the button. -->\n @if (contextLabel()) {\n <span class=\"lc-header__context-label\">{{ contextLabel() }}</span>&ngsp;\n }\n <span class=\"lc-header__context-name\" [attr.title]=\"contextName()\">{{ contextName() }}</span>\n </button>\n }\n\n <!-- User profile menu -->\n @if (showUserMenu()) {\n <lc-menu\n [items]=\"menuItems()\"\n [isOpen]=\"isDropdownOpen()\"\n position=\"bottom-right\"\n minWidth=\"min(220px, calc(100vw - 2rem))\"\n maxWidth=\"min(18rem, calc(100vw - 2rem))\"\n [size]=\"menuSize()\"\n (itemClick)=\"onMenuItemClick($event)\"\n (closed)=\"closeDropdown()\"\n >\n <!-- Menu header with avatar, name and email -->\n @if (userName() || userEmail()) {\n <div header class=\"lc-header__menu-header\">\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n [fallback]=\"userAvatarFallback()\"\n size=\"md\"\n />\n <div class=\"lc-header__menu-user-info\">\n @if (userName()) {\n <div class=\"lc-header__menu-user-name\">{{ userName() }}</div>\n }\n @if (userEmail()) {\n <div class=\"lc-header__menu-user-email\">{{ userEmail() }}</div>\n }\n </div>\n </div>\n }\n\n @if (userMenuTrigger() === 'avatar') {\n <button\n trigger\n class=\"lc-header__profile-trigger lc-header__profile-trigger--avatar\"\n type=\"button\"\n [attr.aria-label]=\"avatarTriggerAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n [fallback]=\"userAvatarFallback()\"\n [decorative]=\"true\"\n size=\"md\"\n />\n </button>\n } @else {\n <button\n trigger\n class=\"lc-header__profile-trigger\"\n type=\"button\"\n [attr.aria-label]=\"userMenuAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-icon name=\"user\" size=\"sm\" [decorative]=\"true\" />\n <lc-icon name=\"chevron-down\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </lc-menu>\n }\n </div>\n</header>\n\n<ng-template #brandLogo>\n <lc-logo\n [variant]=\"logo() ? 'full' : 'emblem'\"\n [size]=\"logoSize()\"\n [clickable]=\"false\"\n [colorMode]=\"theme() === 'dark' ? 'dark' : theme() === 'light' ? 'light' : 'auto'\"\n [src]=\"logoSrc()\"\n [emblemSrc]=\"logoEmblemSrc()\"\n [darkSrc]=\"logoDarkSrc()\"\n [darkEmblemSrc]=\"logoDarkEmblemSrc()\"\n [alt]=\"logoAlt() || title() || 'Logo'\"\n />\n</ng-template>\n"],"mappings":"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"}
|
|
@@ -347,7 +347,7 @@ var InputComponent = class InputComponent {
|
|
|
347
347
|
}],
|
|
348
348
|
ngImport: i0,
|
|
349
349
|
template: "<div class=\"input-wrapper\">\n <!-- Label -->\n @if (label()) {\n <!-- No whitespace before the *: the gap is its margin, and it never wraps onto a line alone -->\n <label [id]=\"inputId + '-label'\" [attr.for]=\"wrapsReadonlyValue() ? null : inputId\" class=\"input-label\">\n {{ label() }}@if (required() && requiredIndicator()) {<span class=\"required-indicator\" aria-hidden=\"true\">*</span>}\n </label>\n }\n\n <!-- Input Container -->\n <div\n class=\"input-container\"\n [class.input-xs]=\"size() === 'xs'\"\n [class.input-sm]=\"size() === 'sm'\"\n [class.input-md]=\"size() === 'md'\"\n [class.input-lg]=\"size() === 'lg'\"\n [class.input-invalid]=\"hasError\"\n [class.input-disabled]=\"isDisabled\"\n [class.input-readonly]=\"readonly()\"\n [class.input-readonly-wrap]=\"wrapsReadonlyValue()\"\n >\n <!-- Icon Before -->\n @if (iconBefore()) {\n <span class=\"input-icon input-icon-before\" aria-hidden=\"true\">\n <lc-icon [name]=\"iconBefore()!\" size=\"sm\" [decorative]=\"true\" />\n </span>\n }\n\n <!-- Read-only value that wraps (SI-10): a read-only textbox named by the label -->\n @if (wrapsReadonlyValue()) {\n <div\n #readonlyValueRef\n class=\"input-field input-readonly-value\"\n role=\"textbox\"\n aria-readonly=\"true\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"label() ? inputId + '-label' : null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n >{{ value() }}</div>\n }\n\n <!-- Input Element (hidden while the read-only value wraps; it keeps value, name and autocomplete) -->\n <input\n #inputRef\n [id]=\"inputId\"\n [type]=\"type()\"\n [value]=\"value()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [hidden]=\"wrapsReadonlyValue()\"\n [attr.maxlength]=\"maxLength() || null\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [attr.name]=\"name() ?? null\"\n [attr.autocapitalize]=\"autocapitalize() ?? null\"\n [attr.spellcheck]=\"spellcheck() === undefined ? null : spellcheck() ? 'true' : 'false'\"\n [attr.enterkeyhint]=\"enterkeyhint() ?? null\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-required]=\"required() || undefined\"\n [attr.aria-invalid]=\"hasError || undefined\"\n [attr.aria-describedby]=\"describedBy()\"\n class=\"input-field\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n <!-- Icon After -->\n @if (iconAfter()) {\n <span class=\"input-icon input-icon-after\" aria-hidden=\"true\">\n <lc-icon [name]=\"iconAfter()!\" size=\"sm\" [decorative]=\"true\" />\n </span>\n }\n </div>\n\n <!-- Helper Text / Error Message / Character Count -->\n @if (error() || helperText() || (showCharCount() && maxLength())) {\n <div class=\"input-footer\">\n <!-- Error Message -->\n @if (error()) {\n <p [id]=\"inputId + '-error'\" class=\"input-error\" [attr.role]=\"announceError() ? 'alert' : null\">\n {{ error() }}\n </p>\n }\n\n <!-- Helper Text -->\n @if (helperText() && !error()) {\n <p [id]=\"inputId + '-helper'\" class=\"input-helper\">\n {{ helperText() }}\n </p>\n }\n\n <!-- Character Count: always visible; spoken only near the limit (live region below) -->\n @if (showCharCount() && maxLength()) {\n <p class=\"char-count\">\n {{ charCount }} / {{ maxLength() }}\n </p>\n }\n </div>\n }\n\n @if (showCharCount() && maxLength()) {\n <span class=\"input-char-count-live\" aria-live=\"polite\">{{ charCountAnnouncement() }}</span>\n }\n</div>\n",
|
|
350
|
-
styles: [".input-wrapper{position:relative;display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%}.input-label{display:block;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-primary);margin-bottom:var(--spacing-1)}.input-label .required-indicator{color:var(--color-error-600);margin-inline-start:var(--spacing-1)}.input-container{position:relative;display:flex;align-items:center;width:100%;background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease)}.input-container:hover:not(.input-disabled):not(.input-readonly){border-color:var(--color-text-secondary)}.input-container:focus-within{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.input-container.input-invalid{border-color:var(--color-error-600)}.input-container.input-invalid:focus-within{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.input-container.input-disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.input-container.input-readonly{background-color:var(--color-surface-muted)}.input-container.input-readonly-wrap{height:auto;min-height:var(--lc-input-height);align-items:stretch}.input-readonly-value{display:flex;align-items:center;min-width:0;white-space:normal;overflow-wrap:anywhere;-webkit-user-select:text;user-select:text}.input-char-count-live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.input-field{flex:1;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background:transparent;border:none;outline:none}.input-field::placeholder{color:var(--color-text-secondary)}.input-field:disabled{cursor:not-allowed}.input-field:read-only{cursor:default}.input-field[type=number]::-webkit-inner-spin-button,.input-field[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.input-field[type=number]{-moz-appearance:textfield}.input-icon{display:flex;align-items:center;justify-content:center;color:var(--color-text-secondary);pointer-events:none}.input-icon .icon{width:1.25rem;height:1.25rem}.input-icon.input-icon-before{margin-left:var(--spacing-3);margin-right:var(--spacing-2)}.input-icon.input-icon-after{margin-left:var(--spacing-2);margin-right:var(--spacing-3)}.input-xs{--lc-input-height: var(--size-interactive-xs-height);height:var(--lc-input-height)}.input-xs .input-field{padding:var(--size-interactive-xs-padding);font-size:var(--size-interactive-xs-font-size)}.input-xs .icon{width:1rem;height:1rem}.input-sm{--lc-input-height: var(--size-interactive-sm-height);height:var(--lc-input-height)}.input-sm .input-field{padding:var(--size-interactive-sm-padding);font-size:var(--size-interactive-sm-font-size)}.input-md{--lc-input-height: var(--size-interactive-md-height);height:var(--lc-input-height)}.input-md .input-field{padding:var(--size-interactive-md-padding);font-size:var(--size-interactive-md-font-size)}.input-lg{--lc-input-height: var(--size-interactive-lg-height);height:var(--lc-input-height)}.input-lg .input-field{padding:var(--size-interactive-lg-padding);font-size:var(--size-interactive-lg-font-size)}.input-lg .icon{width:1.5rem;height:1.5rem}.input-footer{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--lc-density-gap-sm, var(--spacing-2));min-height:1.25rem}.input-error{flex:1;font-size:var(--font-size-xs);color:var(--color-error-600);margin:0}.input-helper{flex:1;font-size:var(--font-size-xs);color:var(--color-text-secondary);margin:0}.char-count{font-size:var(--font-size-xs);color:var(--color-text-secondary);white-space:nowrap;margin:0}\n"],
|
|
350
|
+
styles: [".input-wrapper{position:relative;display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%}.input-label{display:block;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-primary);margin-bottom:var(--spacing-1)}.input-label .required-indicator{color:var(--color-error-600);margin-inline-start:var(--spacing-1)}.input-container{position:relative;display:flex;align-items:center;width:100%;background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease)}.input-container:hover:not(.input-disabled):not(.input-readonly):not(:focus-within){border-color:var(--color-text-secondary)}.input-container:focus-within{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.input-container.input-invalid{border-color:var(--color-error-600)}.input-container.input-invalid:focus-within{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.input-container.input-disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.input-container.input-readonly{background-color:var(--color-surface-muted)}.input-container.input-readonly-wrap{height:auto;min-height:var(--lc-input-height);align-items:stretch}.input-readonly-value{display:flex;align-items:center;min-width:0;white-space:normal;overflow-wrap:anywhere;-webkit-user-select:text;user-select:text}.input-char-count-live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.input-field{flex:1;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background:transparent;border:none;outline:none}.input-field::placeholder{color:var(--color-text-secondary)}.input-field:disabled{cursor:not-allowed}.input-field:read-only{cursor:default}.input-field[type=number]::-webkit-inner-spin-button,.input-field[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.input-field[type=number]{-moz-appearance:textfield}.input-icon{display:flex;align-items:center;justify-content:center;color:var(--color-text-secondary);pointer-events:none}.input-icon .icon{width:1.25rem;height:1.25rem}.input-icon.input-icon-before{margin-left:var(--spacing-3);margin-right:var(--spacing-2)}.input-icon.input-icon-after{margin-left:var(--spacing-2);margin-right:var(--spacing-3)}.input-xs{--lc-input-height: var(--size-interactive-xs-height);height:var(--lc-input-height)}.input-xs .input-field{padding:var(--size-interactive-xs-padding);font-size:var(--size-interactive-xs-font-size)}.input-xs .icon{width:1rem;height:1rem}.input-sm{--lc-input-height: var(--size-interactive-sm-height);height:var(--lc-input-height)}.input-sm .input-field{padding:var(--size-interactive-sm-padding);font-size:var(--size-interactive-sm-font-size)}.input-md{--lc-input-height: var(--size-interactive-md-height);height:var(--lc-input-height)}.input-md .input-field{padding:var(--size-interactive-md-padding);font-size:var(--size-interactive-md-font-size)}.input-lg{--lc-input-height: var(--size-interactive-lg-height);height:var(--lc-input-height)}.input-lg .input-field{padding:var(--size-interactive-lg-padding);font-size:var(--size-interactive-lg-font-size)}.input-lg .icon{width:1.5rem;height:1.5rem}.input-footer{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--lc-density-gap-sm, var(--spacing-2));min-height:1.25rem}.input-error{flex:1;font-size:var(--font-size-xs);color:var(--color-error-600);margin:0}.input-helper{flex:1;font-size:var(--font-size-xs);color:var(--color-text-secondary);margin:0}.char-count{font-size:var(--font-size-xs);color:var(--color-text-secondary);white-space:nowrap;margin:0}\n"],
|
|
351
351
|
dependencies: [{
|
|
352
352
|
kind: "component",
|
|
353
353
|
type: IconComponent,
|
|
@@ -382,7 +382,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
382
382
|
multi: true
|
|
383
383
|
}],
|
|
384
384
|
template: "<div class=\"input-wrapper\">\n <!-- Label -->\n @if (label()) {\n <!-- No whitespace before the *: the gap is its margin, and it never wraps onto a line alone -->\n <label [id]=\"inputId + '-label'\" [attr.for]=\"wrapsReadonlyValue() ? null : inputId\" class=\"input-label\">\n {{ label() }}@if (required() && requiredIndicator()) {<span class=\"required-indicator\" aria-hidden=\"true\">*</span>}\n </label>\n }\n\n <!-- Input Container -->\n <div\n class=\"input-container\"\n [class.input-xs]=\"size() === 'xs'\"\n [class.input-sm]=\"size() === 'sm'\"\n [class.input-md]=\"size() === 'md'\"\n [class.input-lg]=\"size() === 'lg'\"\n [class.input-invalid]=\"hasError\"\n [class.input-disabled]=\"isDisabled\"\n [class.input-readonly]=\"readonly()\"\n [class.input-readonly-wrap]=\"wrapsReadonlyValue()\"\n >\n <!-- Icon Before -->\n @if (iconBefore()) {\n <span class=\"input-icon input-icon-before\" aria-hidden=\"true\">\n <lc-icon [name]=\"iconBefore()!\" size=\"sm\" [decorative]=\"true\" />\n </span>\n }\n\n <!-- Read-only value that wraps (SI-10): a read-only textbox named by the label -->\n @if (wrapsReadonlyValue()) {\n <div\n #readonlyValueRef\n class=\"input-field input-readonly-value\"\n role=\"textbox\"\n aria-readonly=\"true\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"label() ? inputId + '-label' : null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n >{{ value() }}</div>\n }\n\n <!-- Input Element (hidden while the read-only value wraps; it keeps value, name and autocomplete) -->\n <input\n #inputRef\n [id]=\"inputId\"\n [type]=\"type()\"\n [value]=\"value()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [hidden]=\"wrapsReadonlyValue()\"\n [attr.maxlength]=\"maxLength() || null\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [attr.name]=\"name() ?? null\"\n [attr.autocapitalize]=\"autocapitalize() ?? null\"\n [attr.spellcheck]=\"spellcheck() === undefined ? null : spellcheck() ? 'true' : 'false'\"\n [attr.enterkeyhint]=\"enterkeyhint() ?? null\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-required]=\"required() || undefined\"\n [attr.aria-invalid]=\"hasError || undefined\"\n [attr.aria-describedby]=\"describedBy()\"\n class=\"input-field\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n <!-- Icon After -->\n @if (iconAfter()) {\n <span class=\"input-icon input-icon-after\" aria-hidden=\"true\">\n <lc-icon [name]=\"iconAfter()!\" size=\"sm\" [decorative]=\"true\" />\n </span>\n }\n </div>\n\n <!-- Helper Text / Error Message / Character Count -->\n @if (error() || helperText() || (showCharCount() && maxLength())) {\n <div class=\"input-footer\">\n <!-- Error Message -->\n @if (error()) {\n <p [id]=\"inputId + '-error'\" class=\"input-error\" [attr.role]=\"announceError() ? 'alert' : null\">\n {{ error() }}\n </p>\n }\n\n <!-- Helper Text -->\n @if (helperText() && !error()) {\n <p [id]=\"inputId + '-helper'\" class=\"input-helper\">\n {{ helperText() }}\n </p>\n }\n\n <!-- Character Count: always visible; spoken only near the limit (live region below) -->\n @if (showCharCount() && maxLength()) {\n <p class=\"char-count\">\n {{ charCount }} / {{ maxLength() }}\n </p>\n }\n </div>\n }\n\n @if (showCharCount() && maxLength()) {\n <span class=\"input-char-count-live\" aria-live=\"polite\">{{ charCountAnnouncement() }}</span>\n }\n</div>\n",
|
|
385
|
-
styles: [".input-wrapper{position:relative;display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%}.input-label{display:block;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-primary);margin-bottom:var(--spacing-1)}.input-label .required-indicator{color:var(--color-error-600);margin-inline-start:var(--spacing-1)}.input-container{position:relative;display:flex;align-items:center;width:100%;background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease)}.input-container:hover:not(.input-disabled):not(.input-readonly){border-color:var(--color-text-secondary)}.input-container:focus-within{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.input-container.input-invalid{border-color:var(--color-error-600)}.input-container.input-invalid:focus-within{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.input-container.input-disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.input-container.input-readonly{background-color:var(--color-surface-muted)}.input-container.input-readonly-wrap{height:auto;min-height:var(--lc-input-height);align-items:stretch}.input-readonly-value{display:flex;align-items:center;min-width:0;white-space:normal;overflow-wrap:anywhere;-webkit-user-select:text;user-select:text}.input-char-count-live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.input-field{flex:1;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background:transparent;border:none;outline:none}.input-field::placeholder{color:var(--color-text-secondary)}.input-field:disabled{cursor:not-allowed}.input-field:read-only{cursor:default}.input-field[type=number]::-webkit-inner-spin-button,.input-field[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.input-field[type=number]{-moz-appearance:textfield}.input-icon{display:flex;align-items:center;justify-content:center;color:var(--color-text-secondary);pointer-events:none}.input-icon .icon{width:1.25rem;height:1.25rem}.input-icon.input-icon-before{margin-left:var(--spacing-3);margin-right:var(--spacing-2)}.input-icon.input-icon-after{margin-left:var(--spacing-2);margin-right:var(--spacing-3)}.input-xs{--lc-input-height: var(--size-interactive-xs-height);height:var(--lc-input-height)}.input-xs .input-field{padding:var(--size-interactive-xs-padding);font-size:var(--size-interactive-xs-font-size)}.input-xs .icon{width:1rem;height:1rem}.input-sm{--lc-input-height: var(--size-interactive-sm-height);height:var(--lc-input-height)}.input-sm .input-field{padding:var(--size-interactive-sm-padding);font-size:var(--size-interactive-sm-font-size)}.input-md{--lc-input-height: var(--size-interactive-md-height);height:var(--lc-input-height)}.input-md .input-field{padding:var(--size-interactive-md-padding);font-size:var(--size-interactive-md-font-size)}.input-lg{--lc-input-height: var(--size-interactive-lg-height);height:var(--lc-input-height)}.input-lg .input-field{padding:var(--size-interactive-lg-padding);font-size:var(--size-interactive-lg-font-size)}.input-lg .icon{width:1.5rem;height:1.5rem}.input-footer{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--lc-density-gap-sm, var(--spacing-2));min-height:1.25rem}.input-error{flex:1;font-size:var(--font-size-xs);color:var(--color-error-600);margin:0}.input-helper{flex:1;font-size:var(--font-size-xs);color:var(--color-text-secondary);margin:0}.char-count{font-size:var(--font-size-xs);color:var(--color-text-secondary);white-space:nowrap;margin:0}\n"]
|
|
385
|
+
styles: [".input-wrapper{position:relative;display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%}.input-label{display:block;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-primary);margin-bottom:var(--spacing-1)}.input-label .required-indicator{color:var(--color-error-600);margin-inline-start:var(--spacing-1)}.input-container{position:relative;display:flex;align-items:center;width:100%;background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease)}.input-container:hover:not(.input-disabled):not(.input-readonly):not(:focus-within){border-color:var(--color-text-secondary)}.input-container:focus-within{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.input-container.input-invalid{border-color:var(--color-error-600)}.input-container.input-invalid:focus-within{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.input-container.input-disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.input-container.input-readonly{background-color:var(--color-surface-muted)}.input-container.input-readonly-wrap{height:auto;min-height:var(--lc-input-height);align-items:stretch}.input-readonly-value{display:flex;align-items:center;min-width:0;white-space:normal;overflow-wrap:anywhere;-webkit-user-select:text;user-select:text}.input-char-count-live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.input-field{flex:1;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background:transparent;border:none;outline:none}.input-field::placeholder{color:var(--color-text-secondary)}.input-field:disabled{cursor:not-allowed}.input-field:read-only{cursor:default}.input-field[type=number]::-webkit-inner-spin-button,.input-field[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.input-field[type=number]{-moz-appearance:textfield}.input-icon{display:flex;align-items:center;justify-content:center;color:var(--color-text-secondary);pointer-events:none}.input-icon .icon{width:1.25rem;height:1.25rem}.input-icon.input-icon-before{margin-left:var(--spacing-3);margin-right:var(--spacing-2)}.input-icon.input-icon-after{margin-left:var(--spacing-2);margin-right:var(--spacing-3)}.input-xs{--lc-input-height: var(--size-interactive-xs-height);height:var(--lc-input-height)}.input-xs .input-field{padding:var(--size-interactive-xs-padding);font-size:var(--size-interactive-xs-font-size)}.input-xs .icon{width:1rem;height:1rem}.input-sm{--lc-input-height: var(--size-interactive-sm-height);height:var(--lc-input-height)}.input-sm .input-field{padding:var(--size-interactive-sm-padding);font-size:var(--size-interactive-sm-font-size)}.input-md{--lc-input-height: var(--size-interactive-md-height);height:var(--lc-input-height)}.input-md .input-field{padding:var(--size-interactive-md-padding);font-size:var(--size-interactive-md-font-size)}.input-lg{--lc-input-height: var(--size-interactive-lg-height);height:var(--lc-input-height)}.input-lg .input-field{padding:var(--size-interactive-lg-padding);font-size:var(--size-interactive-lg-font-size)}.input-lg .icon{width:1.5rem;height:1.5rem}.input-footer{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--lc-density-gap-sm, var(--spacing-2));min-height:1.25rem}.input-error{flex:1;font-size:var(--font-size-xs);color:var(--color-error-600);margin:0}.input-helper{flex:1;font-size:var(--font-size-xs);color:var(--color-text-secondary);margin:0}.char-count{font-size:var(--font-size-xs);color:var(--color-text-secondary);white-space:nowrap;margin:0}\n"]
|
|
386
386
|
}]
|
|
387
387
|
}],
|
|
388
388
|
propDecorators: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-input.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/input/input.component.ts","../../../../libs/angular-ui-kit/src/lib/input/input.component.html"],"sourcesContent":["/* eslint-disable @typescript-eslint/member-ordering */\nimport {\n Component,\n computed,\n input,\n model,\n output,\n signal,\n viewChild,\n ElementRef,\n ChangeDetectionStrategy,\n forwardRef,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { IconComponent } from '@lifecorner/angular-ui-kit/icon';\n\n/** Values of the native `autocapitalize` attribute. */\nexport type InputAutocapitalize = 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters';\n\n/** Values of the native `enterkeyhint` attribute (label of the on-screen keyboard's Enter key). */\nexport type InputEnterKeyHint = 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';\n\n/** Counter for generated ids: they follow creation order, so prerendered HTML is the same in every build. */\nlet nextUniqueId = 0;\n\n/**\n * Input component for single-line text form data entry.\n *\n * Features:\n * - Type variants (text, email, password, number, tel, url)\n * - Size presets (xs, sm, md, lg)\n * - Leading and trailing icon support\n * - Character count display with maxLength (announced only near the limit)\n * - Validation error message display\n * - Helper text support\n * - Disabled and readonly states (read-only values can wrap: `readonlyWrap`)\n * - Input purpose and keyboard hints: `autocomplete`, `name`, `autocapitalize`,\n * `spellcheck`, `enterkeyhint`\n * - ControlValueAccessor integration for reactive forms\n *\n * @example\n * ```html\n * <lc-input label=\"Name\" autocomplete=\"name\" autocapitalize=\"words\" [spellcheck]=\"false\" [(ngModel)]=\"name\" />\n * ```\n */\n@Component({\n selector: 'lc-input',\n imports: [IconComponent],\n templateUrl: './input.component.html',\n styleUrl: './input.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => InputComponent),\n multi: true,\n },\n ],\n})\nexport class InputComponent implements ControlValueAccessor {\n // Input Properties\n /**\n * Input label (displayed above input)\n */\n readonly label = input<string>();\n\n /**\n * Placeholder text\n * @default ''\n */\n readonly placeholder = input<string>('');\n\n /**\n * Input type\n * @default 'text'\n */\n readonly type = input<'text' | 'email' | 'password' | 'number' | 'tel' | 'url'>('text');\n\n /**\n * Size of the input\n * @default 'md'\n */\n readonly size = input<'xs' | 'sm' | 'md' | 'lg'>('md');\n\n /**\n * Whether the input is disabled\n * @default false\n */\n readonly disabled = input<boolean>(false);\n\n /**\n * Whether the input is read-only\n * @default false\n */\n readonly readonly = input<boolean>(false);\n\n /**\n * Read-only values wrap onto more lines instead of being clipped (WCAG 1.4.10):\n * the value is shown as text (a read-only textbox named by the label), and a\n * hidden native input keeps the value, `name` and `autocomplete` for forms and\n * password managers. Only applies while `readonly` is set.\n * @default false\n */\n readonly readonlyWrap = input<boolean>(false);\n\n /**\n * Whether the input is required\n * @default false\n */\n readonly required = input<boolean>(false);\n\n /**\n * Show the `*` after the label of a `required` field. `false` keeps the\n * required semantics (`required`, `aria-required`) without the asterisk —\n * for forms where every field is required.\n * @default true\n */\n readonly requiredIndicator = input<boolean>(true);\n\n /**\n * Error message to display (if validation fails). While it is set, the field\n * container carries the class `input-invalid` and the message renders as\n * `<p class=\"input-error\">`. Before 3.13 the container also carried\n * `input-error` (G-WL3).\n * @default undefined\n */\n readonly error = input<string>();\n\n /**\n * Helper text to display below input\n */\n readonly helperText = input<string>();\n\n /**\n * Icon to display before input text (Tabler icon name)\n * @example 'envelope'\n */\n readonly iconBefore = input<string>();\n\n /**\n * Icon to display after input text (Tabler icon name)\n * @example 'eye'\n */\n readonly iconAfter = input<string>();\n\n /**\n * Maximum number of characters\n */\n readonly maxLength = input<number>();\n\n /**\n * Whether to show character count\n * @default false\n */\n readonly showCharCount = input<boolean>(false);\n\n /**\n * Screen-reader announcement of the character count near the limit;\n * `{remaining}` is replaced.\n * @default 'Characters remaining: {remaining}'\n */\n readonly charCountRemainingLabel = input('Characters remaining: {remaining}');\n\n /**\n * Remaining characters from which the count is announced (the visible count\n * is always shown). Unset = the last 10 % of `maxLength` (at least 1).\n */\n readonly charCountAnnounceThreshold = input<number>();\n\n /**\n * ARIA label for accessibility\n */\n readonly ariaLabel = input<string>();\n\n /**\n * Native `autocomplete` — the input purpose (WCAG 1.3.5), so browsers and\n * password managers fill the field: `name`, `email`, `username`,\n * `username webauthn` (offers passkeys in the field), `current-password`,\n * `new-password`, `one-time-code`, `tel`, `off` … Unset = no attribute.\n */\n readonly autocomplete = input<string>();\n\n /** Native `name` of the inner `<input>` (form posts, password managers). Unset = no attribute. */\n readonly name = input<string>();\n\n /**\n * Native `autocapitalize` for on-screen keyboards: `off` for addresses,\n * user names and codes, `words` for names. Unset = no attribute.\n */\n readonly autocapitalize = input<InputAutocapitalize>();\n\n /** Native `spellcheck`: `false` for names, addresses and codes. Unset = no attribute. */\n readonly spellcheck = input<boolean>();\n\n /** Native `enterkeyhint`: the label of the on-screen keyboard's Enter key. Unset = no attribute. */\n readonly enterkeyhint = input<InputEnterKeyHint>();\n\n /**\n * Deprecated, no effect since 3.12. The `*` is decorative and hidden from\n * assistive technology, because the native `required` state is announced\n * already, in the screen reader's language; a name on the `*` made the field\n * say \"required\" twice. Kept so existing bindings compile.\n * @deprecated No effect since 3.12: the native `required` state is announced instead.\n * @default 'required'\n */\n readonly requiredAriaLabel = input('required');\n\n /**\n * Id of the native `<input>`. The label's `for`, the error (`<id>-error`),\n * the helper text (`<id>-helper`), the label id (`<id>-label`) and\n * `aria-describedby` derive from it, so an error summary can link to the\n * field (`<a href=\"#contact-email\">`) and prerendered HTML is the same in\n * every build. Unique in the document, no spaces. Unset (or empty) = a\n * generated `lc-input-<n>`, which follows creation order (on the server it\n * keeps counting across prerendered routes): set it on prerendered pages.\n * @default generated (lc-input-<n>)\n */\n readonly controlId = input<string | undefined>(undefined);\n\n /**\n * Announce the error message the moment it appears (`role=\"alert\"` on the\n * message). Set `false` when an `lc-alert` error summary above the form\n * already announces the errors (a page re-rendered after a failed submit,\n * e.g. 422), so they aren't read twice. The message stays visible, stays\n * linked through `aria-describedby` (read with the field), and the control\n * keeps `aria-invalid`.\n * @default true\n */\n readonly announceError = input<boolean>(true);\n\n /**\n * Current value (two-way bindable: `[value]` / `[(value)]`). Emits\n * `valueChange` whenever it changes — once per user keystroke, on `clear()`\n * and when a bound form control writes a value.\n */\n readonly value = model<string>('');\n\n // Output Events\n /**\n * Emitted when input receives focus\n */\n readonly focused = output<void>();\n\n /**\n * Emitted when input loses focus\n */\n readonly blurred = output<void>();\n\n /**\n * Emitted when Enter key is pressed\n */\n readonly enterPressed = output<void>();\n\n // Internal state\n /** Generated id, taken once per instance (also with `controlId`), so later ids don't shift. */\n private readonly generatedId = `lc-input-${nextUniqueId++}`;\n\n private readonly resolvedId = computed(() => this.controlId() || this.generatedId);\n\n /**\n * Resolved id of the native control: `controlId`, or the generated\n * `lc-input-<n>`. Read-only, same meaning as before 3.12.\n */\n get inputId(): string {\n return this.resolvedId();\n }\n\n // ViewChild reference\n private readonly inputElement = viewChild<ElementRef<HTMLInputElement>>('inputRef');\n private readonly readonlyValueElement = viewChild<ElementRef<HTMLElement>>('readonlyValueRef');\n\n // Internal disabled state (for ControlValueAccessor)\n private readonly _formDisabled = signal<boolean>(false);\n\n // ControlValueAccessor callbacks\n private onChange: (value: string) => void = () => { /* set by registerOnChange */ };\n private onTouched: () => void = () => { /* set by registerOnTouched */ };\n\n /** The read-only value is shown as wrapping text (SI-10). */\n protected readonly wrapsReadonlyValue = computed(() => this.readonly() && this.readonlyWrap());\n\n /** `aria-describedby`: only the texts that are rendered (the error replaces the helper text). */\n protected readonly describedBy = computed(() => {\n if (this.error()) return `${this.inputId}-error`;\n if (this.helperText()) return `${this.inputId}-helper`;\n return null;\n });\n\n /** Screen-reader text of the character count: empty until the limit is near. */\n protected readonly charCountAnnouncement = computed(() => {\n const max = this.maxLength();\n if (!this.showCharCount() || !max) return '';\n const remaining = Math.max(0, max - this.value().length);\n const threshold = this.charCountAnnounceThreshold() ?? Math.max(1, Math.ceil(max * 0.1));\n if (remaining > threshold) return '';\n return this.charCountRemainingLabel().replace('{remaining}', String(remaining));\n });\n\n /**\n * Computed disabled state from both input and form control\n */\n protected get isDisabled(): boolean {\n return this.disabled() || this._formDisabled();\n }\n\n /**\n * Gets current character count\n */\n protected get charCount(): number {\n return this.value().length;\n }\n\n /**\n * Determines if error state should be shown\n */\n protected get hasError(): boolean {\n return !!this.error();\n }\n\n /**\n * Programmatically focus the input (the visible value while `readonlyWrap` applies)\n */\n public focus(): void {\n if (this.wrapsReadonlyValue()) {\n this.readonlyValueElement()?.nativeElement.focus();\n return;\n }\n this.inputElement()?.nativeElement.focus();\n }\n\n /**\n * Programmatically select input text\n */\n public select(): void {\n const shown = this.wrapsReadonlyValue() ? this.readonlyValueElement()?.nativeElement : undefined;\n if (shown) {\n const selection = shown.ownerDocument.getSelection();\n const range = shown.ownerDocument.createRange();\n range.selectNodeContents(shown);\n selection?.removeAllRanges();\n selection?.addRange(range);\n return;\n }\n this.inputElement()?.nativeElement.select();\n }\n\n /**\n * Clear the input value\n */\n public clear(): void {\n this.value.set('');\n this.onChange('');\n }\n\n // ControlValueAccessor implementation\n writeValue(value: string | null): void {\n this.value.set(value || '');\n }\n\n registerOnChange(fn: (value: string) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this._formDisabled.set(isDisabled);\n }\n\n /**\n * Handles input value changes\n */\n protected onInput(event: Event): void {\n const target = event.target as HTMLInputElement;\n const newValue = target.value;\n // model.set() emits `valueChange` exactly once per actual change\n this.value.set(newValue);\n this.onChange(newValue);\n }\n\n /**\n * Handles input focus\n */\n protected onFocus(): void {\n this.focused.emit();\n }\n\n /**\n * Handles input blur\n */\n protected onBlur(): void {\n this.onTouched();\n this.blurred.emit();\n }\n\n /**\n * Handles keydown events\n */\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n this.enterPressed.emit();\n }\n }\n}\n","<div class=\"input-wrapper\">\n <!-- Label -->\n @if (label()) {\n <!-- No whitespace before the *: the gap is its margin, and it never wraps onto a line alone -->\n <label [id]=\"inputId + '-label'\" [attr.for]=\"wrapsReadonlyValue() ? null : inputId\" class=\"input-label\">\n {{ label() }}@if (required() && requiredIndicator()) {<span class=\"required-indicator\" aria-hidden=\"true\">*</span>}\n </label>\n }\n\n <!-- Input Container -->\n <div\n class=\"input-container\"\n [class.input-xs]=\"size() === 'xs'\"\n [class.input-sm]=\"size() === 'sm'\"\n [class.input-md]=\"size() === 'md'\"\n [class.input-lg]=\"size() === 'lg'\"\n [class.input-invalid]=\"hasError\"\n [class.input-disabled]=\"isDisabled\"\n [class.input-readonly]=\"readonly()\"\n [class.input-readonly-wrap]=\"wrapsReadonlyValue()\"\n >\n <!-- Icon Before -->\n @if (iconBefore()) {\n <span class=\"input-icon input-icon-before\" aria-hidden=\"true\">\n <lc-icon [name]=\"iconBefore()!\" size=\"sm\" [decorative]=\"true\" />\n </span>\n }\n\n <!-- Read-only value that wraps (SI-10): a read-only textbox named by the label -->\n @if (wrapsReadonlyValue()) {\n <div\n #readonlyValueRef\n class=\"input-field input-readonly-value\"\n role=\"textbox\"\n aria-readonly=\"true\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"label() ? inputId + '-label' : null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n >{{ value() }}</div>\n }\n\n <!-- Input Element (hidden while the read-only value wraps; it keeps value, name and autocomplete) -->\n <input\n #inputRef\n [id]=\"inputId\"\n [type]=\"type()\"\n [value]=\"value()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [hidden]=\"wrapsReadonlyValue()\"\n [attr.maxlength]=\"maxLength() || null\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [attr.name]=\"name() ?? null\"\n [attr.autocapitalize]=\"autocapitalize() ?? null\"\n [attr.spellcheck]=\"spellcheck() === undefined ? null : spellcheck() ? 'true' : 'false'\"\n [attr.enterkeyhint]=\"enterkeyhint() ?? null\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-required]=\"required() || undefined\"\n [attr.aria-invalid]=\"hasError || undefined\"\n [attr.aria-describedby]=\"describedBy()\"\n class=\"input-field\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n <!-- Icon After -->\n @if (iconAfter()) {\n <span class=\"input-icon input-icon-after\" aria-hidden=\"true\">\n <lc-icon [name]=\"iconAfter()!\" size=\"sm\" [decorative]=\"true\" />\n </span>\n }\n </div>\n\n <!-- Helper Text / Error Message / Character Count -->\n @if (error() || helperText() || (showCharCount() && maxLength())) {\n <div class=\"input-footer\">\n <!-- Error Message -->\n @if (error()) {\n <p [id]=\"inputId + '-error'\" class=\"input-error\" [attr.role]=\"announceError() ? 'alert' : null\">\n {{ error() }}\n </p>\n }\n\n <!-- Helper Text -->\n @if (helperText() && !error()) {\n <p [id]=\"inputId + '-helper'\" class=\"input-helper\">\n {{ helperText() }}\n </p>\n }\n\n <!-- Character Count: always visible; spoken only near the limit (live region below) -->\n @if (showCharCount() && maxLength()) {\n <p class=\"char-count\">\n {{ charCount }} / {{ maxLength() }}\n </p>\n }\n </div>\n }\n\n @if (showCharCount() && maxLength()) {\n <span class=\"input-char-count-live\" aria-live=\"polite\">{{ charCountAnnouncement() }}</span>\n }\n</div>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-input.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/input/input.component.ts","../../../../libs/angular-ui-kit/src/lib/input/input.component.html"],"sourcesContent":["/* eslint-disable @typescript-eslint/member-ordering */\nimport {\n Component,\n computed,\n input,\n model,\n output,\n signal,\n viewChild,\n ElementRef,\n ChangeDetectionStrategy,\n forwardRef,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { IconComponent } from '@lifecorner/angular-ui-kit/icon';\n\n/** Values of the native `autocapitalize` attribute. */\nexport type InputAutocapitalize = 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters';\n\n/** Values of the native `enterkeyhint` attribute (label of the on-screen keyboard's Enter key). */\nexport type InputEnterKeyHint = 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';\n\n/** Counter for generated ids: they follow creation order, so prerendered HTML is the same in every build. */\nlet nextUniqueId = 0;\n\n/**\n * Input component for single-line text form data entry.\n *\n * Features:\n * - Type variants (text, email, password, number, tel, url)\n * - Size presets (xs, sm, md, lg)\n * - Leading and trailing icon support\n * - Character count display with maxLength (announced only near the limit)\n * - Validation error message display\n * - Helper text support\n * - Disabled and readonly states (read-only values can wrap: `readonlyWrap`)\n * - Input purpose and keyboard hints: `autocomplete`, `name`, `autocapitalize`,\n * `spellcheck`, `enterkeyhint`\n * - ControlValueAccessor integration for reactive forms\n *\n * @example\n * ```html\n * <lc-input label=\"Name\" autocomplete=\"name\" autocapitalize=\"words\" [spellcheck]=\"false\" [(ngModel)]=\"name\" />\n * ```\n */\n@Component({\n selector: 'lc-input',\n imports: [IconComponent],\n templateUrl: './input.component.html',\n styleUrl: './input.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => InputComponent),\n multi: true,\n },\n ],\n})\nexport class InputComponent implements ControlValueAccessor {\n // Input Properties\n /**\n * Input label (displayed above input)\n */\n readonly label = input<string>();\n\n /**\n * Placeholder text\n * @default ''\n */\n readonly placeholder = input<string>('');\n\n /**\n * Input type\n * @default 'text'\n */\n readonly type = input<'text' | 'email' | 'password' | 'number' | 'tel' | 'url'>('text');\n\n /**\n * Size of the input\n * @default 'md'\n */\n readonly size = input<'xs' | 'sm' | 'md' | 'lg'>('md');\n\n /**\n * Whether the input is disabled\n * @default false\n */\n readonly disabled = input<boolean>(false);\n\n /**\n * Whether the input is read-only\n * @default false\n */\n readonly readonly = input<boolean>(false);\n\n /**\n * Read-only values wrap onto more lines instead of being clipped (WCAG 1.4.10):\n * the value is shown as text (a read-only textbox named by the label), and a\n * hidden native input keeps the value, `name` and `autocomplete` for forms and\n * password managers. Only applies while `readonly` is set.\n * @default false\n */\n readonly readonlyWrap = input<boolean>(false);\n\n /**\n * Whether the input is required\n * @default false\n */\n readonly required = input<boolean>(false);\n\n /**\n * Show the `*` after the label of a `required` field. `false` keeps the\n * required semantics (`required`, `aria-required`) without the asterisk —\n * for forms where every field is required.\n * @default true\n */\n readonly requiredIndicator = input<boolean>(true);\n\n /**\n * Error message to display (if validation fails). While it is set, the field\n * container carries the class `input-invalid` and the message renders as\n * `<p class=\"input-error\">`. Before 3.13 the container also carried\n * `input-error` (G-WL3).\n * @default undefined\n */\n readonly error = input<string>();\n\n /**\n * Helper text to display below input\n */\n readonly helperText = input<string>();\n\n /**\n * Icon to display before input text (Tabler icon name)\n * @example 'envelope'\n */\n readonly iconBefore = input<string>();\n\n /**\n * Icon to display after input text (Tabler icon name)\n * @example 'eye'\n */\n readonly iconAfter = input<string>();\n\n /**\n * Maximum number of characters\n */\n readonly maxLength = input<number>();\n\n /**\n * Whether to show character count\n * @default false\n */\n readonly showCharCount = input<boolean>(false);\n\n /**\n * Screen-reader announcement of the character count near the limit;\n * `{remaining}` is replaced.\n * @default 'Characters remaining: {remaining}'\n */\n readonly charCountRemainingLabel = input('Characters remaining: {remaining}');\n\n /**\n * Remaining characters from which the count is announced (the visible count\n * is always shown). Unset = the last 10 % of `maxLength` (at least 1).\n */\n readonly charCountAnnounceThreshold = input<number>();\n\n /**\n * ARIA label for accessibility\n */\n readonly ariaLabel = input<string>();\n\n /**\n * Native `autocomplete` — the input purpose (WCAG 1.3.5), so browsers and\n * password managers fill the field: `name`, `email`, `username`,\n * `username webauthn` (offers passkeys in the field), `current-password`,\n * `new-password`, `one-time-code`, `tel`, `off` … Unset = no attribute.\n */\n readonly autocomplete = input<string>();\n\n /** Native `name` of the inner `<input>` (form posts, password managers). Unset = no attribute. */\n readonly name = input<string>();\n\n /**\n * Native `autocapitalize` for on-screen keyboards: `off` for addresses,\n * user names and codes, `words` for names. Unset = no attribute.\n */\n readonly autocapitalize = input<InputAutocapitalize>();\n\n /** Native `spellcheck`: `false` for names, addresses and codes. Unset = no attribute. */\n readonly spellcheck = input<boolean>();\n\n /** Native `enterkeyhint`: the label of the on-screen keyboard's Enter key. Unset = no attribute. */\n readonly enterkeyhint = input<InputEnterKeyHint>();\n\n /**\n * Deprecated, no effect since 3.12. The `*` is decorative and hidden from\n * assistive technology, because the native `required` state is announced\n * already, in the screen reader's language; a name on the `*` made the field\n * say \"required\" twice. Kept so existing bindings compile.\n * @deprecated No effect since 3.12: the native `required` state is announced instead.\n * @default 'required'\n */\n readonly requiredAriaLabel = input('required');\n\n /**\n * Id of the native `<input>`. The label's `for`, the error (`<id>-error`),\n * the helper text (`<id>-helper`), the label id (`<id>-label`) and\n * `aria-describedby` derive from it, so an error summary can link to the\n * field (`<a href=\"#contact-email\">`) and prerendered HTML is the same in\n * every build. Unique in the document, no spaces. Unset (or empty) = a\n * generated `lc-input-<n>`, which follows creation order (on the server it\n * keeps counting across prerendered routes): set it on prerendered pages.\n * @default generated (lc-input-<n>)\n */\n readonly controlId = input<string | undefined>(undefined);\n\n /**\n * Announce the error message the moment it appears (`role=\"alert\"` on the\n * message). Set `false` when an `lc-alert` error summary above the form\n * already announces the errors (a page re-rendered after a failed submit,\n * e.g. 422), so they aren't read twice. The message stays visible, stays\n * linked through `aria-describedby` (read with the field), and the control\n * keeps `aria-invalid`.\n * @default true\n */\n readonly announceError = input<boolean>(true);\n\n /**\n * Current value (two-way bindable: `[value]` / `[(value)]`). Emits\n * `valueChange` whenever it changes — once per user keystroke, on `clear()`\n * and when a bound form control writes a value.\n */\n readonly value = model<string>('');\n\n // Output Events\n /**\n * Emitted when input receives focus\n */\n readonly focused = output<void>();\n\n /**\n * Emitted when input loses focus\n */\n readonly blurred = output<void>();\n\n /**\n * Emitted when Enter key is pressed\n */\n readonly enterPressed = output<void>();\n\n // Internal state\n /** Generated id, taken once per instance (also with `controlId`), so later ids don't shift. */\n private readonly generatedId = `lc-input-${nextUniqueId++}`;\n\n private readonly resolvedId = computed(() => this.controlId() || this.generatedId);\n\n /**\n * Resolved id of the native control: `controlId`, or the generated\n * `lc-input-<n>`. Read-only, same meaning as before 3.12.\n */\n get inputId(): string {\n return this.resolvedId();\n }\n\n // ViewChild reference\n private readonly inputElement = viewChild<ElementRef<HTMLInputElement>>('inputRef');\n private readonly readonlyValueElement = viewChild<ElementRef<HTMLElement>>('readonlyValueRef');\n\n // Internal disabled state (for ControlValueAccessor)\n private readonly _formDisabled = signal<boolean>(false);\n\n // ControlValueAccessor callbacks\n private onChange: (value: string) => void = () => { /* set by registerOnChange */ };\n private onTouched: () => void = () => { /* set by registerOnTouched */ };\n\n /** The read-only value is shown as wrapping text (SI-10). */\n protected readonly wrapsReadonlyValue = computed(() => this.readonly() && this.readonlyWrap());\n\n /** `aria-describedby`: only the texts that are rendered (the error replaces the helper text). */\n protected readonly describedBy = computed(() => {\n if (this.error()) return `${this.inputId}-error`;\n if (this.helperText()) return `${this.inputId}-helper`;\n return null;\n });\n\n /** Screen-reader text of the character count: empty until the limit is near. */\n protected readonly charCountAnnouncement = computed(() => {\n const max = this.maxLength();\n if (!this.showCharCount() || !max) return '';\n const remaining = Math.max(0, max - this.value().length);\n const threshold = this.charCountAnnounceThreshold() ?? Math.max(1, Math.ceil(max * 0.1));\n if (remaining > threshold) return '';\n return this.charCountRemainingLabel().replace('{remaining}', String(remaining));\n });\n\n /**\n * Computed disabled state from both input and form control\n */\n protected get isDisabled(): boolean {\n return this.disabled() || this._formDisabled();\n }\n\n /**\n * Gets current character count\n */\n protected get charCount(): number {\n return this.value().length;\n }\n\n /**\n * Determines if error state should be shown\n */\n protected get hasError(): boolean {\n return !!this.error();\n }\n\n /**\n * Programmatically focus the input (the visible value while `readonlyWrap` applies)\n */\n public focus(): void {\n if (this.wrapsReadonlyValue()) {\n this.readonlyValueElement()?.nativeElement.focus();\n return;\n }\n this.inputElement()?.nativeElement.focus();\n }\n\n /**\n * Programmatically select input text\n */\n public select(): void {\n const shown = this.wrapsReadonlyValue() ? this.readonlyValueElement()?.nativeElement : undefined;\n if (shown) {\n const selection = shown.ownerDocument.getSelection();\n const range = shown.ownerDocument.createRange();\n range.selectNodeContents(shown);\n selection?.removeAllRanges();\n selection?.addRange(range);\n return;\n }\n this.inputElement()?.nativeElement.select();\n }\n\n /**\n * Clear the input value\n */\n public clear(): void {\n this.value.set('');\n this.onChange('');\n }\n\n // ControlValueAccessor implementation\n writeValue(value: string | null): void {\n this.value.set(value || '');\n }\n\n registerOnChange(fn: (value: string) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this._formDisabled.set(isDisabled);\n }\n\n /**\n * Handles input value changes\n */\n protected onInput(event: Event): void {\n const target = event.target as HTMLInputElement;\n const newValue = target.value;\n // model.set() emits `valueChange` exactly once per actual change\n this.value.set(newValue);\n this.onChange(newValue);\n }\n\n /**\n * Handles input focus\n */\n protected onFocus(): void {\n this.focused.emit();\n }\n\n /**\n * Handles input blur\n */\n protected onBlur(): void {\n this.onTouched();\n this.blurred.emit();\n }\n\n /**\n * Handles keydown events\n */\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter') {\n this.enterPressed.emit();\n }\n }\n}\n","<div class=\"input-wrapper\">\n <!-- Label -->\n @if (label()) {\n <!-- No whitespace before the *: the gap is its margin, and it never wraps onto a line alone -->\n <label [id]=\"inputId + '-label'\" [attr.for]=\"wrapsReadonlyValue() ? null : inputId\" class=\"input-label\">\n {{ label() }}@if (required() && requiredIndicator()) {<span class=\"required-indicator\" aria-hidden=\"true\">*</span>}\n </label>\n }\n\n <!-- Input Container -->\n <div\n class=\"input-container\"\n [class.input-xs]=\"size() === 'xs'\"\n [class.input-sm]=\"size() === 'sm'\"\n [class.input-md]=\"size() === 'md'\"\n [class.input-lg]=\"size() === 'lg'\"\n [class.input-invalid]=\"hasError\"\n [class.input-disabled]=\"isDisabled\"\n [class.input-readonly]=\"readonly()\"\n [class.input-readonly-wrap]=\"wrapsReadonlyValue()\"\n >\n <!-- Icon Before -->\n @if (iconBefore()) {\n <span class=\"input-icon input-icon-before\" aria-hidden=\"true\">\n <lc-icon [name]=\"iconBefore()!\" size=\"sm\" [decorative]=\"true\" />\n </span>\n }\n\n <!-- Read-only value that wraps (SI-10): a read-only textbox named by the label -->\n @if (wrapsReadonlyValue()) {\n <div\n #readonlyValueRef\n class=\"input-field input-readonly-value\"\n role=\"textbox\"\n aria-readonly=\"true\"\n tabindex=\"0\"\n [attr.aria-labelledby]=\"label() ? inputId + '-label' : null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-describedby]=\"describedBy()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n >{{ value() }}</div>\n }\n\n <!-- Input Element (hidden while the read-only value wraps; it keeps value, name and autocomplete) -->\n <input\n #inputRef\n [id]=\"inputId\"\n [type]=\"type()\"\n [value]=\"value()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [hidden]=\"wrapsReadonlyValue()\"\n [attr.maxlength]=\"maxLength() || null\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [attr.name]=\"name() ?? null\"\n [attr.autocapitalize]=\"autocapitalize() ?? null\"\n [attr.spellcheck]=\"spellcheck() === undefined ? null : spellcheck() ? 'true' : 'false'\"\n [attr.enterkeyhint]=\"enterkeyhint() ?? null\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-required]=\"required() || undefined\"\n [attr.aria-invalid]=\"hasError || undefined\"\n [attr.aria-describedby]=\"describedBy()\"\n class=\"input-field\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n\n <!-- Icon After -->\n @if (iconAfter()) {\n <span class=\"input-icon input-icon-after\" aria-hidden=\"true\">\n <lc-icon [name]=\"iconAfter()!\" size=\"sm\" [decorative]=\"true\" />\n </span>\n }\n </div>\n\n <!-- Helper Text / Error Message / Character Count -->\n @if (error() || helperText() || (showCharCount() && maxLength())) {\n <div class=\"input-footer\">\n <!-- Error Message -->\n @if (error()) {\n <p [id]=\"inputId + '-error'\" class=\"input-error\" [attr.role]=\"announceError() ? 'alert' : null\">\n {{ error() }}\n </p>\n }\n\n <!-- Helper Text -->\n @if (helperText() && !error()) {\n <p [id]=\"inputId + '-helper'\" class=\"input-helper\">\n {{ helperText() }}\n </p>\n }\n\n <!-- Character Count: always visible; spoken only near the limit (live region below) -->\n @if (showCharCount() && maxLength()) {\n <p class=\"char-count\">\n {{ charCount }} / {{ maxLength() }}\n </p>\n }\n </div>\n }\n\n @if (showCharCount() && maxLength()) {\n <span class=\"input-char-count-live\" aria-live=\"polite\">{{ charCountAnnouncement() }}</span>\n }\n</div>\n"],"mappings":"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"}
|