@lifecorner/angular-ui-kit 3.11.0 → 3.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs +26 -2
- package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs +4 -4
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-character.mjs +18 -2
- package/fesm2022/lifecorner-angular-ui-kit-character.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-footer.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-footer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs +6 -1
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-icon.mjs +14 -5
- package/fesm2022/lifecorner-angular-ui-kit-icon.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-logo.mjs +115 -2
- package/fesm2022/lifecorner-angular-ui-kit-logo.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs +5 -1
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs.map +1 -1
- package/package.json +1 -1
- package/types/lifecorner-angular-ui-kit-avatar.d.ts +27 -1
- package/types/lifecorner-angular-ui-kit-character.d.ts +19 -0
- package/types/lifecorner-angular-ui-kit-icon.d.ts +19 -7
- package/types/lifecorner-angular-ui-kit-logo.d.ts +69 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-logo.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/logo/logo.component.ts","../../../../libs/angular-ui-kit/src/lib/logo/logo.component.html"],"sourcesContent":["import {\n Component,\n InjectionToken,\n input,\n inject,\n computed,\n ChangeDetectionStrategy,\n} from '@angular/core';\n\n/**\n * Injection token for the base path used to resolve the built-in\n * LifeCorner logo assets. Defaults to `'/assets'` so consuming apps\n * that copy the package's `assets/` folder to their public root keep\n * working out of the box.\n *\n * Override this token at the application root if your app serves\n * static files from a different prefix (e.g. `/static`, `/ui-kit`).\n *\n * @example\n * ```ts\n * providers: [\n * { provide: LC_LOGO_BASE_PATH, useValue: '/static/lc' },\n * ]\n * ```\n */\nexport const LC_LOGO_BASE_PATH = new InjectionToken<string>('LC_LOGO_BASE_PATH', {\n providedIn: 'root',\n factory: () => '/assets',\n});\n\n/** Sizes at or below 32 px, which use the small emblem (heavier arms, filled points). */\nconst SMALL_EMBLEM_SIZES: ReadonlySet<string> = new Set(['xs', 'sm']);\n\n/**\n * Logo component for displaying a brand identity.\n *\n * Defaults to the LifeCorner logo (Edu, the emblem, and the LifeCorner\n * lockup) but accepts custom `src` / `emblemSrc` (and optional `darkSrc` /\n * `darkEmblemSrc`) so consuming apps can drop in their own brand assets\n * without forking the component.\n *\n * Features:\n * - Full lockup and emblem-only variants; the emblem switches to its small\n * drawing at `xs` and `sm` (32 px and below)\n * - Multiple size options (xs, sm, md, lg, xl)\n * - Light and dark sources that follow the APP theme exactly as the theme\n * stylesheets do: dark under `:root.dark`, under a root without a theme\n * class (dark-first default), and under `:root.system` when the OS is dark;\n * light under `:root.light` and under `:root.system` when the OS is light.\n * `colorMode=\"light|dark\"` pins one source.\n * - The built-in logo ships its own dark drawings; nothing is inverted or\n * recoloured by CSS. A custom logo without a dark partner stays as it is.\n * - The logo is flat and fixed: never animated, posed or distorted.\n *\n * @example Default LifeCorner logo\n * ```html\n * <lc-logo variant=\"full\" size=\"md\"></lc-logo>\n * ```\n *\n * @example Custom brand logo\n * ```html\n * <lc-logo\n * src=\"/assets/acme-logo.svg\"\n * emblemSrc=\"/assets/acme-emblem.svg\"\n * darkSrc=\"/assets/acme-logo-dark.svg\"\n * alt=\"Acme Inc.\">\n * </lc-logo>\n * ```\n */\n@Component({\n selector: 'lc-logo',\n standalone: true,\n imports: [],\n templateUrl: './logo.component.html',\n styleUrls: ['./logo.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class LogoComponent {\n /**\n * Logo variant to display\n * - 'full': the lockup (emblem and name)\n * - 'emblem': just the emblem\n */\n readonly variant = input<'full' | 'emblem'>('full');\n\n /**\n * Size of the logo\n * - 'xs': 24px height (small emblem)\n * - 'sm': 32px height (small emblem)\n * - 'md': 48px height (default)\n * - 'lg': 64px height\n * - 'xl': 96px height\n */\n readonly size = input<'xs' | 'sm' | 'md' | 'lg' | 'xl'>('md');\n\n /**\n * Alt text for accessibility. Defaults to the name of the built-in logo;\n * set it to your brand name when you pass your own sources.\n */\n readonly alt = input('LifeCorner');\n\n /**\n * Makes the logo appear clickable\n */\n readonly clickable = input(false);\n\n /**\n * Which source to show.\n * - 'auto': follows the app theme (light source on light, dark source on dark)\n * - 'light': always the light source (for light backgrounds)\n * - 'dark': always the dark source (for dark backgrounds); falls back to the\n * light source when a custom logo has no dark partner\n */\n readonly colorMode = input<'auto' | 'light' | 'dark'>('auto');\n\n /**\n * Custom URL for the full logo. When set, overrides the built-in\n * LifeCorner lockup.\n */\n readonly src = input<string>('');\n\n /**\n * Custom URL for the emblem-only logo. When set, overrides the built-in\n * LifeCorner emblem at every size.\n */\n readonly emblemSrc = input<string>('');\n\n /**\n * Optional dark-theme URL for the full logo. When provided, the logo swaps\n * with the app theme (see `colorMode`). Without it a custom `src` is shown\n * on dark too; the built-in lockup brings its own dark drawing.\n */\n readonly darkSrc = input<string>('');\n\n /**\n * Optional dark-theme URL for the emblem-only logo.\n */\n readonly darkEmblemSrc = input<string>('');\n\n /** Whether the consumer supplied at least one custom source. */\n readonly hasCustomSrc = computed(\n () => !!this.src() || !!this.emblemSrc() || !!this.darkSrc() || !!this.darkEmblemSrc(),\n );\n\n private readonly basePath = inject(LC_LOGO_BASE_PATH);\n\n /** The built-in LifeCorner pair for the current variant and size. */\n private readonly builtIn = computed(() => {\n const base = this.basePath.replace(/\\/$/, '');\n if (this.variant() === 'emblem') {\n const small = SMALL_EMBLEM_SIZES.has(this.size()) ? '-small' : '';\n return {\n light: `${base}/lifecorner-emblem${small}.svg`,\n dark: `${base}/lifecorner-emblem${small}-on-dark.svg`,\n };\n }\n return {\n light: `${base}/lifecorner-logo.svg`,\n dark: `${base}/lifecorner-logo-on-dark.svg`,\n };\n });\n\n /** Custom light source for the current variant, or empty string. */\n private readonly customSrc = computed(() =>\n this.variant() === 'emblem' ? this.emblemSrc() : this.src(),\n );\n\n readonly logoSrc = computed(() => this.customSrc() || this.builtIn().light);\n\n /**\n * Dark-theme source for the current variant: the custom dark source, else\n * the built-in dark drawing — unless a custom light logo is set without a\n * dark partner (the kit never recolours a brand), then empty string.\n */\n readonly logoDarkSrc = computed(() => {\n const customDark = this.variant() === 'emblem' ? this.darkEmblemSrc() : this.darkSrc();\n if (customDark) {\n return customDark;\n }\n return this.customSrc() ? '' : this.builtIn().dark;\n });\n\n /**\n * Which sources are in the DOM. Without a dark source there is only the one\n * image. With one, an explicit `colorMode` renders that side alone; `auto`\n * renders BOTH and lets the stylesheet show the one matching the root theme\n * class — that way the swap follows the app theme (also when it is toggled\n * without `ThemeService`, e.g. Storybook), needs no JS, and is right on the\n * first paint.\n */\n readonly showLightSrc = computed(() => !this.logoDarkSrc() || this.colorMode() !== 'dark');\n readonly showDarkSrc = computed(() => !!this.logoDarkSrc() && this.colorMode() !== 'light');\n\n readonly logoClasses = computed(() => {\n const classes = [`size-${this.size()}`];\n if (this.clickable()) {\n classes.push('clickable');\n }\n return classes.join(' ');\n });\n}\n","@if (showLightSrc()) {\n <img\n [src]=\"logoSrc()\"\n [alt]=\"alt()\"\n [class]=\"logoClasses()\"\n class=\"lc-logo\"\n [class.lc-logo--light-src]=\"showDarkSrc()\"\n />\n}\n@if (showDarkSrc()) {\n <img\n [src]=\"logoDarkSrc()\"\n [alt]=\"alt()\"\n [class]=\"logoClasses()\"\n class=\"lc-logo\"\n [class.lc-logo--dark-src]=\"showLightSrc()\"\n />\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-logo.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/logo/logo.component.ts","../../../../libs/angular-ui-kit/src/lib/logo/logo.component.html"],"sourcesContent":["import {\n Component,\n InjectionToken,\n input,\n inject,\n computed,\n ChangeDetectionStrategy,\n} from '@angular/core';\n\n/**\n * Injection token for the base path used to resolve the built-in\n * LifeCorner logo assets. Defaults to `'/assets'` so consuming apps\n * that copy the package's `assets/` folder to their public root keep\n * working out of the box.\n *\n * Override this token at the application root if your app serves\n * static files from a different prefix (e.g. `/static`, `/ui-kit`).\n *\n * @example\n * ```ts\n * providers: [\n * { provide: LC_LOGO_BASE_PATH, useValue: '/static/lc' },\n * ]\n * ```\n */\nexport const LC_LOGO_BASE_PATH = new InjectionToken<string>('LC_LOGO_BASE_PATH', {\n providedIn: 'root',\n factory: () => '/assets',\n});\n\n/** Sizes at or below 32 px, which use the small emblem (heavier arms, filled points). */\nconst SMALL_EMBLEM_SIZES: ReadonlySet<string> = new Set(['xs', 'sm']);\n\n/** The CSS height of each size in px, which is also the built-in emblem's square (3.11.2, G-38). */\nconst EMBLEM_PX: Readonly<Record<'xs' | 'sm' | 'md' | 'lg' | 'xl', number>> = { xs: 24, sm: 32, md: 48, lg: 64, xl: 96 };\n\n/** The built-in lockup files' own size (viewBox and `width`/`height` of both SVGs). */\nconst LOCKUP_SIZE = { width: 485, height: 100 } as const;\n\n/** The `width`/`height` pair written on one `<img>`; `null` writes no size attributes. */\ntype IntrinsicSize = { readonly width: number; readonly height: number } | null;\n\n/**\n * `srcWidth=\"160\"` from a template is the number 160. A finite value > 0 is\n * rounded to whole px; `''`, `0`, negative values, `NaN`, `null` and\n * `undefined` become `undefined` (no attribute).\n */\nfunction toIntrinsicSize(value: number | string | null | undefined): number | undefined {\n if (value === null || value === undefined || value === '') {\n return undefined;\n }\n const px = Number(value);\n return Number.isFinite(px) && px > 0 ? Math.round(px) : undefined;\n}\n\n/** A pair only when both values are defined. */\nfunction pair(width: number | undefined, height: number | undefined): IntrinsicSize {\n return width !== undefined && height !== undefined ? { width, height } : null;\n}\n\n/**\n * Logo component for displaying a brand identity.\n *\n * Defaults to the LifeCorner logo (Edu, the emblem, and the LifeCorner\n * lockup) but accepts custom `src` / `emblemSrc` (and optional `darkSrc` /\n * `darkEmblemSrc`) so consuming apps can drop in their own brand assets\n * without forking the component.\n *\n * Features:\n * - Full lockup and emblem-only variants; the emblem switches to its small\n * drawing at `xs` and `sm` (32 px and below)\n * - Multiple size options (xs, sm, md, lg, xl)\n * - Light and dark sources that follow the APP theme exactly as the theme\n * stylesheets do: dark under `:root.dark`, under a root without a theme\n * class (dark-first default), and under `:root.system` when the OS is dark;\n * light under `:root.light` and under `:root.system` when the OS is light.\n * `colorMode=\"light|dark\"` pins one source.\n * - The built-in logo ships its own dark drawings; nothing is inverted or\n * recoloured by CSS. A custom logo without a dark partner stays as it is.\n * - The logo is flat and fixed: never animated, posed or distorted.\n * - Every built-in `<img>` carries its file's intrinsic `width`/`height`\n * (3.11.2, G-38), so the browser reserves the box before the file loads;\n * for your own files set `srcWidth`/`srcHeight` and\n * `emblemSrcWidth`/`emblemSrcHeight`.\n *\n * @example Default LifeCorner logo\n * ```html\n * <lc-logo variant=\"full\" size=\"md\"></lc-logo>\n * ```\n *\n * @example Custom brand logo\n * ```html\n * <lc-logo\n * src=\"/assets/acme-logo.svg\"\n * emblemSrc=\"/assets/acme-emblem.svg\"\n * darkSrc=\"/assets/acme-logo-dark.svg\"\n * alt=\"Acme Inc.\">\n * </lc-logo>\n * ```\n */\n@Component({\n selector: 'lc-logo',\n standalone: true,\n imports: [],\n templateUrl: './logo.component.html',\n styleUrls: ['./logo.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class LogoComponent {\n /**\n * Logo variant to display\n * - 'full': the lockup (emblem and name)\n * - 'emblem': just the emblem\n */\n readonly variant = input<'full' | 'emblem'>('full');\n\n /**\n * Size of the logo\n * - 'xs': 24px height (small emblem)\n * - 'sm': 32px height (small emblem)\n * - 'md': 48px height (default)\n * - 'lg': 64px height\n * - 'xl': 96px height\n *\n * With the built-in files the `<img>` carries the file's intrinsic size as\n * `width`/`height`: the lockup 485 × 100 at every size, the emblem the\n * size's px squared (24 … 96). CSS still sets the rendered height.\n * @default 'md'\n */\n readonly size = input<'xs' | 'sm' | 'md' | 'lg' | 'xl'>('md');\n\n /**\n * Alt text for accessibility. Defaults to the name of the built-in logo;\n * set it to your brand name when you pass your own sources.\n */\n readonly alt = input('LifeCorner');\n\n /**\n * Makes the logo appear clickable\n */\n readonly clickable = input(false);\n\n /**\n * Which source to show.\n * - 'auto': follows the app theme (light source on light, dark source on dark)\n * - 'light': always the light source (for light backgrounds)\n * - 'dark': always the dark source (for dark backgrounds); falls back to the\n * light source when a custom logo has no dark partner\n */\n readonly colorMode = input<'auto' | 'light' | 'dark'>('auto');\n\n /**\n * Custom URL for the full logo. When set, overrides the built-in\n * LifeCorner lockup.\n */\n readonly src = input<string>('');\n\n /**\n * Custom URL for the emblem-only logo. When set, overrides the built-in\n * LifeCorner emblem at every size.\n */\n readonly emblemSrc = input<string>('');\n\n /**\n * Optional dark-theme URL for the full logo. When provided, the logo swaps\n * with the app theme (see `colorMode`). Without it a custom `src` is shown\n * on dark too; the built-in lockup brings its own dark drawing.\n */\n readonly darkSrc = input<string>('');\n\n /**\n * Optional dark-theme URL for the emblem-only logo.\n */\n readonly darkEmblemSrc = input<string>('');\n\n /**\n * Intrinsic width in px of your `src` file (and `darkSrc`), written as the\n * `<img>` `width`. Set it together with `srcHeight` so the browser reserves\n * the logo's box before the file loads; `size` still sets the rendered\n * height. Without both, no size attributes are written.\n * @default undefined\n */\n readonly srcWidth = input<number | undefined, number | string | null | undefined>(undefined, {\n transform: toIntrinsicSize,\n });\n\n /**\n * Intrinsic height in px of your `src` file (and `darkSrc`). See `srcWidth`.\n * @default undefined\n */\n readonly srcHeight = input<number | undefined, number | string | null | undefined>(undefined, {\n transform: toIntrinsicSize,\n });\n\n /**\n * Intrinsic width in px of your `emblemSrc` file (and `darkEmblemSrc`),\n * written as the `<img>` `width`; set it together with `emblemSrcHeight`.\n * @default undefined\n */\n readonly emblemSrcWidth = input<number | undefined, number | string | null | undefined>(undefined, {\n transform: toIntrinsicSize,\n });\n\n /**\n * Intrinsic height in px of your `emblemSrc` file (and `darkEmblemSrc`).\n * See `emblemSrcWidth`.\n * @default undefined\n */\n readonly emblemSrcHeight = input<number | undefined, number | string | null | undefined>(undefined, {\n transform: toIntrinsicSize,\n });\n\n /** Whether the consumer supplied at least one custom source. */\n readonly hasCustomSrc = computed(\n () => !!this.src() || !!this.emblemSrc() || !!this.darkSrc() || !!this.darkEmblemSrc(),\n );\n\n private readonly basePath = inject(LC_LOGO_BASE_PATH);\n\n /** The built-in LifeCorner pair for the current variant and size. */\n private readonly builtIn = computed(() => {\n const base = this.basePath.replace(/\\/$/, '');\n if (this.variant() === 'emblem') {\n const small = SMALL_EMBLEM_SIZES.has(this.size()) ? '-small' : '';\n return {\n light: `${base}/lifecorner-emblem${small}.svg`,\n dark: `${base}/lifecorner-emblem${small}-on-dark.svg`,\n };\n }\n return {\n light: `${base}/lifecorner-logo.svg`,\n dark: `${base}/lifecorner-logo-on-dark.svg`,\n };\n });\n\n /** Custom light source for the current variant, or empty string. */\n private readonly customSrc = computed(() =>\n this.variant() === 'emblem' ? this.emblemSrc() : this.src(),\n );\n\n readonly logoSrc = computed(() => this.customSrc() || this.builtIn().light);\n\n /**\n * Dark-theme source for the current variant: the custom dark source, else\n * the built-in dark drawing — unless a custom light logo is set without a\n * dark partner (the kit never recolours a brand), then empty string.\n */\n readonly logoDarkSrc = computed(() => {\n const customDark = this.variant() === 'emblem' ? this.darkEmblemSrc() : this.darkSrc();\n if (customDark) {\n return customDark;\n }\n return this.customSrc() ? '' : this.builtIn().dark;\n });\n\n /**\n * Which sources are in the DOM. Without a dark source there is only the one\n * image. With one, an explicit `colorMode` renders that side alone; `auto`\n * renders BOTH and lets the stylesheet show the one matching the root theme\n * class — that way the swap follows the app theme (also when it is toggled\n * without `ThemeService`, e.g. Storybook), needs no JS, and is right on the\n * first paint.\n */\n readonly showLightSrc = computed(() => !this.logoDarkSrc() || this.colorMode() !== 'dark');\n readonly showDarkSrc = computed(() => !!this.logoDarkSrc() && this.colorMode() !== 'light');\n\n /** The built-in file's own size: the lockup 485 × 100, the emblem the size's px squared. */\n private readonly builtInSize = computed<IntrinsicSize>(() => {\n if (this.variant() === 'emblem') {\n const px = EMBLEM_PX[this.size()];\n return { width: px, height: px };\n }\n return LOCKUP_SIZE;\n });\n\n /** The consumer's pair for the current variant (a dark file shares its light partner's pair). */\n private readonly customSize = computed<IntrinsicSize>(() =>\n this.variant() === 'emblem'\n ? pair(this.emblemSrcWidth(), this.emblemSrcHeight())\n : pair(this.srcWidth(), this.srcHeight()),\n );\n\n /** `width`/`height` of the light `<img>`: follows the file it shows (G-38). */\n protected readonly lightSize = computed<IntrinsicSize>(() =>\n this.customSrc() ? this.customSize() : this.builtInSize(),\n );\n\n /** `width`/`height` of the dark `<img>`: follows the file it shows (G-38). */\n protected readonly darkSize = computed<IntrinsicSize>(() => {\n const customDark = this.variant() === 'emblem' ? this.darkEmblemSrc() : this.darkSrc();\n return customDark ? this.customSize() : this.builtInSize();\n });\n\n readonly logoClasses = computed(() => {\n const classes = [`size-${this.size()}`];\n if (this.clickable()) {\n classes.push('clickable');\n }\n return classes.join(' ');\n });\n}\n","@if (showLightSrc()) {\n <img\n [src]=\"logoSrc()\"\n [alt]=\"alt()\"\n [attr.width]=\"lightSize()?.width ?? null\"\n [attr.height]=\"lightSize()?.height ?? null\"\n [class]=\"logoClasses()\"\n class=\"lc-logo\"\n [class.lc-logo--light-src]=\"showDarkSrc()\"\n />\n}\n@if (showDarkSrc()) {\n <img\n [src]=\"logoDarkSrc()\"\n [alt]=\"alt()\"\n [attr.width]=\"darkSize()?.width ?? null\"\n [attr.height]=\"darkSize()?.height ?? null\"\n [class]=\"logoClasses()\"\n class=\"lc-logo\"\n [class.lc-logo--dark-src]=\"showLightSrc()\"\n />\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-sidenav.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/sidenav/sidenav.component.ts","../../../../libs/angular-ui-kit/src/lib/sidenav/sidenav.component.html"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n signal,\n computed,\n input,\n output,\n model,\n effect,\n untracked,\n HostListener,\n OnDestroy,\n inject,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { NgTemplateOutlet, NgStyle } from '@angular/common';\nimport { NavigationEnd, Router, RouterLink } from '@angular/router';\nimport { filter } from 'rxjs';\nimport { A11yModule } from '@angular/cdk/a11y';\nimport { NavigationItem } from '@lifecorner/angular-ui-kit/models';\nimport {\n currentItemParents,\n currentNavigationItem,\n navigationLinks,\n navigationPath,\n sortNavigationItems,\n} from '@lifecorner/angular-ui-kit/internal/navigation';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHEVRON_DOWN, ICON_CHEVRON_LEFT, ICON_CHEVRON_RIGHT } from '@lifecorner/angular-ui-kit/icons';\nimport { BadgeComponent } from '@lifecorner/angular-ui-kit/badge';\nimport { LogoComponent } from '@lifecorner/angular-ui-kit/logo';\n\nexport type SidenavPosition = 'left' | 'right';\nexport type SidenavMode = 'drawer' | 'docked';\n\n/**\n * Surface of the docked sidenav: `default` is the rail on `--color-sidebar`\n * with a border; `transparent` has no background and no border and draws the\n * items as 48 px pills (the side navigation on the page, \"Weite\"). A drawer\n * keeps its surface in both.\n */\nexport type SidenavVariant = 'default' | 'transparent';\n\n/**\n * Sidenav component for application navigation sidebar.\n *\n * Features:\n * - Drawer (overlay) and docked (persistent) modes\n * - Responsive mobile mode — docked automatically switches to drawer below a configurable breakpoint\n * - Collapsed icon-rail mode (narrow 56px sidebar with icons only and hover tooltips)\n * - Integrated logo area with collapse-toggle (sidebar-first layouts)\n * - Hierarchical navigation with collapsible groups (up to 3 levels)\n * - Section headlines for item grouping with optional action buttons\n * - Action buttons on any item (hover-reveal)\n * - Badge support on items (count / status indicator)\n * - One current item, announced and painted alike: the link for `activeRoute`\n * (or, without it, the one the router's URL matches) gets\n * `aria-current=\"page\"` and the current look, every other link neither\n * (AS-16). No hover color change on the current item\n * - Keyboard navigation support (Escape closes drawer)\n * - Configurable width and position (left/right)\n * - Optional backdrop overlay\n * - Theme variants: auto, light, dark (with teal accent for dark mode)\n * - `variant=\"transparent\"`: no rail background or border, items as 48 px\n * pills with 16 px labels, the current one on `--color-surface-selected`\n * - Items are at least 44 px high in every density; the current item's ink is\n * `--color-on-surface-selected` (AA on the selected tint)\n * - Accessible: the inner `<nav>` is the navigation landmark; in drawer mode\n * the panel is a modal dialog (`role=\"dialog\"`, focus moved to the close\n * button on open, trapped while open, restored on close)\n *\n * @example\n * ```html\n * <lc-sidenav\n * [isOpen]=\"isOpen\"\n * mode=\"docked\"\n * [(collapsed)]=\"isCollapsed\"\n * [showLogo]=\"true\"\n * logoSize=\"md\"\n * [mobileBreakpoint]=\"768\"\n * [items]=\"navItems\"\n * activeRoute=\"/dashboard\"\n * theme=\"dark\"\n * (closed)=\"isOpen = false\"\n * (itemClicked)=\"navigate($event)\"\n * (itemAction)=\"onAction($event)\" />\n * ```\n */\n@Component({\n selector: 'lc-sidenav',\n standalone: true,\n imports: [NgTemplateOutlet, NgStyle, RouterLink, A11yModule, IconComponent, BadgeComponent, LogoComponent],\n viewProviders: [ɵprovideKitIcons([ICON_CHEVRON_DOWN, ICON_CHEVRON_LEFT, ICON_CHEVRON_RIGHT])],\n templateUrl: './sidenav.component.html',\n styleUrl: './sidenav.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class.lc-sidenav-container]': 'true',\n '[class.lc-sidenav-container--docked]': \"effectiveMode() === 'docked'\",\n '[class.lc-sidenav-container--open]': 'isOpen()',\n },\n})\nexport class SidenavComponent implements OnDestroy {\n private readonly router = inject(Router);\n\n /**\n * The router's URL, updated on every `NavigationEnd`. Before the first\n * navigation it is the router's initial URL (`/`). Read only when\n * `activeRoute` is empty.\n */\n private readonly routerUrl = signal(this.router.url);\n\n /** Whether the sidenav is collapsed to icon-only rail (two-way bindable) */\n readonly collapsed = model(false);\n\n /** Whether to show the logo at the top of the sidenav */\n readonly showLogo = input(false);\n\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. */\n readonly logoAlt = input('');\n\n /** Size of the brand logo (forwarded to inner `<lc-logo>`). Defaults to `md` for a prominent brand block aligned with `<lc-header size=\"md\">` (both 64px). */\n readonly logoSize = input<'xs' | 'sm' | 'md' | 'lg' | 'xl'>('md');\n\n /** Whether the sidenav is open */\n readonly isOpen = input(false);\n\n /** Display mode: 'drawer' (overlay) or 'docked' (persistent sidebar) */\n readonly mode = input<SidenavMode>('drawer');\n\n /** Mobile breakpoint in pixels. Below this width, docked mode switches to drawer. */\n readonly mobileBreakpoint = input(768);\n\n /** Whether the viewport is below the mobile breakpoint */\n readonly isMobile = signal(false);\n\n /** Effective mode: switches docked → drawer on mobile */\n readonly effectiveMode = computed(() => {\n if (this.isMobile() && this.mode() === 'docked') {\n return 'drawer' as SidenavMode;\n }\n return this.mode();\n });\n\n private mediaQuery: MediaQueryList | null = null;\n private mediaHandler = (e: MediaQueryListEvent) => this.isMobile.set(e.matches);\n\n /** Position of the sidenav (left or right) */\n readonly position = input<SidenavPosition>('left');\n\n /** Width of the sidenav drawer */\n readonly width = input('320px');\n\n /**\n * ARIA label of the navigation landmark (the inner `<nav>`) and, in drawer\n * mode, of the dialog panel.\n */\n readonly ariaLabel = input('Side navigation');\n\n /** Whether to show the overlay backdrop */\n readonly hasOverlay = input(true);\n\n /**\n * Navigation items (`NavigationItem[]`): `id`, `icon`, `label`, `route`,\n * `displayOrder` (sort order, 1 = first); optional `children`\n * (`NavigationItem[]`, a collapsible group, up to 3 levels), `isSection`\n * (renders `label` as a section headline over its `children`), `badge`\n * (`{ value: string | number; variant?: 'default' | 'primary' | 'success' |\n * 'warning' | 'error' | 'info' }`), `action` (`{ icon: string; ariaLabel?:\n * string }`, a button that emits `itemAction`), `requiredRole` (for the\n * app's own filtering; not evaluated here). Items link with `routerLink`;\n * exactly one link, the current item (see `activeRoute`), gets\n * `aria-current=\"page\"`.\n * @default []\n */\n readonly items = input<NavigationItem[]>([]);\n\n /**\n * The current route. When set, the first link (in display order) whose\n * `route` equals it is the current item: it alone gets `aria-current=\"page\"`\n * and the current look, whatever the router matches. When empty, the\n * sidenav follows the router: the link whose route equals the URL's path is\n * current, otherwise the one with the longest route the path starts with\n * (`/household` on `/household/members`; `/` only on `/`). Routes are\n * compared as written, so give them as absolute paths (`'/household'`).\n * @default ''\n */\n readonly activeRoute = input('');\n\n /** Theme variant for the sidenav */\n readonly theme = input<'light' | 'dark' | 'auto'>('auto');\n\n /**\n * Surface of the docked sidenav: `default` (the rail with background and\n * border) or `transparent` (no background, no border, items as 48 px pills\n * with radius full and 16 px labels; the current one on\n * `--color-surface-selected`). A drawer keeps its surface.\n */\n readonly variant = input<SidenavVariant>('default');\n\n /** Accessible name of the logo button that collapses/expands the sidebar. */\n readonly toggleAriaLabel = input('Toggle sidebar');\n\n /** Accessible name of the collapse button. Empty: \"Collapse navigation to the left/right\" by `position`. */\n readonly collapseAriaLabel = input('');\n\n /** Tooltip of the collapse button. */\n readonly collapseTitle = input('Collapse sidebar');\n\n /** Accessible name of the close button (drawer mode). */\n readonly closeAriaLabel = input('Close navigation');\n\n /**\n * Ids of the expanded parent items — the single source of truth for\n * `isExpanded`. Seeded with the current item's parent whenever it changes\n * (see constructor), so a group opens on navigation but can still\n * be collapsed by the user. (It used to be OR-ed with `hasActiveChild` at\n * read time, so toggling such a group flipped the set without ever closing\n * it — the set drifted out of sync with what was on screen.)\n */\n readonly expandedItems = signal<Set<string>>(new Set());\n\n /** Ids of the collapsible parents (top-level groups, section sub-groups) that contain the current item. */\n private readonly activeChildParents = computed(() => currentItemParents(this.items(), this.currentItem()));\n\n /**\n * Computed sorted navigation items by displayOrder\n */\n readonly sortedItems = computed(() => sortNavigationItems(this.items()));\n\n /**\n * Every item rendered as a link, in display order (depth first): simple\n * items, the children of a group, the children of a section, and the\n * children of a section's sub-group.\n */\n private readonly linkItems = computed(() => navigationLinks(this.sortedItems()));\n\n /** The router URL's path: primary outlet only, no query, fragment or matrix parameters. */\n private readonly routerPath = computed(() => navigationPath(this.router, this.routerUrl()));\n\n /**\n * The one current link (or none). The single source of both the current\n * look (`lc-sidenav__nav-item--active`) and `aria-current=\"page\"` (AS-16).\n * With `activeRoute` set: the first link whose route equals it. Without:\n * the router's path — the exact match wins, otherwise the longest link\n * route the path continues with a `/` (`/` matches only `/`); ties go to\n * the first link in display order. The rules live in\n * `internal/navigation` since 3.6, shared with `lc-sidenav-placeholder`.\n */\n private readonly currentItem = computed<NavigationItem | null>(() =>\n currentNavigationItem(this.linkItems(), this.activeRoute(), this.activeRoute() === '' ? this.routerPath() : ''),\n );\n\n /**\n * Event emitted when the sidenav should close\n */\n readonly closed = output<void>();\n\n /**\n * Event emitted when a navigation item is clicked\n */\n readonly itemClicked = output<NavigationItem>();\n\n /**\n * Event emitted when an item's action button is clicked\n */\n readonly itemAction = output<NavigationItem>();\n\n constructor() {\n this.router.events\n .pipe(\n filter((event): event is NavigationEnd => event instanceof NavigationEnd),\n takeUntilDestroyed(),\n )\n .subscribe(() => this.routerUrl.set(this.router.url));\n\n // React to mobileBreakpoint changes\n effect(() => {\n this.mobileBreakpoint(); // track dependency\n this.setupMediaQuery();\n });\n\n // Navigating into a group opens it: add the active child's parent(s) to\n // the expanded set. Only additive — the user's own collapses/expands of\n // other groups survive a route change.\n effect(() => {\n const parents = this.activeChildParents();\n if (parents.length === 0) return;\n const expanded = untracked(this.expandedItems);\n if (parents.every((id) => expanded.has(id))) return;\n this.expandedItems.set(new Set([...expanded, ...parents]));\n });\n }\n\n ngOnDestroy(): void {\n this.teardownMediaQuery();\n }\n\n private setupMediaQuery(): void {\n if (typeof window === 'undefined') return;\n this.teardownMediaQuery();\n this.mediaQuery = window.matchMedia(`(max-width: ${this.mobileBreakpoint()}px)`);\n this.isMobile.set(this.mediaQuery.matches);\n this.mediaQuery.addEventListener('change', this.mediaHandler);\n }\n\n private teardownMediaQuery(): void {\n this.mediaQuery?.removeEventListener('change', this.mediaHandler);\n this.mediaQuery = null;\n }\n\n /**\n * Computed CSS classes for the sidenav\n */\n sidenavClasses = computed(() => {\n const classes = ['lc-sidenav'];\n classes.push(`lc-sidenav--${this.position()}`);\n classes.push(`lc-sidenav--${this.effectiveMode()}`);\n if (this.isOpen()) {\n classes.push('lc-sidenav--open');\n }\n if (this.collapsed() && !this.isMobile()) {\n classes.push('lc-sidenav--collapsed');\n }\n if (this.theme() !== 'auto') {\n classes.push(`lc-sidenav--${this.theme()}`);\n }\n if (this.variant() === 'transparent') {\n classes.push('lc-sidenav--transparent');\n }\n return classes.join(' ');\n });\n\n /**\n * Computed inline styles for the sidenav\n */\n sidenavStyles = computed(() => ({\n width: this.isMobile() ? this.width() : (this.collapsed() ? '56px' : this.width()),\n }));\n\n /**\n * Toggle collapsed state\n */\n toggleCollapsed(): void {\n this.collapsed.set(!this.collapsed());\n }\n\n /**\n * Handle close action\n */\n handleClose(): void {\n this.closed.emit();\n }\n\n /**\n * Handle navigation item click\n */\n handleItemClick(item: NavigationItem): void {\n this.itemClicked.emit(item);\n // Auto-close drawer on mobile after navigation\n if (this.isMobile()) {\n this.handleClose();\n }\n }\n\n /**\n * Handle action button click on a navigation item\n */\n handleItemAction(event: Event, item: NavigationItem): void {\n event.stopPropagation();\n this.itemAction.emit(item);\n }\n\n /**\n * Whether the item is the current link (see `currentItem`): it alone is\n * painted current and carries `aria-current=\"page\"`.\n */\n isItemActive(item: NavigationItem): boolean {\n return this.currentItem() === item;\n }\n\n /**\n * Check if a parent item contains the current link\n */\n hasActiveChild(item: NavigationItem): boolean {\n const current = this.currentItem();\n return !!current && !!item.children?.includes(current);\n }\n\n /**\n * Toggle expansion of a parent item.\n * If the sidenav is collapsed, expand it first.\n */\n toggleExpanded(item: NavigationItem): void {\n if (this.collapsed()) {\n this.collapsed.set(false);\n // Expand the clicked item after uncollapsing\n const expanded = new Set(this.expandedItems());\n expanded.add(item.id);\n this.expandedItems.set(expanded);\n return;\n }\n const expanded = new Set(this.expandedItems());\n if (expanded.has(item.id)) {\n expanded.delete(item.id);\n } else {\n expanded.add(item.id);\n }\n this.expandedItems.set(expanded);\n }\n\n /**\n * Check if an item is expanded\n */\n isExpanded(item: NavigationItem): boolean {\n return this.expandedItems().has(item.id);\n }\n\n /**\n * Handle keyboard navigation. Keyed on the EFFECTIVE mode: a docked sidenav\n * that has become a drawer below the mobile breakpoint must close on Escape\n * like any drawer.\n */\n @HostListener('document:keydown', ['$event'])\n handleKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape' && this.isOpen() && this.effectiveMode() === 'drawer') {\n this.handleClose();\n }\n }\n}\n","<!-- Drawer mode: render with overlay and conditional visibility -->\n@if (effectiveMode() === 'drawer') {\n @if (isOpen()) {\n <!-- Overlay backdrop -->\n @if (hasOverlay()) {\n <div\n class=\"lc-sidenav__overlay\"\n (click)=\"handleClose()\"\n aria-hidden=\"true\">\n </div>\n }\n\n <ng-container *ngTemplateOutlet=\"sidenavPanel\" />\n }\n}\n\n<!-- Docked mode: always render, visibility controlled by CSS -->\n@if (effectiveMode() === 'docked') {\n <ng-container *ngTemplateOutlet=\"sidenavPanel\" />\n}\n\n<!-- Shared sidenav panel template.\n The <aside> is a plain complementary region; the navigation landmark is\n the inner <nav> (nesting a role=\"navigation\" wrapper around a <nav> gave\n two navigation landmarks). In drawer mode the panel is a modal dialog:\n focus is captured (close button first, see cdkFocusInitial), trapped\n while open and restored to the opener when the panel is destroyed. -->\n<ng-template #sidenavPanel>\n <aside\n [class]=\"sidenavClasses()\"\n [ngStyle]=\"sidenavStyles()\"\n [attr.role]=\"effectiveMode() === 'drawer' ? 'dialog' : null\"\n [attr.aria-modal]=\"effectiveMode() === 'drawer' ? 'true' : null\"\n [attr.aria-label]=\"effectiveMode() === 'drawer' ? ariaLabel() : null\"\n [cdkTrapFocus]=\"effectiveMode() === 'drawer'\"\n [cdkTrapFocusAutoCapture]=\"effectiveMode() === 'drawer'\">\n\n <!-- Logo area (sidebar-first layout) -->\n @if (showLogo()) {\n <div\n class=\"lc-sidenav__logo\"\n [class.lc-sidenav__logo--size-xs]=\"logoSize() === 'xs'\"\n [class.lc-sidenav__logo--size-sm]=\"logoSize() === 'sm'\"\n [class.lc-sidenav__logo--size-md]=\"logoSize() === 'md'\"\n [class.lc-sidenav__logo--size-lg]=\"logoSize() === 'lg'\"\n [class.lc-sidenav__logo--size-xl]=\"logoSize() === 'xl'\"\n >\n <button type=\"button\" class=\"lc-sidenav__logo-link\" [attr.aria-label]=\"toggleAriaLabel()\" (click)=\"toggleCollapsed()\">\n <lc-logo\n [variant]=\"collapsed() ? 'emblem' : 'full'\"\n [size]=\"collapsed() ? 'sm' : 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() || 'Logo'\"\n />\n </button>\n @if (!collapsed() && effectiveMode() === 'docked') {\n <button\n type=\"button\"\n class=\"lc-sidenav__logo-toggle\"\n (click)=\"toggleCollapsed()\"\n [attr.aria-label]=\"collapseAriaLabel() || (position() === 'right' ? 'Collapse navigation to the right' : 'Collapse navigation to the left')\"\n [attr.title]=\"collapseTitle()\">\n <lc-icon\n [name]=\"position() === 'right' ? 'chevron-right' : 'chevron-left'\"\n size=\"sm\"\n [decorative]=\"true\" />\n </button>\n }\n </div>\n }\n\n <!-- Close button (drawer mode only) -->\n @if (effectiveMode() === 'drawer') {\n <button\n type=\"button\"\n class=\"lc-sidenav__close\"\n cdkFocusInitial\n (click)=\"handleClose()\"\n [attr.aria-label]=\"closeAriaLabel()\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n\n <!-- Navigation items (if provided) -->\n @if (items().length > 0) {\n <nav\n class=\"lc-sidenav__nav\"\n [class.lc-sidenav__nav--docked]=\"effectiveMode() === 'docked'\"\n [attr.aria-label]=\"ariaLabel()\">\n @for (item of sortedItems(); track item.id) {\n <!-- Section headline -->\n @if (item.isSection) {\n <div class=\"lc-sidenav__section\">\n <div class=\"lc-sidenav__section-header\">\n <h2 class=\"lc-sidenav__section-title\">{{ item.label }}</h2>\n @if (item.action) {\n <button\n type=\"button\"\n class=\"lc-sidenav__action-btn\"\n [attr.aria-label]=\"item.action.ariaLabel || item.label + ' action'\"\n (click)=\"handleItemAction($event, item)\">\n <lc-icon [name]=\"item.action.icon\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n @if (item.children?.length) {\n <ul class=\"lc-sidenav__section-items\">\n @for (child of item.children; track child.id) {\n <li>\n @if (child.children?.length) {\n <!-- Section child with nested children (collapsible) -->\n <div class=\"lc-sidenav__nav-item-row\">\n <button\n type=\"button\"\n class=\"lc-sidenav__nav-item lc-sidenav__nav-item--parent\"\n [class.lc-sidenav__nav-item--expanded]=\"isExpanded(child)\"\n [class.lc-sidenav__nav-item--has-active-child]=\"hasActiveChild(child)\"\n (click)=\"toggleExpanded(child)\"\n [attr.aria-expanded]=\"isExpanded(child)\"\n [title]=\"collapsed() ? child.label : ''\">\n @if (child.icon) {\n <lc-icon [name]=\"child.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n }\n <span class=\"lc-sidenav__nav-label\">{{ child.label }}</span>\n @if (child.badge) {\n <lc-badge [variant]=\"child.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ child.badge.value }}</lc-badge>\n }\n <lc-icon name=\"chevron-down\" size=\"xs\" [decorative]=\"true\" class=\"lc-sidenav__nav-chevron\" />\n </button>\n @if (child.action) {\n <button\n type=\"button\"\n class=\"lc-sidenav__action-btn\"\n [attr.aria-label]=\"child.action.ariaLabel || child.label + ' action'\"\n (click)=\"handleItemAction($event, child)\">\n <lc-icon [name]=\"child.action.icon\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n @if (isExpanded(child)) {\n <div class=\"lc-sidenav__nav-children\">\n @for (grandchild of child.children; track grandchild.id) {\n <a\n [routerLink]=\"grandchild.route\"\n class=\"lc-sidenav__nav-item lc-sidenav__nav-item--child\"\n (click)=\"handleItemClick(grandchild)\"\n [class.lc-sidenav__nav-item--active]=\"isItemActive(grandchild)\"\n [attr.aria-current]=\"isItemActive(grandchild) ? 'page' : null\">\n @if (grandchild.icon) {\n <lc-icon [name]=\"grandchild.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n }\n <span class=\"lc-sidenav__nav-label\">{{ grandchild.label }}</span>\n @if (grandchild.badge) {\n <lc-badge [variant]=\"grandchild.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ grandchild.badge.value }}</lc-badge>\n }\n </a>\n }\n </div>\n }\n } @else {\n <!-- Section child (simple link) -->\n <div class=\"lc-sidenav__nav-item-row\">\n <a\n [routerLink]=\"child.route\"\n class=\"lc-sidenav__nav-item lc-sidenav__nav-item--child\"\n (click)=\"handleItemClick(child)\"\n [class.lc-sidenav__nav-item--active]=\"isItemActive(child)\"\n [attr.aria-current]=\"isItemActive(child) ? 'page' : null\"\n [title]=\"collapsed() ? child.label : ''\">\n @if (child.icon) {\n <lc-icon [name]=\"child.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n }\n <span class=\"lc-sidenav__nav-label\">{{ child.label }}</span>\n @if (child.badge) {\n <lc-badge [variant]=\"child.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ child.badge.value }}</lc-badge>\n }\n </a>\n @if (child.action) {\n <button\n type=\"button\"\n class=\"lc-sidenav__action-btn\"\n [attr.aria-label]=\"child.action.ariaLabel || child.label + ' action'\"\n (click)=\"handleItemAction($event, child)\">\n <lc-icon [name]=\"child.action.icon\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n }\n </li>\n }\n </ul>\n }\n </div>\n } @else if (item.children?.length) {\n <!-- Parent item with children (collapsible group) -->\n <div class=\"lc-sidenav__nav-item-row\">\n <button\n type=\"button\"\n class=\"lc-sidenav__nav-item lc-sidenav__nav-item--parent\"\n [class.lc-sidenav__nav-item--expanded]=\"isExpanded(item)\"\n [class.lc-sidenav__nav-item--has-active-child]=\"hasActiveChild(item)\"\n (click)=\"toggleExpanded(item)\"\n [attr.aria-expanded]=\"isExpanded(item)\"\n [title]=\"collapsed() ? item.label : ''\">\n <lc-icon [name]=\"item.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n <span class=\"lc-sidenav__nav-label\">{{ item.label }}</span>\n @if (item.badge) {\n <lc-badge [variant]=\"item.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ item.badge.value }}</lc-badge>\n }\n <lc-icon name=\"chevron-down\" size=\"xs\" [decorative]=\"true\" class=\"lc-sidenav__nav-chevron\" />\n </button>\n @if (item.action) {\n <button\n type=\"button\"\n class=\"lc-sidenav__action-btn\"\n [attr.aria-label]=\"item.action.ariaLabel || item.label + ' action'\"\n (click)=\"handleItemAction($event, item)\">\n <lc-icon [name]=\"item.action.icon\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n @if (isExpanded(item)) {\n <div class=\"lc-sidenav__nav-children\">\n @for (child of item.children; track child.id) {\n <a\n [routerLink]=\"child.route\"\n class=\"lc-sidenav__nav-item lc-sidenav__nav-item--child\"\n (click)=\"handleItemClick(child)\"\n [class.lc-sidenav__nav-item--active]=\"isItemActive(child)\"\n [attr.aria-current]=\"isItemActive(child) ? 'page' : null\">\n <lc-icon [name]=\"child.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n <span class=\"lc-sidenav__nav-label\">{{ child.label }}</span>\n @if (child.badge) {\n <lc-badge [variant]=\"child.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ child.badge.value }}</lc-badge>\n }\n </a>\n }\n </div>\n }\n } @else {\n <!-- Simple item without children -->\n <div class=\"lc-sidenav__nav-item-row\">\n <a\n [routerLink]=\"item.route\"\n class=\"lc-sidenav__nav-item\"\n (click)=\"handleItemClick(item)\"\n [class.lc-sidenav__nav-item--active]=\"isItemActive(item)\"\n [attr.aria-current]=\"isItemActive(item) ? 'page' : null\"\n [title]=\"collapsed() ? item.label : ''\">\n <lc-icon [name]=\"item.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n <span class=\"lc-sidenav__nav-label\">{{ item.label }}</span>\n @if (item.badge) {\n <lc-badge [variant]=\"item.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ item.badge.value }}</lc-badge>\n }\n </a>\n @if (item.action) {\n <button\n type=\"button\"\n class=\"lc-sidenav__action-btn\"\n [attr.aria-label]=\"item.action.ariaLabel || item.label + ' action'\"\n (click)=\"handleItemAction($event, item)\">\n <lc-icon [name]=\"item.action.icon\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n }\n }\n </nav>\n }\n\n <!-- Content projection (for custom content) -->\n <div class=\"lc-sidenav__content\" [class.lc-sidenav__content--docked]=\"effectiveMode() === 'docked'\">\n <ng-content></ng-content>\n </div>\n </aside>\n</ng-template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-sidenav.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/sidenav/sidenav.component.ts","../../../../libs/angular-ui-kit/src/lib/sidenav/sidenav.component.html"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n signal,\n computed,\n input,\n output,\n model,\n effect,\n untracked,\n HostListener,\n OnDestroy,\n inject,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { NgTemplateOutlet, NgStyle } from '@angular/common';\nimport { NavigationEnd, Router, RouterLink } from '@angular/router';\nimport { filter } from 'rxjs';\nimport { A11yModule } from '@angular/cdk/a11y';\nimport { NavigationItem } from '@lifecorner/angular-ui-kit/models';\nimport {\n currentItemParents,\n currentNavigationItem,\n navigationLinks,\n navigationPath,\n sortNavigationItems,\n} from '@lifecorner/angular-ui-kit/internal/navigation';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHEVRON_DOWN, ICON_CHEVRON_LEFT, ICON_CHEVRON_RIGHT } from '@lifecorner/angular-ui-kit/icons';\nimport { BadgeComponent } from '@lifecorner/angular-ui-kit/badge';\nimport { LogoComponent } from '@lifecorner/angular-ui-kit/logo';\n\nexport type SidenavPosition = 'left' | 'right';\nexport type SidenavMode = 'drawer' | 'docked';\n\n/**\n * Surface of the docked sidenav: `default` is the rail on `--color-sidebar`\n * with a border; `transparent` has no background and no border and draws the\n * items as 48 px pills (the side navigation on the page, \"Weite\"). A drawer\n * keeps its surface in both.\n */\nexport type SidenavVariant = 'default' | 'transparent';\n\n/**\n * Sidenav component for application navigation sidebar.\n *\n * Features:\n * - Drawer (overlay) and docked (persistent) modes\n * - Responsive mobile mode — docked automatically switches to drawer below a configurable breakpoint\n * - Collapsed icon-rail mode (narrow 56px sidebar with icons only and hover tooltips)\n * - Integrated logo area with collapse-toggle (sidebar-first layouts)\n * - Hierarchical navigation with collapsible groups (up to 3 levels)\n * - Section headlines for item grouping with optional action buttons\n * - Action buttons on any item (hover-reveal)\n * - Badge support on items (count / status indicator)\n * - One current item, announced and painted alike: the link for `activeRoute`\n * (or, without it, the one the router's URL matches) gets\n * `aria-current=\"page\"` and the current look, every other link neither\n * (AS-16). No hover color change on the current item\n * - Keyboard navigation support (Escape closes drawer)\n * - Configurable width and position (left/right)\n * - Optional backdrop overlay\n * - Theme variants: auto, light, dark (with teal accent for dark mode)\n * - `variant=\"transparent\"`: no rail background or border, items as 48 px\n * pills with 16 px labels, the current one on `--color-surface-selected`\n * - Items are at least 44 px high in every density; the current item's ink is\n * `--color-on-surface-selected` (AA on the selected tint)\n * - Accessible: the inner `<nav>` is the navigation landmark; in drawer mode\n * the panel is a modal dialog (`role=\"dialog\"`, focus moved to the close\n * button on open, trapped while open, restored on close)\n *\n * @example\n * ```html\n * <lc-sidenav\n * [isOpen]=\"isOpen\"\n * mode=\"docked\"\n * [(collapsed)]=\"isCollapsed\"\n * [showLogo]=\"true\"\n * logoSize=\"md\"\n * [mobileBreakpoint]=\"768\"\n * [items]=\"navItems\"\n * activeRoute=\"/dashboard\"\n * theme=\"dark\"\n * (closed)=\"isOpen = false\"\n * (itemClicked)=\"navigate($event)\"\n * (itemAction)=\"onAction($event)\" />\n * ```\n */\n@Component({\n selector: 'lc-sidenav',\n standalone: true,\n imports: [NgTemplateOutlet, NgStyle, RouterLink, A11yModule, IconComponent, BadgeComponent, LogoComponent],\n viewProviders: [ɵprovideKitIcons([ICON_CHEVRON_DOWN, ICON_CHEVRON_LEFT, ICON_CHEVRON_RIGHT])],\n templateUrl: './sidenav.component.html',\n styleUrl: './sidenav.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class.lc-sidenav-container]': 'true',\n '[class.lc-sidenav-container--docked]': \"effectiveMode() === 'docked'\",\n '[class.lc-sidenav-container--open]': 'isOpen()',\n },\n})\nexport class SidenavComponent implements OnDestroy {\n private readonly router = inject(Router);\n\n /**\n * The router's URL, updated on every `NavigationEnd`. Before the first\n * navigation it is the router's initial URL (`/`). Read only when\n * `activeRoute` is empty.\n */\n private readonly routerUrl = signal(this.router.url);\n\n /** Whether the sidenav is collapsed to icon-only rail (two-way bindable) */\n readonly collapsed = model(false);\n\n /** Whether to show the logo at the top of the sidenav */\n readonly showLogo = input(false);\n\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. */\n readonly logoAlt = input('');\n\n /** Size of the brand logo (forwarded to inner `<lc-logo>`). Defaults to `md` for a prominent brand block aligned with `<lc-header size=\"md\">` (both 64px). */\n readonly logoSize = input<'xs' | 'sm' | 'md' | 'lg' | 'xl'>('md');\n\n /** Whether the sidenav is open */\n readonly isOpen = input(false);\n\n /** Display mode: 'drawer' (overlay) or 'docked' (persistent sidebar) */\n readonly mode = input<SidenavMode>('drawer');\n\n /** Mobile breakpoint in pixels. Below this width, docked mode switches to drawer. */\n readonly mobileBreakpoint = input(768);\n\n /** Whether the viewport is below the mobile breakpoint */\n readonly isMobile = signal(false);\n\n /** Effective mode: switches docked → drawer on mobile */\n readonly effectiveMode = computed(() => {\n if (this.isMobile() && this.mode() === 'docked') {\n return 'drawer' as SidenavMode;\n }\n return this.mode();\n });\n\n private mediaQuery: MediaQueryList | null = null;\n private mediaHandler = (e: MediaQueryListEvent) => this.isMobile.set(e.matches);\n\n /** Position of the sidenav (left or right) */\n readonly position = input<SidenavPosition>('left');\n\n /** Width of the sidenav drawer */\n readonly width = input('320px');\n\n /**\n * ARIA label of the navigation landmark (the inner `<nav>`) and, in drawer\n * mode, of the dialog panel.\n */\n readonly ariaLabel = input('Side navigation');\n\n /** Whether to show the overlay backdrop */\n readonly hasOverlay = input(true);\n\n /**\n * Navigation items (`NavigationItem[]`): `id`, `icon`, `label`, `route`,\n * `displayOrder` (sort order, 1 = first); optional `children`\n * (`NavigationItem[]`, a collapsible group, up to 3 levels), `isSection`\n * (renders `label` as a section headline over its `children`), `badge`\n * (`{ value: string | number; variant?: 'default' | 'primary' | 'success' |\n * 'warning' | 'error' | 'info' }`), `action` (`{ icon: string; ariaLabel?:\n * string }`, a button that emits `itemAction`), `requiredRole` (for the\n * app's own filtering; not evaluated here). Items link with `routerLink`;\n * exactly one link, the current item (see `activeRoute`), gets\n * `aria-current=\"page\"`.\n * @default []\n */\n readonly items = input<NavigationItem[]>([]);\n\n /**\n * The current route. When set, the first link (in display order) whose\n * `route` equals it is the current item: it alone gets `aria-current=\"page\"`\n * and the current look, whatever the router matches. When empty, the\n * sidenav follows the router: the link whose route equals the URL's path is\n * current, otherwise the one with the longest route the path starts with\n * (`/household` on `/household/members`; `/` only on `/`). Routes are\n * compared as written, so give them as absolute paths (`'/household'`).\n * @default ''\n */\n readonly activeRoute = input('');\n\n /** Theme variant for the sidenav */\n readonly theme = input<'light' | 'dark' | 'auto'>('auto');\n\n /**\n * Surface of the docked sidenav: `default` (the rail with background and\n * border) or `transparent` (no background, no border, items as 48 px pills\n * with radius full and 16 px labels; the current one on\n * `--color-surface-selected`). A drawer keeps its surface.\n */\n readonly variant = input<SidenavVariant>('default');\n\n /** Accessible name of the logo button that collapses/expands the sidebar. */\n readonly toggleAriaLabel = input('Toggle sidebar');\n\n /** Accessible name of the collapse button. Empty: \"Collapse navigation to the left/right\" by `position`. */\n readonly collapseAriaLabel = input('');\n\n /** Tooltip of the collapse button. */\n readonly collapseTitle = input('Collapse sidebar');\n\n /** Accessible name of the close button (drawer mode). */\n readonly closeAriaLabel = input('Close navigation');\n\n /**\n * Ids of the expanded parent items — the single source of truth for\n * `isExpanded`. Seeded with the current item's parent whenever it changes\n * (see constructor), so a group opens on navigation but can still\n * be collapsed by the user. (It used to be OR-ed with `hasActiveChild` at\n * read time, so toggling such a group flipped the set without ever closing\n * it — the set drifted out of sync with what was on screen.)\n */\n readonly expandedItems = signal<Set<string>>(new Set());\n\n /** Ids of the collapsible parents (top-level groups, section sub-groups) that contain the current item. */\n private readonly activeChildParents = computed(() => currentItemParents(this.items(), this.currentItem()));\n\n /**\n * Computed sorted navigation items by displayOrder\n */\n readonly sortedItems = computed(() => sortNavigationItems(this.items()));\n\n /**\n * Every item rendered as a link, in display order (depth first): simple\n * items, the children of a group, the children of a section, and the\n * children of a section's sub-group.\n */\n private readonly linkItems = computed(() => navigationLinks(this.sortedItems()));\n\n /** The router URL's path: primary outlet only, no query, fragment or matrix parameters. */\n private readonly routerPath = computed(() => navigationPath(this.router, this.routerUrl()));\n\n /**\n * The one current link (or none). The single source of both the current\n * look (`lc-sidenav__nav-item--active`) and `aria-current=\"page\"` (AS-16).\n * With `activeRoute` set: the first link whose route equals it. Without:\n * the router's path — the exact match wins, otherwise the longest link\n * route the path continues with a `/` (`/` matches only `/`); ties go to\n * the first link in display order. The rules live in\n * `internal/navigation` since 3.6, shared with `lc-sidenav-placeholder`.\n */\n private readonly currentItem = computed<NavigationItem | null>(() =>\n currentNavigationItem(this.linkItems(), this.activeRoute(), this.activeRoute() === '' ? this.routerPath() : ''),\n );\n\n /**\n * Event emitted when the sidenav should close\n */\n readonly closed = output<void>();\n\n /**\n * Event emitted when a navigation item is clicked\n */\n readonly itemClicked = output<NavigationItem>();\n\n /**\n * Event emitted when an item's action button is clicked\n */\n readonly itemAction = output<NavigationItem>();\n\n constructor() {\n this.router.events\n .pipe(\n filter((event): event is NavigationEnd => event instanceof NavigationEnd),\n takeUntilDestroyed(),\n )\n .subscribe(() => this.routerUrl.set(this.router.url));\n\n // React to mobileBreakpoint changes\n effect(() => {\n this.mobileBreakpoint(); // track dependency\n this.setupMediaQuery();\n });\n\n // Navigating into a group opens it: add the active child's parent(s) to\n // the expanded set. Only additive — the user's own collapses/expands of\n // other groups survive a route change.\n effect(() => {\n const parents = this.activeChildParents();\n if (parents.length === 0) return;\n const expanded = untracked(this.expandedItems);\n if (parents.every((id) => expanded.has(id))) return;\n this.expandedItems.set(new Set([...expanded, ...parents]));\n });\n }\n\n ngOnDestroy(): void {\n this.teardownMediaQuery();\n }\n\n private setupMediaQuery(): void {\n if (typeof window === 'undefined') return;\n this.teardownMediaQuery();\n this.mediaQuery = window.matchMedia(`(max-width: ${this.mobileBreakpoint()}px)`);\n this.isMobile.set(this.mediaQuery.matches);\n this.mediaQuery.addEventListener('change', this.mediaHandler);\n }\n\n private teardownMediaQuery(): void {\n this.mediaQuery?.removeEventListener('change', this.mediaHandler);\n this.mediaQuery = null;\n }\n\n /**\n * Computed CSS classes for the sidenav\n */\n sidenavClasses = computed(() => {\n const classes = ['lc-sidenav'];\n classes.push(`lc-sidenav--${this.position()}`);\n classes.push(`lc-sidenav--${this.effectiveMode()}`);\n if (this.isOpen()) {\n classes.push('lc-sidenav--open');\n }\n if (this.collapsed() && !this.isMobile()) {\n classes.push('lc-sidenav--collapsed');\n }\n if (this.theme() !== 'auto') {\n classes.push(`lc-sidenav--${this.theme()}`);\n }\n if (this.variant() === 'transparent') {\n classes.push('lc-sidenav--transparent');\n }\n return classes.join(' ');\n });\n\n /**\n * Computed inline styles for the sidenav\n */\n sidenavStyles = computed(() => ({\n width: this.isMobile() ? this.width() : (this.collapsed() ? '56px' : this.width()),\n }));\n\n /**\n * Toggle collapsed state\n */\n toggleCollapsed(): void {\n this.collapsed.set(!this.collapsed());\n }\n\n /**\n * Handle close action\n */\n handleClose(): void {\n this.closed.emit();\n }\n\n /**\n * Handle navigation item click\n */\n handleItemClick(item: NavigationItem): void {\n this.itemClicked.emit(item);\n // Auto-close drawer on mobile after navigation\n if (this.isMobile()) {\n this.handleClose();\n }\n }\n\n /**\n * Handle action button click on a navigation item\n */\n handleItemAction(event: Event, item: NavigationItem): void {\n event.stopPropagation();\n this.itemAction.emit(item);\n }\n\n /**\n * Whether the item is the current link (see `currentItem`): it alone is\n * painted current and carries `aria-current=\"page\"`.\n */\n isItemActive(item: NavigationItem): boolean {\n return this.currentItem() === item;\n }\n\n /**\n * Check if a parent item contains the current link\n */\n hasActiveChild(item: NavigationItem): boolean {\n const current = this.currentItem();\n return !!current && !!item.children?.includes(current);\n }\n\n /**\n * Toggle expansion of a parent item.\n * If the sidenav is collapsed, expand it first.\n */\n toggleExpanded(item: NavigationItem): void {\n if (this.collapsed()) {\n this.collapsed.set(false);\n // Expand the clicked item after uncollapsing\n const expanded = new Set(this.expandedItems());\n expanded.add(item.id);\n this.expandedItems.set(expanded);\n return;\n }\n const expanded = new Set(this.expandedItems());\n if (expanded.has(item.id)) {\n expanded.delete(item.id);\n } else {\n expanded.add(item.id);\n }\n this.expandedItems.set(expanded);\n }\n\n /**\n * Check if an item is expanded\n */\n isExpanded(item: NavigationItem): boolean {\n return this.expandedItems().has(item.id);\n }\n\n /**\n * Handle keyboard navigation. Keyed on the EFFECTIVE mode: a docked sidenav\n * that has become a drawer below the mobile breakpoint must close on Escape\n * like any drawer.\n */\n @HostListener('document:keydown', ['$event'])\n handleKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape' && this.isOpen() && this.effectiveMode() === 'drawer') {\n this.handleClose();\n }\n }\n}\n","<!-- Drawer mode: render with overlay and conditional visibility -->\n@if (effectiveMode() === 'drawer') {\n @if (isOpen()) {\n <!-- Overlay backdrop -->\n @if (hasOverlay()) {\n <div\n class=\"lc-sidenav__overlay\"\n (click)=\"handleClose()\"\n aria-hidden=\"true\">\n </div>\n }\n\n <ng-container *ngTemplateOutlet=\"sidenavPanel\" />\n }\n}\n\n<!-- Docked mode: always render, visibility controlled by CSS -->\n@if (effectiveMode() === 'docked') {\n <ng-container *ngTemplateOutlet=\"sidenavPanel\" />\n}\n\n<!-- Shared sidenav panel template.\n The <aside> is a plain complementary region; the navigation landmark is\n the inner <nav> (nesting a role=\"navigation\" wrapper around a <nav> gave\n two navigation landmarks). In drawer mode the panel is a modal dialog:\n focus is captured (close button first, see cdkFocusInitial), trapped\n while open and restored to the opener when the panel is destroyed. -->\n<ng-template #sidenavPanel>\n <aside\n [class]=\"sidenavClasses()\"\n [ngStyle]=\"sidenavStyles()\"\n [attr.role]=\"effectiveMode() === 'drawer' ? 'dialog' : null\"\n [attr.aria-modal]=\"effectiveMode() === 'drawer' ? 'true' : null\"\n [attr.aria-label]=\"effectiveMode() === 'drawer' ? ariaLabel() : null\"\n [cdkTrapFocus]=\"effectiveMode() === 'drawer'\"\n [cdkTrapFocusAutoCapture]=\"effectiveMode() === 'drawer'\">\n\n <!-- Logo area (sidebar-first layout) -->\n @if (showLogo()) {\n <div\n class=\"lc-sidenav__logo\"\n [class.lc-sidenav__logo--size-xs]=\"logoSize() === 'xs'\"\n [class.lc-sidenav__logo--size-sm]=\"logoSize() === 'sm'\"\n [class.lc-sidenav__logo--size-md]=\"logoSize() === 'md'\"\n [class.lc-sidenav__logo--size-lg]=\"logoSize() === 'lg'\"\n [class.lc-sidenav__logo--size-xl]=\"logoSize() === 'xl'\"\n >\n <button type=\"button\" class=\"lc-sidenav__logo-link\" [attr.aria-label]=\"toggleAriaLabel()\" (click)=\"toggleCollapsed()\">\n <lc-logo\n [variant]=\"collapsed() ? 'emblem' : 'full'\"\n [size]=\"collapsed() ? 'sm' : 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() || 'Logo'\"\n />\n </button>\n @if (!collapsed() && effectiveMode() === 'docked') {\n <button\n type=\"button\"\n class=\"lc-sidenav__logo-toggle\"\n (click)=\"toggleCollapsed()\"\n [attr.aria-label]=\"collapseAriaLabel() || (position() === 'right' ? 'Collapse navigation to the right' : 'Collapse navigation to the left')\"\n [attr.title]=\"collapseTitle()\">\n <lc-icon\n [name]=\"position() === 'right' ? 'chevron-right' : 'chevron-left'\"\n size=\"sm\"\n [decorative]=\"true\" />\n </button>\n }\n </div>\n }\n\n <!-- Close button (drawer mode only) -->\n @if (effectiveMode() === 'drawer') {\n <button\n type=\"button\"\n class=\"lc-sidenav__close\"\n cdkFocusInitial\n (click)=\"handleClose()\"\n [attr.aria-label]=\"closeAriaLabel()\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n\n <!-- Navigation items (if provided) -->\n @if (items().length > 0) {\n <nav\n class=\"lc-sidenav__nav\"\n [class.lc-sidenav__nav--docked]=\"effectiveMode() === 'docked'\"\n [attr.aria-label]=\"ariaLabel()\">\n @for (item of sortedItems(); track item.id) {\n <!-- Section headline -->\n @if (item.isSection) {\n <div class=\"lc-sidenav__section\">\n <div class=\"lc-sidenav__section-header\">\n <h2 class=\"lc-sidenav__section-title\">{{ item.label }}</h2>\n @if (item.action) {\n <button\n type=\"button\"\n class=\"lc-sidenav__action-btn\"\n [attr.aria-label]=\"item.action.ariaLabel || item.label + ' action'\"\n (click)=\"handleItemAction($event, item)\">\n <lc-icon [name]=\"item.action.icon\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n @if (item.children?.length) {\n <ul class=\"lc-sidenav__section-items\">\n @for (child of item.children; track child.id) {\n <li>\n @if (child.children?.length) {\n <!-- Section child with nested children (collapsible) -->\n <div class=\"lc-sidenav__nav-item-row\">\n <button\n type=\"button\"\n class=\"lc-sidenav__nav-item lc-sidenav__nav-item--parent\"\n [class.lc-sidenav__nav-item--expanded]=\"isExpanded(child)\"\n [class.lc-sidenav__nav-item--has-active-child]=\"hasActiveChild(child)\"\n (click)=\"toggleExpanded(child)\"\n [attr.aria-expanded]=\"isExpanded(child)\"\n [title]=\"collapsed() ? child.label : ''\">\n @if (child.icon) {\n <lc-icon [name]=\"child.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n }\n <span class=\"lc-sidenav__nav-label\">{{ child.label }}</span>\n @if (child.badge) {\n <lc-badge [variant]=\"child.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ child.badge.value }}</lc-badge>\n }\n <lc-icon name=\"chevron-down\" size=\"xs\" [decorative]=\"true\" class=\"lc-sidenav__nav-chevron\" />\n </button>\n @if (child.action) {\n <button\n type=\"button\"\n class=\"lc-sidenav__action-btn\"\n [attr.aria-label]=\"child.action.ariaLabel || child.label + ' action'\"\n (click)=\"handleItemAction($event, child)\">\n <lc-icon [name]=\"child.action.icon\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n @if (isExpanded(child)) {\n <div class=\"lc-sidenav__nav-children\">\n @for (grandchild of child.children; track grandchild.id) {\n <a\n [routerLink]=\"grandchild.route\"\n class=\"lc-sidenav__nav-item lc-sidenav__nav-item--child\"\n (click)=\"handleItemClick(grandchild)\"\n [class.lc-sidenav__nav-item--active]=\"isItemActive(grandchild)\"\n [attr.aria-current]=\"isItemActive(grandchild) ? 'page' : null\">\n @if (grandchild.icon) {\n <lc-icon [name]=\"grandchild.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n }\n <span class=\"lc-sidenav__nav-label\">{{ grandchild.label }}</span>\n @if (grandchild.badge) {\n <lc-badge [variant]=\"grandchild.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ grandchild.badge.value }}</lc-badge>\n }\n </a>\n }\n </div>\n }\n } @else {\n <!-- Section child (simple link) -->\n <div class=\"lc-sidenav__nav-item-row\">\n <a\n [routerLink]=\"child.route\"\n class=\"lc-sidenav__nav-item lc-sidenav__nav-item--child\"\n (click)=\"handleItemClick(child)\"\n [class.lc-sidenav__nav-item--active]=\"isItemActive(child)\"\n [attr.aria-current]=\"isItemActive(child) ? 'page' : null\"\n [title]=\"collapsed() ? child.label : ''\">\n @if (child.icon) {\n <lc-icon [name]=\"child.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n }\n <span class=\"lc-sidenav__nav-label\">{{ child.label }}</span>\n @if (child.badge) {\n <lc-badge [variant]=\"child.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ child.badge.value }}</lc-badge>\n }\n </a>\n @if (child.action) {\n <button\n type=\"button\"\n class=\"lc-sidenav__action-btn\"\n [attr.aria-label]=\"child.action.ariaLabel || child.label + ' action'\"\n (click)=\"handleItemAction($event, child)\">\n <lc-icon [name]=\"child.action.icon\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n }\n </li>\n }\n </ul>\n }\n </div>\n } @else if (item.children?.length) {\n <!-- Parent item with children (collapsible group) -->\n <div class=\"lc-sidenav__nav-item-row\">\n <button\n type=\"button\"\n class=\"lc-sidenav__nav-item lc-sidenav__nav-item--parent\"\n [class.lc-sidenav__nav-item--expanded]=\"isExpanded(item)\"\n [class.lc-sidenav__nav-item--has-active-child]=\"hasActiveChild(item)\"\n (click)=\"toggleExpanded(item)\"\n [attr.aria-expanded]=\"isExpanded(item)\"\n [title]=\"collapsed() ? item.label : ''\">\n <lc-icon [name]=\"item.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n <span class=\"lc-sidenav__nav-label\">{{ item.label }}</span>\n @if (item.badge) {\n <lc-badge [variant]=\"item.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ item.badge.value }}</lc-badge>\n }\n <lc-icon name=\"chevron-down\" size=\"xs\" [decorative]=\"true\" class=\"lc-sidenav__nav-chevron\" />\n </button>\n @if (item.action) {\n <button\n type=\"button\"\n class=\"lc-sidenav__action-btn\"\n [attr.aria-label]=\"item.action.ariaLabel || item.label + ' action'\"\n (click)=\"handleItemAction($event, item)\">\n <lc-icon [name]=\"item.action.icon\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n @if (isExpanded(item)) {\n <div class=\"lc-sidenav__nav-children\">\n @for (child of item.children; track child.id) {\n <a\n [routerLink]=\"child.route\"\n class=\"lc-sidenav__nav-item lc-sidenav__nav-item--child\"\n (click)=\"handleItemClick(child)\"\n [class.lc-sidenav__nav-item--active]=\"isItemActive(child)\"\n [attr.aria-current]=\"isItemActive(child) ? 'page' : null\">\n <lc-icon [name]=\"child.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n <span class=\"lc-sidenav__nav-label\">{{ child.label }}</span>\n @if (child.badge) {\n <lc-badge [variant]=\"child.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ child.badge.value }}</lc-badge>\n }\n </a>\n }\n </div>\n }\n } @else {\n <!-- Simple item without children -->\n <div class=\"lc-sidenav__nav-item-row\">\n <a\n [routerLink]=\"item.route\"\n class=\"lc-sidenav__nav-item\"\n (click)=\"handleItemClick(item)\"\n [class.lc-sidenav__nav-item--active]=\"isItemActive(item)\"\n [attr.aria-current]=\"isItemActive(item) ? 'page' : null\"\n [title]=\"collapsed() ? item.label : ''\">\n <lc-icon [name]=\"item.icon\" size=\"sm\" [decorative]=\"true\" class=\"lc-sidenav__nav-icon\" />\n <span class=\"lc-sidenav__nav-label\">{{ item.label }}</span>\n @if (item.badge) {\n <lc-badge [variant]=\"item.badge.variant || 'default'\" size=\"xs\" [rounded]=\"true\" class=\"lc-sidenav__nav-badge\">{{ item.badge.value }}</lc-badge>\n }\n </a>\n @if (item.action) {\n <button\n type=\"button\"\n class=\"lc-sidenav__action-btn\"\n [attr.aria-label]=\"item.action.ariaLabel || item.label + ' action'\"\n (click)=\"handleItemAction($event, item)\">\n <lc-icon [name]=\"item.action.icon\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </div>\n }\n }\n </nav>\n }\n\n <!-- Content projection (for custom content) -->\n <div class=\"lc-sidenav__content\" [class.lc-sidenav__content--docked]=\"effectiveMode() === 'docked'\">\n <ng-content></ng-content>\n </div>\n </aside>\n</ng-template>\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
2
|
export type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
3
3
|
export type AvatarStatus = 'online' | 'offline' | 'away' | 'busy';
|
|
4
|
+
/**
|
|
5
|
+
* How the browser loads the image (3.11.2, G-40). The same union as
|
|
6
|
+
* `CharacterLoading`, kept separate because entries don't import each other.
|
|
7
|
+
* - `eager`: no attribute, the browser default.
|
|
8
|
+
* - `lazy`: `loading="lazy"`, for an avatar below the fold.
|
|
9
|
+
*/
|
|
10
|
+
export type AvatarLoading = 'eager' | 'lazy';
|
|
4
11
|
/**
|
|
5
12
|
* Background of the initials. `default` is the neutral kit avatar; `member-1`
|
|
6
13
|
* … `member-6` are the member colours (`--color-member-1` … `-6`: teal, rust,
|
|
@@ -38,8 +45,20 @@ export declare class AvatarComponent {
|
|
|
38
45
|
alt: import("@angular/core").InputSignal<string | undefined>;
|
|
39
46
|
/** Full name for generating initials */
|
|
40
47
|
name: import("@angular/core").InputSignal<string | undefined>;
|
|
41
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* Size of the avatar: xs 24, sm 32, md 40, lg 48, xl 64 px (1.5 … 4 rem).
|
|
50
|
+
* The `<img>` carries the size's px as `width`/`height`; CSS sizes the box,
|
|
51
|
+
* so at 200 % text the box grows and the attributes only give the 1:1 ratio.
|
|
52
|
+
* @default 'md'
|
|
53
|
+
*/
|
|
42
54
|
size: import("@angular/core").InputSignal<AvatarSize>;
|
|
55
|
+
/**
|
|
56
|
+
* How the browser loads the image. `lazy`: for an avatar below the fold;
|
|
57
|
+
* writes `loading="lazy"`. `eager` writes no attribute. The initials still
|
|
58
|
+
* replace an image that fails.
|
|
59
|
+
* @default 'eager'
|
|
60
|
+
*/
|
|
61
|
+
loading: import("@angular/core").InputSignal<AvatarLoading>;
|
|
43
62
|
/** Status indicator */
|
|
44
63
|
status: import("@angular/core").InputSignal<AvatarStatus | undefined>;
|
|
45
64
|
/**
|
|
@@ -72,6 +91,8 @@ export declare class AvatarComponent {
|
|
|
72
91
|
* Get aria-label for accessibility
|
|
73
92
|
*/
|
|
74
93
|
ariaLabel: import("@angular/core").Signal<string>;
|
|
94
|
+
/** The size's px, written as the `<img>` `width` and `height` (G-40). */
|
|
95
|
+
protected readonly imagePx: import("@angular/core").Signal<number>;
|
|
75
96
|
/**
|
|
76
97
|
* Check if image should be displayed
|
|
77
98
|
*/
|
|
@@ -107,6 +128,11 @@ export declare class AvatarComponent {
|
|
|
107
128
|
"required": false;
|
|
108
129
|
"isSignal": true;
|
|
109
130
|
};
|
|
131
|
+
"loading": {
|
|
132
|
+
"alias": "loading";
|
|
133
|
+
"required": false;
|
|
134
|
+
"isSignal": true;
|
|
135
|
+
};
|
|
110
136
|
"status": {
|
|
111
137
|
"alias": "status";
|
|
112
138
|
"required": false;
|
|
@@ -9,6 +9,12 @@ export type CharacterSize = 48 | 64 | 80 | 96 | 128;
|
|
|
9
9
|
* - `dark`: the on-dark drawing in both themes, for a fixed dark surface.
|
|
10
10
|
*/
|
|
11
11
|
export type CharacterColorMode = 'auto' | 'dark';
|
|
12
|
+
/**
|
|
13
|
+
* How the browser loads the drawings (3.11.2, G-39).
|
|
14
|
+
* - `eager`: no attribute, the browser default; keep it above the fold.
|
|
15
|
+
* - `lazy`: `loading="lazy"` on every drawing, for a figure below the fold.
|
|
16
|
+
*/
|
|
17
|
+
export type CharacterLoading = 'eager' | 'lazy';
|
|
12
18
|
/**
|
|
13
19
|
* The URL folder that holds the pose files (`<pose>-light.svg`,
|
|
14
20
|
* `<pose>-dark.svg`, copied from the package's `assets/character/`). Follows
|
|
@@ -73,6 +79,14 @@ export declare class CharacterComponent {
|
|
|
73
79
|
* @default ''
|
|
74
80
|
*/
|
|
75
81
|
readonly ariaLabel: import("@angular/core").InputSignal<string>;
|
|
82
|
+
/**
|
|
83
|
+
* How the browser loads the drawings. `lazy`: for a figure below the fold
|
|
84
|
+
* (such as the horizon); writes `loading="lazy"` on every drawing, and in
|
|
85
|
+
* `auto` only the drawing of the current theme is fetched. `eager` writes no
|
|
86
|
+
* attribute (the browser default). Keep `eager` above the fold.
|
|
87
|
+
* @default 'eager'
|
|
88
|
+
*/
|
|
89
|
+
readonly loading: import("@angular/core").InputSignal<CharacterLoading>;
|
|
76
90
|
private readonly basePath;
|
|
77
91
|
protected readonly lightSrc: import("@angular/core").Signal<string>;
|
|
78
92
|
protected readonly darkSrc: import("@angular/core").Signal<string>;
|
|
@@ -99,6 +113,11 @@ export declare class CharacterComponent {
|
|
|
99
113
|
"required": false;
|
|
100
114
|
"isSignal": true;
|
|
101
115
|
};
|
|
116
|
+
"loading": {
|
|
117
|
+
"alias": "loading";
|
|
118
|
+
"required": false;
|
|
119
|
+
"isSignal": true;
|
|
120
|
+
};
|
|
102
121
|
}, {}, never, never, true, never>;
|
|
103
122
|
}
|
|
104
123
|
export type { CharacterPose };
|
|
@@ -123,15 +123,25 @@ export declare class IconComponent {
|
|
|
123
123
|
* - md: 24px (default)
|
|
124
124
|
* - lg: 32px
|
|
125
125
|
* - xl: 40px
|
|
126
|
+
*
|
|
127
|
+
* Set by the `icon-<size>` class in the component stylesheet; `lc-icon`
|
|
128
|
+
* writes no inline size (3.11.1).
|
|
126
129
|
* @default "md"
|
|
127
130
|
*/
|
|
128
131
|
readonly size: import("@angular/core").InputSignal<IconSize>;
|
|
129
132
|
/**
|
|
130
|
-
* Icon
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
133
|
+
* Icon colour. By default the icon takes the text colour of its parent
|
|
134
|
+
* (`currentColor`, through the stylesheet) and `lc-icon` renders **no
|
|
135
|
+
* `style` attribute**, so it works under a `style-src 'self'` CSP (3.11.1).
|
|
136
|
+
*
|
|
137
|
+
* Any other value, a CSS colour (`#FF5733`, `rgb(…)`) or a variable
|
|
138
|
+
* (`var(--color-primary-500)`), becomes the `<svg>`'s inline `color`, set
|
|
139
|
+
* through CSSOM, which such a CSP allows in the browser. In prerendered HTML
|
|
140
|
+
* it is a `style` attribute, which that CSP blocks until the app hydrates,
|
|
141
|
+
* so the icon shows the parent's colour until then. Under a strict CSP,
|
|
142
|
+
* colour the icon from your stylesheet instead: set `color` on `lc-icon` or
|
|
143
|
+
* on its parent. `currentColor` in any letter case, and an empty string,
|
|
144
|
+
* mean the default.
|
|
135
145
|
* @default "currentColor"
|
|
136
146
|
*/
|
|
137
147
|
readonly color: import("@angular/core").InputSignal<string>;
|
|
@@ -172,7 +182,8 @@ export declare class IconComponent {
|
|
|
172
182
|
*/
|
|
173
183
|
readonly iconPath: import("@angular/core").Signal<string>;
|
|
174
184
|
/**
|
|
175
|
-
* Computed size in pixels
|
|
185
|
+
* Computed size in pixels, for the svg's `width`/`height` attributes; the
|
|
186
|
+
* same values as the `icon-<size>` rules in icon.component.scss
|
|
176
187
|
* @internal
|
|
177
188
|
*/
|
|
178
189
|
readonly sizeInPixels: import("@angular/core").Signal<string>;
|
|
@@ -182,7 +193,8 @@ export declare class IconComponent {
|
|
|
182
193
|
*/
|
|
183
194
|
readonly computedClasses: import("@angular/core").Signal<string>;
|
|
184
195
|
/**
|
|
185
|
-
*
|
|
196
|
+
* The `color` input as handed to the svg: a custom value becomes its inline
|
|
197
|
+
* colour (CSSOM), the default writes nothing (see `decorateSvg`)
|
|
186
198
|
* @internal
|
|
187
199
|
*/
|
|
188
200
|
readonly colorStyle: import("@angular/core").Signal<string>;
|
|
@@ -17,6 +17,11 @@ import { InjectionToken } from "@angular/core";
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
export declare const LC_LOGO_BASE_PATH: InjectionToken<string>;
|
|
20
|
+
/** The `width`/`height` pair written on one `<img>`; `null` writes no size attributes. */
|
|
21
|
+
type IntrinsicSize = {
|
|
22
|
+
readonly width: number;
|
|
23
|
+
readonly height: number;
|
|
24
|
+
} | null;
|
|
20
25
|
/**
|
|
21
26
|
* Logo component for displaying a brand identity.
|
|
22
27
|
*
|
|
@@ -37,6 +42,10 @@ export declare const LC_LOGO_BASE_PATH: InjectionToken<string>;
|
|
|
37
42
|
* - The built-in logo ships its own dark drawings; nothing is inverted or
|
|
38
43
|
* recoloured by CSS. A custom logo without a dark partner stays as it is.
|
|
39
44
|
* - The logo is flat and fixed: never animated, posed or distorted.
|
|
45
|
+
* - Every built-in `<img>` carries its file's intrinsic `width`/`height`
|
|
46
|
+
* (3.11.2, G-38), so the browser reserves the box before the file loads;
|
|
47
|
+
* for your own files set `srcWidth`/`srcHeight` and
|
|
48
|
+
* `emblemSrcWidth`/`emblemSrcHeight`.
|
|
40
49
|
*
|
|
41
50
|
* @example Default LifeCorner logo
|
|
42
51
|
* ```html
|
|
@@ -67,6 +76,11 @@ export declare class LogoComponent {
|
|
|
67
76
|
* - 'md': 48px height (default)
|
|
68
77
|
* - 'lg': 64px height
|
|
69
78
|
* - 'xl': 96px height
|
|
79
|
+
*
|
|
80
|
+
* With the built-in files the `<img>` carries the file's intrinsic size as
|
|
81
|
+
* `width`/`height`: the lockup 485 × 100 at every size, the emblem the
|
|
82
|
+
* size's px squared (24 … 96). CSS still sets the rendered height.
|
|
83
|
+
* @default 'md'
|
|
70
84
|
*/
|
|
71
85
|
readonly size: import("@angular/core").InputSignal<"xs" | "sm" | "md" | "lg" | "xl">;
|
|
72
86
|
/**
|
|
@@ -106,6 +120,31 @@ export declare class LogoComponent {
|
|
|
106
120
|
* Optional dark-theme URL for the emblem-only logo.
|
|
107
121
|
*/
|
|
108
122
|
readonly darkEmblemSrc: import("@angular/core").InputSignal<string>;
|
|
123
|
+
/**
|
|
124
|
+
* Intrinsic width in px of your `src` file (and `darkSrc`), written as the
|
|
125
|
+
* `<img>` `width`. Set it together with `srcHeight` so the browser reserves
|
|
126
|
+
* the logo's box before the file loads; `size` still sets the rendered
|
|
127
|
+
* height. Without both, no size attributes are written.
|
|
128
|
+
* @default undefined
|
|
129
|
+
*/
|
|
130
|
+
readonly srcWidth: import("@angular/core").InputSignalWithTransform<number | undefined, string | number | null | undefined>;
|
|
131
|
+
/**
|
|
132
|
+
* Intrinsic height in px of your `src` file (and `darkSrc`). See `srcWidth`.
|
|
133
|
+
* @default undefined
|
|
134
|
+
*/
|
|
135
|
+
readonly srcHeight: import("@angular/core").InputSignalWithTransform<number | undefined, string | number | null | undefined>;
|
|
136
|
+
/**
|
|
137
|
+
* Intrinsic width in px of your `emblemSrc` file (and `darkEmblemSrc`),
|
|
138
|
+
* written as the `<img>` `width`; set it together with `emblemSrcHeight`.
|
|
139
|
+
* @default undefined
|
|
140
|
+
*/
|
|
141
|
+
readonly emblemSrcWidth: import("@angular/core").InputSignalWithTransform<number | undefined, string | number | null | undefined>;
|
|
142
|
+
/**
|
|
143
|
+
* Intrinsic height in px of your `emblemSrc` file (and `darkEmblemSrc`).
|
|
144
|
+
* See `emblemSrcWidth`.
|
|
145
|
+
* @default undefined
|
|
146
|
+
*/
|
|
147
|
+
readonly emblemSrcHeight: import("@angular/core").InputSignalWithTransform<number | undefined, string | number | null | undefined>;
|
|
109
148
|
/** Whether the consumer supplied at least one custom source. */
|
|
110
149
|
readonly hasCustomSrc: import("@angular/core").Signal<boolean>;
|
|
111
150
|
private readonly basePath;
|
|
@@ -130,6 +169,14 @@ export declare class LogoComponent {
|
|
|
130
169
|
*/
|
|
131
170
|
readonly showLightSrc: import("@angular/core").Signal<boolean>;
|
|
132
171
|
readonly showDarkSrc: import("@angular/core").Signal<boolean>;
|
|
172
|
+
/** The built-in file's own size: the lockup 485 × 100, the emblem the size's px squared. */
|
|
173
|
+
private readonly builtInSize;
|
|
174
|
+
/** The consumer's pair for the current variant (a dark file shares its light partner's pair). */
|
|
175
|
+
private readonly customSize;
|
|
176
|
+
/** `width`/`height` of the light `<img>`: follows the file it shows (G-38). */
|
|
177
|
+
protected readonly lightSize: import("@angular/core").Signal<IntrinsicSize>;
|
|
178
|
+
/** `width`/`height` of the dark `<img>`: follows the file it shows (G-38). */
|
|
179
|
+
protected readonly darkSize: import("@angular/core").Signal<IntrinsicSize>;
|
|
133
180
|
readonly logoClasses: import("@angular/core").Signal<string>;
|
|
134
181
|
static ɵfac: i0.ɵɵFactoryDeclaration<LogoComponent, never>;
|
|
135
182
|
static ɵcmp: i0.ɵɵComponentDeclaration<LogoComponent, "lc-logo", never, {
|
|
@@ -178,5 +225,26 @@ export declare class LogoComponent {
|
|
|
178
225
|
"required": false;
|
|
179
226
|
"isSignal": true;
|
|
180
227
|
};
|
|
228
|
+
"srcWidth": {
|
|
229
|
+
"alias": "srcWidth";
|
|
230
|
+
"required": false;
|
|
231
|
+
"isSignal": true;
|
|
232
|
+
};
|
|
233
|
+
"srcHeight": {
|
|
234
|
+
"alias": "srcHeight";
|
|
235
|
+
"required": false;
|
|
236
|
+
"isSignal": true;
|
|
237
|
+
};
|
|
238
|
+
"emblemSrcWidth": {
|
|
239
|
+
"alias": "emblemSrcWidth";
|
|
240
|
+
"required": false;
|
|
241
|
+
"isSignal": true;
|
|
242
|
+
};
|
|
243
|
+
"emblemSrcHeight": {
|
|
244
|
+
"alias": "emblemSrcHeight";
|
|
245
|
+
"required": false;
|
|
246
|
+
"isSignal": true;
|
|
247
|
+
};
|
|
181
248
|
}, {}, never, never, true, never>;
|
|
182
|
-
}
|
|
249
|
+
}
|
|
250
|
+
export {};
|