@lifecorner/angular-ui-kit 3.14.0 → 3.16.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/README.md +2 -1
- package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs +36 -2
- package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs +2 -1
- package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs +23 -5
- package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs +39 -6
- package/fesm2022/lifecorner-angular-ui-kit-button.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-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-empty-state.mjs +42 -5
- package/fesm2022/lifecorner-angular-ui-kit-empty-state.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs +21 -3
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-icon.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-icon.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-icons.mjs +26 -2
- package/fesm2022/lifecorner-angular-ui-kit-icons.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-internal-icon-set.mjs +10 -1
- package/fesm2022/lifecorner-angular-ui-kit-internal-icon-set.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs +30 -6
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-money.mjs +250 -0
- package/fesm2022/lifecorner-angular-ui-kit-money.mjs.map +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +22 -2
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs +20 -3
- package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-sidenav-placeholder.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-sidenav-placeholder.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-switch.mjs +21 -4
- package/fesm2022/lifecorner-angular-ui-kit-switch.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs +72 -7
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit.mjs +1 -0
- package/package.json +5 -1
- package/src/styles/theme-contrast.spec.ts +74 -0
- package/types/lifecorner-angular-ui-kit-app-shell.d.ts +56 -0
- package/types/lifecorner-angular-ui-kit-avatar.d.ts +24 -0
- package/types/lifecorner-angular-ui-kit-button.d.ts +31 -0
- package/types/lifecorner-angular-ui-kit-empty-state.d.ts +38 -0
- package/types/lifecorner-angular-ui-kit-header.d.ts +15 -2
- package/types/lifecorner-angular-ui-kit-icon.d.ts +2 -1
- package/types/lifecorner-angular-ui-kit-icons.d.ts +5 -1
- package/types/lifecorner-angular-ui-kit-list.d.ts +38 -0
- package/types/lifecorner-angular-ui-kit-money.d.ts +150 -0
- package/types/lifecorner-angular-ui-kit-next-step-card.d.ts +26 -0
- package/types/lifecorner-angular-ui-kit-page-header.d.ts +20 -0
- package/types/lifecorner-angular-ui-kit-sidenav-placeholder.d.ts +4 -2
- package/types/lifecorner-angular-ui-kit-sidenav.d.ts +5 -2
- package/types/lifecorner-angular-ui-kit-switch.d.ts +19 -0
- package/types/lifecorner-angular-ui-kit-table.d.ts +42 -1
- package/types/lifecorner-angular-ui-kit.d.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-list.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/list/list-item-template.directive.ts","../../../../libs/angular-ui-kit/src/lib/list/list.component.ts","../../../../libs/angular-ui-kit/src/lib/list/list.component.html"],"sourcesContent":["import { Directive, TemplateRef, inject } from '@angular/core';\nimport { ListItem } from './list.component';\n\n/**\n * Directive for providing a custom template to render each list item.\n *\n * @example\n * ```html\n * <lc-list [items]=\"runs()\" (itemClick)=\"onRunClick($event)\">\n * <ng-template lcListItem let-item>\n * <lc-badge [variant]=\"getStatusVariant(item.status)\">{{ item.status }}</lc-badge>\n * <span>{{ item.symbol }}</span>\n * <span class=\"text-sm text-neutral-500\">{{ item.date }}</span>\n * </ng-template>\n * </lc-list>\n * ```\n */\n@Directive({\n selector: '[lcListItem]',\n standalone: true,\n})\nexport class ListItemTemplateDirective {\n public readonly template = inject(TemplateRef<{ $implicit: ListItem }>);\n}\n","import {\n Component,\n ChangeDetectionStrategy,\n input,\n computed,\n contentChild,\n output,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { IconComponent } from '@lifecorner/angular-ui-kit/icon';\nimport { ButtonComponent, ButtonSize, ButtonVariant } from '@lifecorner/angular-ui-kit/button';\nimport { ListItemTemplateDirective } from './list-item-template.directive';\nimport type { AvatarColor } from '@lifecorner/angular-ui-kit/avatar';\n\n/**\n * List orientation type\n */\nexport type ListOrientation = 'vertical' | 'horizontal';\n\n/**\n * List visual variant\n * - default: flat rows (original)\n * - card: each item rendered as a mini-card with border, radius and shadow on hover\n */\nexport type ListVariant = 'default' | 'card';\n\n/**\n * List item interface\n */\nexport interface ListItem {\n /** Item label text (primary line) */\n label: string;\n /** Secondary text shown below the label */\n subtitle?: string;\n /** Description text shown below subtitle (third line) */\n description?: string;\n /** Optional icon identifier */\n icon?: string;\n /** Avatar URL or initials (renders a circular avatar instead of icon) */\n avatar?: string;\n /**\n * Background of avatar initials: `default` or a member colour `member-1` …\n * `member-6` with white initials (as `lc-avatar`'s `color`).\n */\n avatarColor?: AvatarColor;\n /** Badge text (e.g. count, status label) shown on the trailing side */\n badge?: string;\n /** Badge color variant */\n badgeVariant?: 'default' | 'primary' | 'success' | 'warning' | 'error';\n /** Metadata text shown on the trailing side (e.g. date, size) */\n metadata?: string;\n /** Optional action label */\n action?: string;\n /**\n * Accessible name of this row's action when the visible label repeats on\n * every row (e.g. „Entfernen“ → „iPhone · Safari entfernen“). The visible\n * label must be part of it (WCAG 2.5.3).\n */\n actionAriaLabel?: string;\n /** Item identifier */\n id?: string;\n /** Whether the item is disabled */\n disabled?: boolean;\n /** Whether the item is selected / highlighted */\n selected?: boolean;\n /** Any additional data */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\n/**\n * List item size\n */\nexport type ListSize = 'sm' | 'md' | 'lg';\n\n/**\n * List component for displaying structured item collections.\n *\n * Features:\n * - Vertical and horizontal layout orientations\n * - Variant styles (default, bordered, card)\n * - Optional dividers between items\n * - Icon and avatar support per item\n * - Action buttons with click events\n * - Accessible with ARIA list role; `clickable` rows are keyboard-operable\n *\n * @example\n * ```html\n * <lc-list\n * [items]=\"listItems\"\n * orientation=\"vertical\"\n * [showDividers]=\"true\"\n * (itemClick)=\"handleItemClick($event)\"\n * />\n * ```\n */\n@Component({\n selector: 'lc-list',\n standalone: true,\n imports: [NgTemplateOutlet, IconComponent, ButtonComponent],\n templateUrl: './list.component.html',\n styleUrl: './list.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ListComponent {\n /** Custom item template provided via lcListItem directive */\n readonly itemTemplate = contentChild(ListItemTemplateDirective);\n\n /** Array of list items to display */\n items = input<ListItem[]>([]);\n\n /** Orientation of the list */\n orientation = input<ListOrientation>('vertical');\n\n /** Visual variant */\n variant = input<ListVariant>('default');\n\n /** Size of list items */\n size = input<ListSize>('md');\n\n /** Whether to show dividers between items */\n showDividers = input<boolean>(false);\n\n /**\n * Whether rows are interactive. When set, each row is rendered as a\n * focusable button (Enter / Space emit `itemClick`) so `itemClick` is\n * reachable from the keyboard. Set this whenever you handle `itemClick`.\n */\n clickable = input<boolean>(false);\n\n /**\n * Clamp each item's `description` to two lines (3.2). Set `false` for\n * reading text that must show in full (3.3, G-11).\n * @default true\n */\n clampDescription = input<boolean>(true);\n\n /**\n * Variant of the built-in row action (`ListItem.action`).\n * @default 'ghost'\n */\n actionVariant = input<ButtonVariant>('ghost');\n\n /**\n * Size of the built-in row action: `xs` (3.2, about 25 px) … `lg` (48.5 px,\n * the 44 px touch target).\n * @default 'xs'\n */\n actionSize = input<ButtonSize>('xs');\n\n /** Event emitted when an item is clicked */\n readonly itemClick = output<ListItem>();\n\n /** Event emitted when an action button is clicked */\n readonly actionClick = output<ListItem>();\n\n /**\n * Computed CSS classes for the list\n */\n listClasses = computed(() => {\n const classes = ['lc-list'];\n\n classes.push(`lc-list--${this.orientation()}`);\n classes.push(`lc-list--${this.variant()}`);\n classes.push(`lc-list--${this.size()}`);\n\n if (this.showDividers()) {\n classes.push('lc-list--with-dividers');\n }\n\n if (this.clickable()) {\n classes.push('lc-list--clickable');\n }\n\n if (!this.clampDescription()) {\n classes.push('lc-list--no-clamp');\n }\n\n return classes.join(' ');\n });\n\n /**\n * Get CSS classes for a list item\n */\n getItemClasses(item: ListItem): string {\n const classes = ['lc-list__item'];\n\n if (item.disabled) {\n classes.push('lc-list__item--disabled');\n }\n\n if (item.selected) {\n classes.push('lc-list__item--selected');\n }\n\n return classes.join(' ');\n }\n\n /** CSS classes of an item's avatar (member colour, LK-7). */\n protected avatarClasses(item: ListItem): string {\n const color = item.avatarColor;\n return color && color !== 'default'\n ? `lc-list__avatar lc-list__avatar--member lc-list__avatar--${color}`\n : 'lc-list__avatar';\n }\n\n /**\n * Handle item click\n */\n onItemClick(item: ListItem): void {\n if (!item.disabled) {\n this.itemClick.emit(item);\n }\n }\n\n /**\n * Keyboard activation of a clickable row. Only reacts to keys on the row\n * itself: a nested control (e.g. the action button) handles its own Enter.\n */\n onItemKeydown(event: KeyboardEvent, item: ListItem): void {\n if (event.target !== event.currentTarget) return;\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.onItemClick(item);\n }\n }\n\n /**\n * Handle action button click\n */\n onActionClick(item: ListItem): void {\n this.actionClick.emit(item);\n }\n}\n","<!--\n Row content is shared between the plain (legacy) row and the keyboard-\n operable row rendered when `clickable` is set.\n-->\n<ng-template #rowContent let-item>\n @if (itemTemplate(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl.template; context: { $implicit: item }\"></ng-container>\n } @else {\n <!-- Leading: Avatar or Icon -->\n @if (item.avatar) {\n <div [class]=\"avatarClasses(item)\">\n @if (item.avatar.startsWith('http') || item.avatar.startsWith('/') || item.avatar.startsWith('data:')) {\n <img [src]=\"item.avatar\" [alt]=\"item.label\" class=\"lc-list__avatar-img\" />\n } @else {\n <span class=\"lc-list__avatar-initials\">{{ item.avatar }}</span>\n }\n </div>\n } @else if (item.icon) {\n <lc-icon [name]=\"item.icon\" class=\"lc-list__icon\" size=\"sm\" [decorative]=\"true\" />\n }\n\n <!-- Content: Label, Subtitle, Description -->\n <div class=\"lc-list__content\">\n <span class=\"lc-list__label\">{{ item.label }}</span>\n @if (item.subtitle) {\n <span class=\"lc-list__subtitle\">{{ item.subtitle }}</span>\n }\n @if (item.description) {\n <span class=\"lc-list__description\">{{ item.description }}</span>\n }\n </div>\n\n <!-- Trailing: Badge, Metadata, Action -->\n <div class=\"lc-list__trailing\">\n @if (item.badge) {\n <span class=\"lc-list__badge lc-list__badge--{{ item.badgeVariant || 'default' }}\">{{ item.badge }}</span>\n }\n @if (item.metadata) {\n <span class=\"lc-list__metadata\">{{ item.metadata }}</span>\n }\n @if (item.action) {\n <!-- The action is its own control: its click must not also activate the row. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- only stops the action click from also activating the row; the action is a real button -->\n <span class=\"lc-list__action-area\" (click)=\"$event.stopPropagation()\">\n <lc-button\n [variant]=\"actionVariant()\"\n [size]=\"actionSize()\"\n [ariaLabel]=\"item.actionAriaLabel ?? ''\"\n class=\"lc-list__action\"\n (clicked)=\"onActionClick(item)\"\n >\n {{ item.action }}\n </lc-button>\n </span>\n }\n </div>\n }\n</ng-template>\n\n<div [class]=\"listClasses()\" role=\"list\">\n @for (item of items(); track item.id || $index) {\n @if (clickable()) {\n <div class=\"lc-list__item-wrapper\" role=\"listitem\">\n <div\n [class]=\"getItemClasses(item)\"\n role=\"button\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n (click)=\"onItemClick(item)\"\n (keydown)=\"onItemKeydown($event, item)\"\n >\n <ng-container *ngTemplateOutlet=\"rowContent; context: { $implicit: item }\"></ng-container>\n </div>\n </div>\n } @else {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -- non-clickable lists keep reporting mouse clicks (backward compatible); use clickable for keyboard rows -->\n <div\n [class]=\"getItemClasses(item)\"\n role=\"listitem\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n (click)=\"onItemClick(item)\"\n >\n <ng-container *ngTemplateOutlet=\"rowContent; context: { $implicit: item }\"></ng-container>\n </div>\n }\n }\n</div>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-list.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/list/list-item-template.directive.ts","../../../../libs/angular-ui-kit/src/lib/list/list.component.ts","../../../../libs/angular-ui-kit/src/lib/list/list.component.html"],"sourcesContent":["import { Directive, TemplateRef, inject } from '@angular/core';\nimport { ListItem } from './list.component';\n\n/**\n * Directive for providing a custom template to render each list item.\n *\n * @example\n * ```html\n * <lc-list [items]=\"runs()\" (itemClick)=\"onRunClick($event)\">\n * <ng-template lcListItem let-item>\n * <lc-badge [variant]=\"getStatusVariant(item.status)\">{{ item.status }}</lc-badge>\n * <span>{{ item.symbol }}</span>\n * <span class=\"text-sm text-neutral-500\">{{ item.date }}</span>\n * </ng-template>\n * </lc-list>\n * ```\n */\n@Directive({\n selector: '[lcListItem]',\n standalone: true,\n})\nexport class ListItemTemplateDirective {\n public readonly template = inject(TemplateRef<{ $implicit: ListItem }>);\n}\n","import {\n Component,\n ChangeDetectionStrategy,\n input,\n computed,\n contentChild,\n effect,\n isDevMode,\n output,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { IconComponent } from '@lifecorner/angular-ui-kit/icon';\nimport { ButtonComponent, ButtonSize, ButtonVariant } from '@lifecorner/angular-ui-kit/button';\nimport { ListItemTemplateDirective } from './list-item-template.directive';\nimport type { AvatarColor } from '@lifecorner/angular-ui-kit/avatar';\n\n/**\n * List orientation type\n */\nexport type ListOrientation = 'vertical' | 'horizontal';\n\n/**\n * List visual variant\n * - default: flat rows (original)\n * - card: each item rendered as a mini-card with border, radius and shadow on hover\n */\nexport type ListVariant = 'default' | 'card';\n\n/**\n * List item interface\n */\nexport interface ListItem {\n /** Item label text (primary line) */\n label: string;\n /** Secondary text shown below the label */\n subtitle?: string;\n /** Description text shown below subtitle (third line) */\n description?: string;\n /** Optional icon identifier */\n icon?: string;\n /** Avatar URL or initials (renders a circular avatar instead of icon) */\n avatar?: string;\n /**\n * Background of avatar initials: `default` or a member colour `member-1` …\n * `member-6` with white initials (as `lc-avatar`'s `color`).\n */\n avatarColor?: AvatarColor;\n /** Badge text (e.g. count, status label) shown on the trailing side */\n badge?: string;\n /** Badge color variant */\n badgeVariant?: 'default' | 'primary' | 'success' | 'warning' | 'error';\n /** Metadata text shown on the trailing side (e.g. date, size) */\n metadata?: string;\n /** Optional action label */\n action?: string;\n /**\n * Accessible name of this row's action when the visible label repeats on\n * every row (e.g. „Entfernen“ → „iPhone · Safari entfernen“). The visible\n * label must be part of it (WCAG 2.5.3).\n */\n actionAriaLabel?: string;\n /**\n * URL of the row link (3.16, TD-4). The row renders as an `<a>` over its\n * full area (at least 44 px high) with real link semantics (middle click,\n * \"open in new tab\"). Not rendered with `href`: `action` (no control inside\n * a link; a dev warning). Not emitted: `itemClick` (see `linkClick`). With\n * `disabled` the row is the plain disabled row, no link. A custom\n * `lcListItem` template must not hold controls in `href` rows.\n */\n href?: string;\n /** Item identifier */\n id?: string;\n /** Whether the item is disabled */\n disabled?: boolean;\n /** Whether the item is selected / highlighted */\n selected?: boolean;\n /** Any additional data */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\n/**\n * List item size\n */\nexport type ListSize = 'sm' | 'md' | 'lg';\n\n/**\n * A plain click (or Enter) on an `href` row (3.16, TD-4): `item` is the row,\n * `event` the click. Call `event.preventDefault()` to navigate with your\n * router instead of a full page load.\n */\nexport interface ListLinkClickEvent {\n item: ListItem;\n event: MouseEvent;\n}\n\n/**\n * List component for displaying structured item collections.\n *\n * Features:\n * - Vertical and horizontal layout orientations\n * - Variant styles (default, bordered, card)\n * - Optional dividers between items\n * - Icon and avatar support per item\n * - Action buttons with click events\n * - Accessible with ARIA list role; `clickable` rows are keyboard-operable\n * - `ListItem.href` rows are real links over the full row (3.16, TD-4);\n * `linkClick` hands plain clicks to your router\n *\n * @example\n * ```html\n * <lc-list\n * [items]=\"listItems\"\n * orientation=\"vertical\"\n * [showDividers]=\"true\"\n * (itemClick)=\"handleItemClick($event)\"\n * />\n * ```\n */\n@Component({\n selector: 'lc-list',\n standalone: true,\n imports: [NgTemplateOutlet, IconComponent, ButtonComponent],\n templateUrl: './list.component.html',\n styleUrl: './list.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ListComponent {\n /** Custom item template provided via lcListItem directive */\n readonly itemTemplate = contentChild(ListItemTemplateDirective);\n\n /** Array of list items to display */\n items = input<ListItem[]>([]);\n\n /** Orientation of the list */\n orientation = input<ListOrientation>('vertical');\n\n /** Visual variant */\n variant = input<ListVariant>('default');\n\n /** Size of list items */\n size = input<ListSize>('md');\n\n /** Whether to show dividers between items */\n showDividers = input<boolean>(false);\n\n /**\n * Whether rows are interactive. When set, each row is rendered as a\n * focusable button (Enter / Space emit `itemClick`) so `itemClick` is\n * reachable from the keyboard. Set this whenever you handle `itemClick`.\n */\n clickable = input<boolean>(false);\n\n /**\n * Clamp each item's `description` to two lines (3.2). Set `false` for\n * reading text that must show in full (3.3, G-11).\n * @default true\n */\n clampDescription = input<boolean>(true);\n\n /**\n * Variant of the built-in row action (`ListItem.action`).\n * @default 'ghost'\n */\n actionVariant = input<ButtonVariant>('ghost');\n\n /**\n * Size of the built-in row action: `xs` (3.2, about 25 px) … `lg` (48.5 px,\n * the 44 px touch target).\n * @default 'xs'\n */\n actionSize = input<ButtonSize>('xs');\n\n /** Event emitted when an item is clicked */\n readonly itemClick = output<ListItem>();\n\n /** Event emitted when an action button is clicked */\n readonly actionClick = output<ListItem>();\n\n /**\n * A plain click (or Enter) on an `href` row: primary button, no\n * Ctrl/Cmd/Shift/Alt (3.16, TD-4). Emitted before the browser follows the\n * link; call `event.preventDefault()` and navigate with your router for an\n * in-app route (`router.navigateByUrl(item.href)`). The kit never prevents\n * the default; modifier and middle clicks are never emitted, so \"open in new\n * tab\" keeps working.\n */\n readonly linkClick = output<ListLinkClickEvent>();\n\n constructor() {\n effect(() => {\n if (!isDevMode()) return;\n // `items` may be bound to undefined (tolerated since 3.2).\n for (const item of this.items() ?? []) {\n if (this.isLinkRow(item) && item.action) {\n console.warn(`[lc-list] item \"${item.label}\" has href and action: the action is not rendered inside a link`);\n }\n }\n });\n }\n\n /** Whether a row renders as a link: `href` set and not disabled. */\n protected isLinkRow(item: ListItem): boolean {\n return !!item.href && !item.disabled;\n }\n\n /**\n * Computed CSS classes for the list\n */\n listClasses = computed(() => {\n const classes = ['lc-list'];\n\n classes.push(`lc-list--${this.orientation()}`);\n classes.push(`lc-list--${this.variant()}`);\n classes.push(`lc-list--${this.size()}`);\n\n if (this.showDividers()) {\n classes.push('lc-list--with-dividers');\n }\n\n if (this.clickable()) {\n classes.push('lc-list--clickable');\n }\n\n if (!this.clampDescription()) {\n classes.push('lc-list--no-clamp');\n }\n\n return classes.join(' ');\n });\n\n /**\n * Get CSS classes for a list item\n */\n getItemClasses(item: ListItem): string {\n const classes = ['lc-list__item'];\n\n if (item.disabled) {\n classes.push('lc-list__item--disabled');\n }\n\n if (item.selected) {\n classes.push('lc-list__item--selected');\n }\n\n return classes.join(' ');\n }\n\n /** CSS classes of an item's avatar (member colour, LK-7). */\n protected avatarClasses(item: ListItem): string {\n const color = item.avatarColor;\n return color && color !== 'default'\n ? `lc-list__avatar lc-list__avatar--member lc-list__avatar--${color}`\n : 'lc-list__avatar';\n }\n\n /**\n * Handle item click\n */\n onItemClick(item: ListItem): void {\n if (!item.disabled) {\n this.itemClick.emit(item);\n }\n }\n\n /**\n * Keyboard activation of a clickable row. Only reacts to keys on the row\n * itself: a nested control (e.g. the action button) handles its own Enter.\n */\n onItemKeydown(event: KeyboardEvent, item: ListItem): void {\n if (event.target !== event.currentTarget) return;\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.onItemClick(item);\n }\n }\n\n /**\n * Handle action button click\n */\n onActionClick(item: ListItem): void {\n this.actionClick.emit(item);\n }\n\n /**\n * A click on a link row: only a plain primary click reaches `linkClick`.\n * The default (following the link) is left to the browser and the consumer.\n */\n protected onLinkClick(event: MouseEvent, item: ListItem): void {\n if (event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return;\n this.linkClick.emit({ item, event });\n }\n}\n","<!--\n Row content is shared between the plain (legacy) row and the keyboard-\n operable row rendered when `clickable` is set.\n-->\n<ng-template #rowContent let-item>\n @if (itemTemplate(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl.template; context: { $implicit: item }\"></ng-container>\n } @else {\n <!-- Leading: Avatar or Icon -->\n @if (item.avatar) {\n <div [class]=\"avatarClasses(item)\">\n @if (item.avatar.startsWith('http') || item.avatar.startsWith('/') || item.avatar.startsWith('data:')) {\n <img [src]=\"item.avatar\" [alt]=\"item.label\" class=\"lc-list__avatar-img\" />\n } @else {\n <span class=\"lc-list__avatar-initials\">{{ item.avatar }}</span>\n }\n </div>\n } @else if (item.icon) {\n <lc-icon [name]=\"item.icon\" class=\"lc-list__icon\" size=\"sm\" [decorative]=\"true\" />\n }\n\n <!-- Content: Label, Subtitle, Description -->\n <div class=\"lc-list__content\">\n <span class=\"lc-list__label\">{{ item.label }}</span>\n @if (item.subtitle) {\n <span class=\"lc-list__subtitle\">{{ item.subtitle }}</span>\n }\n @if (item.description) {\n <span class=\"lc-list__description\">{{ item.description }}</span>\n }\n </div>\n\n <!-- Trailing: Badge, Metadata, Action -->\n <div class=\"lc-list__trailing\">\n @if (item.badge) {\n <span class=\"lc-list__badge lc-list__badge--{{ item.badgeVariant || 'default' }}\">{{ item.badge }}</span>\n }\n @if (item.metadata) {\n <span class=\"lc-list__metadata\">{{ item.metadata }}</span>\n }\n @if (item.action && !isLinkRow(item)) {\n <!-- The action is its own control: its click must not also activate the row. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- only stops the action click from also activating the row; the action is a real button -->\n <span class=\"lc-list__action-area\" (click)=\"$event.stopPropagation()\">\n <lc-button\n [variant]=\"actionVariant()\"\n [size]=\"actionSize()\"\n [ariaLabel]=\"item.actionAriaLabel ?? ''\"\n class=\"lc-list__action\"\n (clicked)=\"onActionClick(item)\"\n >\n {{ item.action }}\n </lc-button>\n </span>\n }\n </div>\n }\n</ng-template>\n\n<div [class]=\"listClasses()\" role=\"list\">\n @for (item of items(); track item.id || $index) {\n @if (isLinkRow(item)) {\n <!-- A real link over the whole row (3.16, TD-4); the row element carries the item styles. -->\n <div class=\"lc-list__item-wrapper\" role=\"listitem\">\n <a [class]=\"getItemClasses(item) + ' lc-list__item--link'\" [href]=\"item.href\" (click)=\"onLinkClick($event, item)\">\n <ng-container *ngTemplateOutlet=\"rowContent; context: { $implicit: item }\"></ng-container>\n </a>\n </div>\n } @else if (clickable()) {\n <div class=\"lc-list__item-wrapper\" role=\"listitem\">\n <div\n [class]=\"getItemClasses(item)\"\n role=\"button\"\n [attr.tabindex]=\"item.disabled ? -1 : 0\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n (click)=\"onItemClick(item)\"\n (keydown)=\"onItemKeydown($event, item)\"\n >\n <ng-container *ngTemplateOutlet=\"rowContent; context: { $implicit: item }\"></ng-container>\n </div>\n </div>\n } @else {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -- non-clickable lists keep reporting mouse clicks (backward compatible); use clickable for keyboard rows -->\n <div\n [class]=\"getItemClasses(item)\"\n role=\"listitem\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n (click)=\"onItemClick(item)\"\n >\n <ng-container *ngTemplateOutlet=\"rowContent; context: { $implicit: item }\"></ng-container>\n </div>\n }\n }\n</div>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, LOCALE_ID, computed, effect, inject, input, isDevMode } from "@angular/core";
|
|
3
|
+
const MINOR_UNITS = {
|
|
4
|
+
BIF: 0,
|
|
5
|
+
CLP: 0,
|
|
6
|
+
DJF: 0,
|
|
7
|
+
GNF: 0,
|
|
8
|
+
ISK: 0,
|
|
9
|
+
JPY: 0,
|
|
10
|
+
KMF: 0,
|
|
11
|
+
KRW: 0,
|
|
12
|
+
PYG: 0,
|
|
13
|
+
RWF: 0,
|
|
14
|
+
UGX: 0,
|
|
15
|
+
UYI: 0,
|
|
16
|
+
VND: 0,
|
|
17
|
+
VUV: 0,
|
|
18
|
+
XAF: 0,
|
|
19
|
+
XOF: 0,
|
|
20
|
+
XPF: 0,
|
|
21
|
+
BHD: 3,
|
|
22
|
+
IQD: 3,
|
|
23
|
+
JOD: 3,
|
|
24
|
+
KWD: 3,
|
|
25
|
+
LYD: 3,
|
|
26
|
+
OMR: 3,
|
|
27
|
+
TND: 3,
|
|
28
|
+
CLF: 4,
|
|
29
|
+
UYW: 4
|
|
30
|
+
};
|
|
31
|
+
function moneyMinorUnits(currency) {
|
|
32
|
+
return MINOR_UNITS[currency.toUpperCase()] ?? 2;
|
|
33
|
+
}
|
|
34
|
+
const RTL_LANGUAGES = /* @__PURE__ */ new Set([
|
|
35
|
+
"ar",
|
|
36
|
+
"ckb",
|
|
37
|
+
"dv",
|
|
38
|
+
"fa",
|
|
39
|
+
"he",
|
|
40
|
+
"iw",
|
|
41
|
+
"ks",
|
|
42
|
+
"ps",
|
|
43
|
+
"sd",
|
|
44
|
+
"ug",
|
|
45
|
+
"ur",
|
|
46
|
+
"yi"
|
|
47
|
+
]);
|
|
48
|
+
function moneyDirection(locale) {
|
|
49
|
+
return RTL_LANGUAGES.has(locale.split(/[-_]/)[0].toLowerCase()) ? "rtl" : "ltr";
|
|
50
|
+
}
|
|
51
|
+
function decimalString(amountMinor, digits) {
|
|
52
|
+
const abs = String(Math.abs(amountMinor)).padStart(digits + 1, "0");
|
|
53
|
+
const value = digits === 0 ? abs : `${abs.slice(0, -digits)}.${abs.slice(-digits)}`;
|
|
54
|
+
return amountMinor < 0 ? `-${value}` : value;
|
|
55
|
+
}
|
|
56
|
+
function numberFormat(locale, options) {
|
|
57
|
+
try {
|
|
58
|
+
return new Intl.NumberFormat(locale, options);
|
|
59
|
+
} catch {
|
|
60
|
+
return new Intl.NumberFormat("en-US", options);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function formatMoney(amountMinor, currency, options = {}) {
|
|
64
|
+
if (!Number.isSafeInteger(amountMinor) || !/^[A-Za-z]{3}$/.test(currency ?? "")) return null;
|
|
65
|
+
const { locale = "en-US", signDisplay = "auto", minusLabel = "minus", plusLabel = "plus" } = options;
|
|
66
|
+
const digits = moneyMinorUnits(currency);
|
|
67
|
+
const value = decimalString(amountMinor, digits);
|
|
68
|
+
const base = {
|
|
69
|
+
style: "currency",
|
|
70
|
+
currency: currency.toUpperCase(),
|
|
71
|
+
signDisplay,
|
|
72
|
+
minimumFractionDigits: digits,
|
|
73
|
+
maximumFractionDigits: digits
|
|
74
|
+
};
|
|
75
|
+
let visible;
|
|
76
|
+
let named;
|
|
77
|
+
try {
|
|
78
|
+
visible = numberFormat(locale || "en-US", base).formatToParts(value);
|
|
79
|
+
named = numberFormat(locale || "en-US", {
|
|
80
|
+
...base,
|
|
81
|
+
currencyDisplay: "name"
|
|
82
|
+
}).formatToParts(value);
|
|
83
|
+
} catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
text: visible.map((p) => p.type === "minusSign" ? p.value.replace(/-/g, "−") : p.value).join(""),
|
|
88
|
+
spoken: named.map((p) => p.type === "minusSign" ? `${minusLabel} ` : p.type === "plusSign" ? `${plusLabel} ` : p.value).join("").replace(/\s+/g, " ").trim()
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
var MoneyComponent = class MoneyComponent {
|
|
92
|
+
appLocale = inject(LOCALE_ID);
|
|
93
|
+
amountMinor = input.required(...ngDevMode ? [{ debugName: "amountMinor" }] : /* istanbul ignore next */ []);
|
|
94
|
+
currency = input.required(...ngDevMode ? [{ debugName: "currency" }] : /* istanbul ignore next */ []);
|
|
95
|
+
locale = input("", ...ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []);
|
|
96
|
+
signDisplay = input("auto", ...ngDevMode ? [{ debugName: "signDisplay" }] : /* istanbul ignore next */ []);
|
|
97
|
+
minusLabel = input("minus", ...ngDevMode ? [{ debugName: "minusLabel" }] : /* istanbul ignore next */ []);
|
|
98
|
+
plusLabel = input("plus", ...ngDevMode ? [{ debugName: "plusLabel" }] : /* istanbul ignore next */ []);
|
|
99
|
+
effectiveLocale = computed(() => this.locale() || this.appLocale || "en-US", ...ngDevMode ? [{ debugName: "effectiveLocale" }] : /* istanbul ignore next */ []);
|
|
100
|
+
formatted = computed(() => formatMoney(this.amountMinor(), this.currency(), {
|
|
101
|
+
locale: this.effectiveLocale(),
|
|
102
|
+
signDisplay: this.signDisplay(),
|
|
103
|
+
minusLabel: this.minusLabel(),
|
|
104
|
+
plusLabel: this.plusLabel()
|
|
105
|
+
}), ...ngDevMode ? [{ debugName: "formatted" }] : /* istanbul ignore next */ []);
|
|
106
|
+
dir = computed(() => moneyDirection(this.effectiveLocale()), ...ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []);
|
|
107
|
+
constructor() {
|
|
108
|
+
effect(() => {
|
|
109
|
+
if (!isDevMode()) return;
|
|
110
|
+
if (!Number.isSafeInteger(this.amountMinor())) console.warn("[lc-money] amountMinor must be a safe integer");
|
|
111
|
+
else if (!this.formatted()) console.warn(`[lc-money] unknown currency "${this.currency()}"`);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
115
|
+
minVersion: "12.0.0",
|
|
116
|
+
version: "22.2.2",
|
|
117
|
+
ngImport: i0,
|
|
118
|
+
type: MoneyComponent,
|
|
119
|
+
deps: [],
|
|
120
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
121
|
+
});
|
|
122
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
123
|
+
minVersion: "17.0.0",
|
|
124
|
+
version: "22.2.2",
|
|
125
|
+
type: MoneyComponent,
|
|
126
|
+
isStandalone: true,
|
|
127
|
+
selector: "lc-money",
|
|
128
|
+
inputs: {
|
|
129
|
+
amountMinor: {
|
|
130
|
+
classPropertyName: "amountMinor",
|
|
131
|
+
publicName: "amountMinor",
|
|
132
|
+
isSignal: true,
|
|
133
|
+
isRequired: true,
|
|
134
|
+
transformFunction: null
|
|
135
|
+
},
|
|
136
|
+
currency: {
|
|
137
|
+
classPropertyName: "currency",
|
|
138
|
+
publicName: "currency",
|
|
139
|
+
isSignal: true,
|
|
140
|
+
isRequired: true,
|
|
141
|
+
transformFunction: null
|
|
142
|
+
},
|
|
143
|
+
locale: {
|
|
144
|
+
classPropertyName: "locale",
|
|
145
|
+
publicName: "locale",
|
|
146
|
+
isSignal: true,
|
|
147
|
+
isRequired: false,
|
|
148
|
+
transformFunction: null
|
|
149
|
+
},
|
|
150
|
+
signDisplay: {
|
|
151
|
+
classPropertyName: "signDisplay",
|
|
152
|
+
publicName: "signDisplay",
|
|
153
|
+
isSignal: true,
|
|
154
|
+
isRequired: false,
|
|
155
|
+
transformFunction: null
|
|
156
|
+
},
|
|
157
|
+
minusLabel: {
|
|
158
|
+
classPropertyName: "minusLabel",
|
|
159
|
+
publicName: "minusLabel",
|
|
160
|
+
isSignal: true,
|
|
161
|
+
isRequired: false,
|
|
162
|
+
transformFunction: null
|
|
163
|
+
},
|
|
164
|
+
plusLabel: {
|
|
165
|
+
classPropertyName: "plusLabel",
|
|
166
|
+
publicName: "plusLabel",
|
|
167
|
+
isSignal: true,
|
|
168
|
+
isRequired: false,
|
|
169
|
+
transformFunction: null
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
host: { classAttribute: "lc-money" },
|
|
173
|
+
ngImport: i0,
|
|
174
|
+
template: "@if (formatted(); as m) {<span class=\"lc-money__amount\" aria-hidden=\"true\" [attr.dir]=\"dir()\">{{ m.text }}</span><span class=\"lc-money__spoken\">{{ m.spoken }}</span>}",
|
|
175
|
+
isInline: true,
|
|
176
|
+
styles: [":host{position:relative;display:inline;font-variant-numeric:tabular-nums;white-space:nowrap}.lc-money__spoken{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;-webkit-user-select:none;user-select:none}\n"],
|
|
177
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
181
|
+
minVersion: "12.0.0",
|
|
182
|
+
version: "22.2.2",
|
|
183
|
+
ngImport: i0,
|
|
184
|
+
type: MoneyComponent,
|
|
185
|
+
decorators: [{
|
|
186
|
+
type: Component,
|
|
187
|
+
args: [{
|
|
188
|
+
selector: "lc-money",
|
|
189
|
+
standalone: true,
|
|
190
|
+
template: "@if (formatted(); as m) {<span class=\"lc-money__amount\" aria-hidden=\"true\" [attr.dir]=\"dir()\">{{ m.text }}</span><span class=\"lc-money__spoken\">{{ m.spoken }}</span>}",
|
|
191
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
192
|
+
host: { class: "lc-money" },
|
|
193
|
+
styles: [":host{position:relative;display:inline;font-variant-numeric:tabular-nums;white-space:nowrap}.lc-money__spoken{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;-webkit-user-select:none;user-select:none}\n"]
|
|
194
|
+
}]
|
|
195
|
+
}],
|
|
196
|
+
ctorParameters: () => [],
|
|
197
|
+
propDecorators: {
|
|
198
|
+
amountMinor: [{
|
|
199
|
+
type: i0.Input,
|
|
200
|
+
args: [{
|
|
201
|
+
isSignal: true,
|
|
202
|
+
alias: "amountMinor",
|
|
203
|
+
required: true
|
|
204
|
+
}]
|
|
205
|
+
}],
|
|
206
|
+
currency: [{
|
|
207
|
+
type: i0.Input,
|
|
208
|
+
args: [{
|
|
209
|
+
isSignal: true,
|
|
210
|
+
alias: "currency",
|
|
211
|
+
required: true
|
|
212
|
+
}]
|
|
213
|
+
}],
|
|
214
|
+
locale: [{
|
|
215
|
+
type: i0.Input,
|
|
216
|
+
args: [{
|
|
217
|
+
isSignal: true,
|
|
218
|
+
alias: "locale",
|
|
219
|
+
required: false
|
|
220
|
+
}]
|
|
221
|
+
}],
|
|
222
|
+
signDisplay: [{
|
|
223
|
+
type: i0.Input,
|
|
224
|
+
args: [{
|
|
225
|
+
isSignal: true,
|
|
226
|
+
alias: "signDisplay",
|
|
227
|
+
required: false
|
|
228
|
+
}]
|
|
229
|
+
}],
|
|
230
|
+
minusLabel: [{
|
|
231
|
+
type: i0.Input,
|
|
232
|
+
args: [{
|
|
233
|
+
isSignal: true,
|
|
234
|
+
alias: "minusLabel",
|
|
235
|
+
required: false
|
|
236
|
+
}]
|
|
237
|
+
}],
|
|
238
|
+
plusLabel: [{
|
|
239
|
+
type: i0.Input,
|
|
240
|
+
args: [{
|
|
241
|
+
isSignal: true,
|
|
242
|
+
alias: "plusLabel",
|
|
243
|
+
required: false
|
|
244
|
+
}]
|
|
245
|
+
}]
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
export { MoneyComponent, formatMoney };
|
|
249
|
+
|
|
250
|
+
//# sourceMappingURL=lifecorner-angular-ui-kit-money.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-money.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/money/money-format.ts","../../../../libs/angular-ui-kit/src/lib/money/money.component.ts"],"sourcesContent":["/**\n * How the sign of an amount shows, as `Intl.NumberFormat`'s `signDisplay`:\n * - `auto`: negative amounts only (−42,17 €)\n * - `always`: plus and minus, also on zero (+0,00 €)\n * - `exceptZero`: plus and minus, no sign on zero\n * - `never`: no sign\n */\nexport type MoneySignDisplay = 'auto' | 'always' | 'exceptZero' | 'never';\n\n/** Options of {@link formatMoney}. */\nexport interface MoneyFormatOptions {\n /** BCP 47 locale. An invalid one falls back to `en-US`. @default 'en-US' */\n locale?: string;\n /** As `Intl.NumberFormat`'s `signDisplay`. @default 'auto' */\n signDisplay?: MoneySignDisplay;\n /** Spoken word for the minus sign. @default 'minus' */\n minusLabel?: string;\n /** Spoken word for the plus sign. @default 'plus' */\n plusLabel?: string;\n}\n\n/** A formatted amount: the visible text and the words a screen reader speaks. */\nexport interface MoneyText {\n /** Visible text, e.g. „−42,17 €“ (U+2212 minus, U+00A0 from `Intl`). */\n text: string;\n /** Spoken text, e.g. „minus 42,17 Euro“. */\n spoken: string;\n}\n\n/**\n * Minor-unit exponents per ISO 4217 that are not 2. Not `Intl`'s digits:\n * CLDR gives 0 for HUF, IDR, RSD and IQD, which ISO 4217 does not.\n */\nconst MINOR_UNITS: Readonly<Record<string, number>> = {\n BIF: 0, CLP: 0, DJF: 0, GNF: 0, ISK: 0, JPY: 0, KMF: 0, KRW: 0, PYG: 0,\n RWF: 0, UGX: 0, UYI: 0, VND: 0, VUV: 0, XAF: 0, XOF: 0, XPF: 0,\n BHD: 3, IQD: 3, JOD: 3, KWD: 3, LYD: 3, OMR: 3, TND: 3,\n CLF: 4, UYW: 4,\n};\n\n/** The ISO 4217 minor-unit exponent of `currency` (2 unless listed). */\nexport function moneyMinorUnits(currency: string): number {\n return MINOR_UNITS[currency.toUpperCase()] ?? 2;\n}\n\n/** Primary language subtags written right to left (a fixed list: the same on server and browser). */\nconst RTL_LANGUAGES = new Set(['ar', 'ckb', 'dv', 'fa', 'he', 'iw', 'ks', 'ps', 'sd', 'ug', 'ur', 'yi']);\n\n/** Text direction of an amount formatted for `locale`. */\nexport function moneyDirection(locale: string): 'ltr' | 'rtl' {\n return RTL_LANGUAGES.has(locale.split(/[-_]/)[0].toLowerCase()) ? 'rtl' : 'ltr';\n}\n\n/** The exact decimal string of an integer amount in minor units: 4217, 2 → \"42.17\". */\nfunction decimalString(amountMinor: number, digits: number): string {\n const abs = String(Math.abs(amountMinor)).padStart(digits + 1, '0');\n const value = digits === 0 ? abs : `${abs.slice(0, -digits)}.${abs.slice(-digits)}`;\n return amountMinor < 0 ? `-${value}` : value; // −0 has no sign\n}\n\n/** `Intl.NumberFormat` for `locale`, or for `en-US` when the locale is invalid. */\nfunction numberFormat(locale: string, options: Intl.NumberFormatOptions): Intl.NumberFormat {\n try {\n return new Intl.NumberFormat(locale, options);\n } catch {\n return new Intl.NumberFormat('en-US', options);\n }\n}\n\n/**\n * Formats an amount of money given in integer minor units (cents, yen, fils)\n * exactly, never through a float: the decimal string goes into `Intl`.\n * Returns `null` for an amount that is not a safe integer or a currency that\n * is not a three-letter code. This is the formatter of `lc-money`, for table\n * `formatter`s and texts.\n *\n * @example\n * ```ts\n * formatMoney(-4217, 'EUR', { locale: 'de-DE' });\n * // { text: '−42,17 €', spoken: 'minus 42,17 Euro' }\n * ```\n */\nexport function formatMoney(amountMinor: number, currency: string, options: MoneyFormatOptions = {}): MoneyText | null {\n if (!Number.isSafeInteger(amountMinor) || !/^[A-Za-z]{3}$/.test(currency ?? '')) return null;\n const { locale = 'en-US', signDisplay = 'auto', minusLabel = 'minus', plusLabel = 'plus' } = options;\n const digits = moneyMinorUnits(currency);\n const value = decimalString(amountMinor, digits) as unknown as number; // exact decimal string (Intl.NumberFormat v3)\n const base: Intl.NumberFormatOptions = {\n style: 'currency',\n currency: currency.toUpperCase(),\n signDisplay,\n minimumFractionDigits: digits,\n maximumFractionDigits: digits,\n };\n let visible: Intl.NumberFormatPart[];\n let named: Intl.NumberFormatPart[];\n try {\n visible = numberFormat(locale || 'en-US', base).formatToParts(value);\n named = numberFormat(locale || 'en-US', { ...base, currencyDisplay: 'name' }).formatToParts(value);\n } catch {\n return null;\n }\n const text = visible.map((p) => (p.type === 'minusSign' ? p.value.replace(/-/g, '−') : p.value)).join('');\n const spoken = named\n .map((p) => (p.type === 'minusSign' ? `${minusLabel} ` : p.type === 'plusSign' ? `${plusLabel} ` : p.value))\n .join('')\n .replace(/\\s+/g, ' ')\n .trim();\n return { text, spoken };\n}\n","import { ChangeDetectionStrategy, Component, LOCALE_ID, computed, effect, inject, input, isDevMode } from '@angular/core';\nimport { formatMoney, moneyDirection, type MoneySignDisplay } from './money-format';\n\n/**\n * Displays an amount of money (3.16, BA-4): locale, currency, sign, tabular\n * figures and a spoken text. Display only, no input parsing or conversion.\n *\n * - `amountMinor` is an integer in the currency's minor units (cents, yen,\n * fils), formatted exactly through a decimal string, never a float. Minor\n * units follow ISO 4217: 2, except 0 (BIF CLP DJF GNF ISK JPY KMF KRW PYG\n * RWF UGX UYI VND VUV XAF XOF XPF), 3 (BHD IQD JOD KWD LYD OMR TND) and 4\n * (CLF UYW).\n * - The visible amount („−42,17 €“, U+2212 minus, a no-break space from\n * `Intl`) is `aria-hidden`; a visually hidden span holds the words\n * („minus 42,17 Euro“), so a screen reader reads the amount once.\n * - Tabular figures, no wrapping inside the amount; the amount is a `dir`\n * isolate (`ltr`, or `rtl` for an RTL locale), safe inside RTL text.\n * - Font and colour come from the context; colour never carries the sign.\n * - `locale` empty: the app's `LOCALE_ID` (Angular's default `en-US`), the\n * same on the server and in the browser.\n * - For table `formatter`s and texts use {@link formatMoney}.\n *\n * Separate a `lc-money` from adjacent text with a space in your template, so\n * the spoken text does not run into the words around it.\n *\n * @example\n * ```html\n * <lc-money [amountMinor]=\"-4217\" currency=\"EUR\" locale=\"de-DE\" />\n * ```\n */\n@Component({\n selector: 'lc-money',\n standalone: true,\n // No whitespace between the spans: the visible amount and the words are separate texts.\n template:\n '@if (formatted(); as m) {<span class=\"lc-money__amount\" aria-hidden=\"true\" [attr.dir]=\"dir()\">{{ m.text }}</span><span class=\"lc-money__spoken\">{{ m.spoken }}</span>}',\n styleUrl: './money.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { class: 'lc-money' },\n})\nexport class MoneyComponent {\n private readonly appLocale = inject(LOCALE_ID);\n\n /**\n * Amount in minor units of `currency` (cents, yen, fils): a safe integer\n * (±9,007,199,254,740,991), formatted exactly. Anything else renders\n * nothing (a dev warning).\n */\n readonly amountMinor = input.required<number>();\n\n /**\n * ISO 4217 currency code (`EUR`, `USD`, `JPY`, `KWD`). It sets the minor\n * units and the symbol. Not a three-letter code: renders nothing (a dev\n * warning).\n */\n readonly currency = input.required<string>();\n\n /**\n * BCP 47 locale of the amount (`de-DE`, `en-GB`). Empty: the app's\n * `LOCALE_ID` (Angular's default `en-US`). An invalid locale falls back to\n * `en-US`.\n * @default ''\n */\n readonly locale = input<string>('');\n\n /**\n * Which signs show, as `Intl.NumberFormat`: `auto` (negative only),\n * `always`, `exceptZero`, `never`. The spoken text says the sign whenever\n * it shows.\n * @default 'auto'\n */\n readonly signDisplay = input<MoneySignDisplay>('auto');\n\n /**\n * Spoken word for the minus sign („minus 42,17 Euro“; the same in German).\n * @default 'minus'\n */\n readonly minusLabel = input<string>('minus');\n\n /**\n * Spoken word for the plus sign („plus 42,17 Euro“; the same in German).\n * @default 'plus'\n */\n readonly plusLabel = input<string>('plus');\n\n /** The locale in use: the `locale` input or the app's `LOCALE_ID`. */\n protected readonly effectiveLocale = computed(() => this.locale() || this.appLocale || 'en-US');\n\n protected readonly formatted = computed(() =>\n formatMoney(this.amountMinor(), this.currency(), {\n locale: this.effectiveLocale(),\n signDisplay: this.signDisplay(),\n minusLabel: this.minusLabel(),\n plusLabel: this.plusLabel(),\n }),\n );\n\n protected readonly dir = computed(() => moneyDirection(this.effectiveLocale()));\n\n constructor() {\n effect(() => {\n if (!isDevMode()) return;\n if (!Number.isSafeInteger(this.amountMinor())) {\n console.warn('[lc-money] amountMinor must be a safe integer');\n } else if (!this.formatted()) {\n console.warn(`[lc-money] unknown currency \"${this.currency()}\"`);\n }\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@ var NextStepCardComponent = class NextStepCardComponent {
|
|
|
11
11
|
titleTag = input("div", ...ngDevMode ? [{ debugName: "titleTag" }] : /* istanbul ignore next */ []);
|
|
12
12
|
actionsLayout = input("inline", ...ngDevMode ? [{ debugName: "actionsLayout" }] : /* istanbul ignore next */ []);
|
|
13
13
|
actionSize = input("sm", ...ngDevMode ? [{ debugName: "actionSize" }] : /* istanbul ignore next */ []);
|
|
14
|
+
actionsStyle = input("default", ...ngDevMode ? [{ debugName: "actionsStyle" }] : /* istanbul ignore next */ []);
|
|
14
15
|
message = input(...ngDevMode ? [void 0, { debugName: "message" }] : /* istanbul ignore next */ []);
|
|
15
16
|
primaryLabel = input(...ngDevMode ? [void 0, { debugName: "primaryLabel" }] : /* istanbul ignore next */ []);
|
|
16
17
|
primaryIcon = input(...ngDevMode ? [void 0, { debugName: "primaryIcon" }] : /* istanbul ignore next */ []);
|
|
@@ -39,6 +40,9 @@ var NextStepCardComponent = class NextStepCardComponent {
|
|
|
39
40
|
effect(() => {
|
|
40
41
|
if (isDevMode() && this.primaryDisabled() && !this.primaryDisabledReason()) console.warn("[lc-next-step-card] `primaryDisabled` is set without a `primaryDisabledReason`. A disabled primary action must explain why (shown as tooltip).");
|
|
41
42
|
});
|
|
43
|
+
effect(() => {
|
|
44
|
+
if (isDevMode() && this.actionsStyle() === "equal" && this.actionSize() !== "lg") console.warn("[lc-next-step-card] actionsStyle=\"equal\" needs actionSize=\"lg\" (44 px)");
|
|
45
|
+
});
|
|
42
46
|
}
|
|
43
47
|
ngAfterViewChecked() {
|
|
44
48
|
const el = this.actionsSlot()?.nativeElement;
|
|
@@ -108,6 +112,13 @@ var NextStepCardComponent = class NextStepCardComponent {
|
|
|
108
112
|
isRequired: false,
|
|
109
113
|
transformFunction: null
|
|
110
114
|
},
|
|
115
|
+
actionsStyle: {
|
|
116
|
+
classPropertyName: "actionsStyle",
|
|
117
|
+
publicName: "actionsStyle",
|
|
118
|
+
isSignal: true,
|
|
119
|
+
isRequired: false,
|
|
120
|
+
transformFunction: null
|
|
121
|
+
},
|
|
111
122
|
message: {
|
|
112
123
|
classPropertyName: "message",
|
|
113
124
|
publicName: "message",
|
|
@@ -198,7 +209,7 @@ var NextStepCardComponent = class NextStepCardComponent {
|
|
|
198
209
|
isSignal: true
|
|
199
210
|
}],
|
|
200
211
|
ngImport: i0,
|
|
201
|
-
template: "<div [class]=\"cardClasses()\" role=\"region\" [attr.aria-label]=\"cardTitle()\">\n <div class=\"lc-next-step-card__icon\" aria-hidden=\"true\">\n <lc-icon [name]=\"icon()\" size=\"md\" [decorative]=\"true\" />\n </div>\n\n <div class=\"lc-next-step-card__body\">\n @switch (titleTag()) {\n @case ('h2') {\n <h2 class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </h2>\n }\n @case ('h3') {\n <h3 class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </h3>\n }\n @default {\n <div class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </div>\n }\n }\n @if (message()) {\n <p class=\"lc-next-step-card__message\">{{ message() }}</p>\n }\n <div class=\"lc-next-step-card__custom-message\">\n <ng-content />\n </div>\n <!-- Form-safe body: no inherited message text styles. -->\n <div class=\"lc-next-step-card__content\">\n <ng-content select=\"[slot='body']\" />\n </div>\n <div class=\"lc-next-step-card__blockers\">\n <ng-content select=\"[slot='blockers']\" />\n </div>\n <div class=\"lc-next-step-card__meta\">\n <ng-content select=\"[slot='meta']\" />\n </div>\n </div>\n\n <div class=\"lc-next-step-card__actions\" [class.lc-next-step-card__actions--empty]=\"!hasActions()\">\n <div #actionsSlot class=\"lc-next-step-card__actions-slot\">\n <ng-content select=\"[slot='actions']\" />\n </div>\n @if (!hasProjectedActions()) {\n @if (secondaryLabel()) {\n <lc-button variant=\"ghost\" [size]=\"actionSize()\" (clicked)=\"secondaryClick.emit()\">\n {{ secondaryLabel() }}\n <lc-icon slot=\"icon-after\" name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </lc-button>\n }\n @if (showLink()) {\n <a\n class=\"btn btn-secondary btn-{{ actionSize() }} lc-next-step-card__link\"\n [href]=\"linkHref()\"\n [attr.target]=\"linkTarget()\"\n [attr.rel]=\"linkRel()\"\n >\n <lc-icon name=\"external-link\" size=\"sm\" [decorative]=\"true\" />\n {{ linkLabel() }}\n </a>\n } @else if (primaryLabel()) {\n <lc-button\n variant=\"primary\"\n [size]=\"actionSize()\"\n [loading]=\"primaryLoading()\"\n [disabled]=\"primaryDisabled()\"\n [disabledReason]=\"primaryDisabledReason()\"\n (clicked)=\"primaryClick.emit()\"\n >\n @if (primaryIcon()) {\n <lc-icon slot=\"icon-before\" [name]=\"primaryIcon()!\" size=\"sm\" [decorative]=\"true\" />\n }\n {{ primaryLabel() }}\n </lc-button>\n }\n }\n </div>\n</div>\n",
|
|
212
|
+
template: "<div [class]=\"cardClasses()\" role=\"region\" [attr.aria-label]=\"cardTitle()\">\n <div class=\"lc-next-step-card__icon\" aria-hidden=\"true\">\n <lc-icon [name]=\"icon()\" size=\"md\" [decorative]=\"true\" />\n </div>\n\n <div class=\"lc-next-step-card__body\">\n @switch (titleTag()) {\n @case ('h2') {\n <h2 class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </h2>\n }\n @case ('h3') {\n <h3 class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </h3>\n }\n @default {\n <div class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </div>\n }\n }\n @if (message()) {\n <p class=\"lc-next-step-card__message\">{{ message() }}</p>\n }\n <div class=\"lc-next-step-card__custom-message\">\n <ng-content />\n </div>\n <!-- Form-safe body: no inherited message text styles. -->\n <div class=\"lc-next-step-card__content\">\n <ng-content select=\"[slot='body']\" />\n </div>\n <div class=\"lc-next-step-card__blockers\">\n <ng-content select=\"[slot='blockers']\" />\n </div>\n <div class=\"lc-next-step-card__meta\">\n <ng-content select=\"[slot='meta']\" />\n </div>\n </div>\n\n <div class=\"lc-next-step-card__actions\" [class.lc-next-step-card__actions--empty]=\"!hasActions()\">\n <div #actionsSlot class=\"lc-next-step-card__actions-slot\">\n <ng-content select=\"[slot='actions']\" />\n </div>\n @if (!hasProjectedActions() && actionsStyle() === 'equal') {\n <!-- Two answers of the same weight (3.16, BA-5): the primary first, both outline in the primary tone. -->\n @if (showLink()) {\n <a\n class=\"btn btn-secondary btn-{{ actionSize() }} lc-next-step-card__link\"\n [href]=\"linkHref()\"\n [attr.target]=\"linkTarget()\"\n [attr.rel]=\"linkRel()\"\n >\n <lc-icon name=\"external-link\" size=\"sm\" [decorative]=\"true\" />\n {{ linkLabel() }}\n </a>\n } @else if (primaryLabel()) {\n <lc-button\n variant=\"outline\"\n tone=\"primary\"\n [size]=\"actionSize()\"\n [loading]=\"primaryLoading()\"\n [disabled]=\"primaryDisabled()\"\n [disabledReason]=\"primaryDisabledReason()\"\n (clicked)=\"primaryClick.emit()\"\n >\n @if (primaryIcon()) {\n <lc-icon slot=\"icon-before\" [name]=\"primaryIcon()!\" size=\"sm\" [decorative]=\"true\" />\n }\n {{ primaryLabel() }}\n </lc-button>\n }\n @if (secondaryLabel()) {\n <lc-button variant=\"outline\" tone=\"primary\" [size]=\"actionSize()\" (clicked)=\"secondaryClick.emit()\">\n {{ secondaryLabel() }}\n </lc-button>\n }\n } @else if (!hasProjectedActions()) {\n @if (secondaryLabel()) {\n <lc-button variant=\"ghost\" [size]=\"actionSize()\" (clicked)=\"secondaryClick.emit()\">\n {{ secondaryLabel() }}\n <lc-icon slot=\"icon-after\" name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </lc-button>\n }\n @if (showLink()) {\n <a\n class=\"btn btn-secondary btn-{{ actionSize() }} lc-next-step-card__link\"\n [href]=\"linkHref()\"\n [attr.target]=\"linkTarget()\"\n [attr.rel]=\"linkRel()\"\n >\n <lc-icon name=\"external-link\" size=\"sm\" [decorative]=\"true\" />\n {{ linkLabel() }}\n </a>\n } @else if (primaryLabel()) {\n <lc-button\n variant=\"primary\"\n [size]=\"actionSize()\"\n [loading]=\"primaryLoading()\"\n [disabled]=\"primaryDisabled()\"\n [disabledReason]=\"primaryDisabledReason()\"\n (clicked)=\"primaryClick.emit()\"\n >\n @if (primaryIcon()) {\n <lc-icon slot=\"icon-before\" [name]=\"primaryIcon()!\" size=\"sm\" [decorative]=\"true\" />\n }\n {{ primaryLabel() }}\n </lc-button>\n }\n }\n </div>\n</div>\n",
|
|
202
213
|
styles: [":host{display:block;inline-size:100%;container:lc-next-step-card/inline-size}.lc-next-step-card{display:flex;align-items:flex-start;flex-wrap:wrap;gap:var(--lc-density-gap-md, var(--spacing-4, 1rem));padding:var(--lc-density-padding-md, var(--spacing-4, 1rem)) var(--lc-density-padding-lg, var(--spacing-6, 1.5rem));background:var(--color-surface);border:1px solid var(--color-border);border-left:4px solid var(--lc-nsc-rail);border-radius:var(--border-radius-lg, .75rem)}.lc-next-step-card--neutral{--lc-nsc-rail: var(--color-border);--lc-nsc-tint: var(--color-surface-hover);--lc-nsc-ink: var(--color-text-secondary)}.lc-next-step-card--primary{--lc-nsc-rail: var(--color-primary);--lc-nsc-tint: var(--color-primary-subtle);--lc-nsc-ink: var(--color-on-primary-subtle)}.lc-next-step-card--success{--lc-nsc-rail: var(--color-success);--lc-nsc-tint: var(--color-success-subtle);--lc-nsc-ink: var(--color-on-success-subtle)}.lc-next-step-card--warning{--lc-nsc-rail: var(--color-warning);--lc-nsc-tint: var(--color-warning-subtle);--lc-nsc-ink: var(--color-on-warning-subtle)}.lc-next-step-card--info{--lc-nsc-rail: var(--color-info);--lc-nsc-tint: var(--color-info-subtle);--lc-nsc-ink: var(--color-on-info-subtle)}.lc-next-step-card__icon{flex:none;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border-radius:999px;background:var(--lc-nsc-tint);color:var(--lc-nsc-ink)}.lc-next-step-card__body{flex:1 1 16rem;min-width:0}.lc-next-step-card__title{margin:0;font-family:inherit;font-size:var(--typography-font-size-base, 1rem);font-weight:var(--typography-font-weight-semibold, 600);line-height:var(--line-height-tight, 1.25);color:var(--color-text-primary);letter-spacing:-.01em;overflow-wrap:break-word}.lc-next-step-card__message{margin:.2rem 0 0;font-size:var(--typography-font-size-sm, .875rem);line-height:1.55;color:var(--color-text-secondary)}.lc-next-step-card__custom-message{font-size:var(--typography-font-size-sm, .875rem);line-height:1.55;color:var(--color-text-secondary)}.lc-next-step-card__custom-message:empty{display:none}:host ::ng-deep .lc-next-step-card__custom-message>p{margin:.2rem 0 0}.lc-next-step-card__content{margin-top:var(--lc-density-gap-sm, .5rem);min-width:0}.lc-next-step-card__content:empty{display:none}.lc-next-step-card__blockers{display:flex;flex-direction:column;gap:.25rem;margin-top:var(--lc-density-gap-sm, .5rem);padding-top:var(--lc-density-gap-sm, .5rem);border-top:1px solid var(--color-border-subtle, var(--color-border));font-size:var(--typography-font-size-sm, .875rem);color:var(--color-text-secondary)}.lc-next-step-card__blockers:empty{display:none}:host ::ng-deep .lc-next-step-card__blockers>*{display:flex;align-items:baseline;gap:.5rem;margin:0}:host ::ng-deep .lc-next-step-card__blockers>*:before{content:\"\";flex:none;width:7px;height:7px;border-radius:999px;background:var(--lc-nsc-rail);transform:translateY(-1px)}.lc-next-step-card__meta{display:flex;align-items:center;gap:.5rem;margin-top:var(--lc-density-gap-sm, .5rem);padding-top:var(--lc-density-gap-sm, .5rem);border-top:1px solid var(--color-border-subtle, var(--color-border));font-size:var(--typography-font-size-xs, .8125rem);color:var(--color-text-tertiary)}.lc-next-step-card__meta:empty{display:none}.lc-next-step-card__actions{display:flex;align-items:center;flex-wrap:wrap;gap:var(--lc-density-gap-sm, .5rem);margin-left:auto}.lc-next-step-card__actions--empty{display:none}.lc-next-step-card__actions-slot{display:contents}.lc-next-step-card__link{display:inline-flex;align-items:center;gap:.375rem;text-decoration:none}:host ::ng-deep .lc-next-step-card__actions:has(.btn-full-width){flex:1 1 100%;margin-left:0}:host ::ng-deep .lc-next-step-card__actions:has(.btn-full-width)>*,:host ::ng-deep .lc-next-step-card__actions:has(.btn-full-width)>.lc-next-step-card__actions-slot>*{flex:1 1 auto;min-width:0}:host ::ng-deep .lc-next-step-card__actions:has(.btn-full-width)>lc-button>.btn,:host ::ng-deep .lc-next-step-card__actions:has(.btn-full-width)>.lc-next-step-card__actions-slot>lc-button>.btn{width:100%}.lc-next-step-card--actions-stacked .lc-next-step-card__actions{flex:1 1 100%;flex-direction:column;flex-wrap:nowrap;align-items:stretch;gap:.5rem;margin-left:0}:host ::ng-deep .lc-next-step-card--actions-stacked .lc-next-step-card__actions>*,:host ::ng-deep .lc-next-step-card--actions-stacked .lc-next-step-card__actions>.lc-next-step-card__actions-slot>*{flex:1 1 auto;min-width:0}:host ::ng-deep .lc-next-step-card--actions-stacked .lc-next-step-card__actions>lc-button>.btn,:host ::ng-deep .lc-next-step-card--actions-stacked .lc-next-step-card__actions>.lc-next-step-card__actions-slot>lc-button>.btn{width:100%}.lc-next-step-card--soft{--lc-nsc-bubble: var(--color-bubble, var(--color-surface));--lc-nsc-ring: var(--color-bubble-ring, var(--color-border-strong));--lc-nsc-ink: var(--color-bubble-icon, var(--color-link, var(--color-primary)));--lc-nsc-fill: var(--color-next-step-soft-neutral, var(--color-surface-muted));align-items:center;gap:1.25rem;padding:1.5rem 2rem;background:var(--lc-nsc-fill);border:0;border-radius:1.5rem;box-shadow:none}.lc-next-step-card--soft.lc-next-step-card--primary{--lc-nsc-fill: var(--color-next-step-soft-primary, var(--color-primary-subtle))}.lc-next-step-card--soft.lc-next-step-card--success{--lc-nsc-fill: var(--color-next-step-soft-success, var(--color-success-subtle));--lc-nsc-ink: var(--color-on-success-subtle);--lc-nsc-ring: color-mix(in srgb, var(--color-success) 45%, var(--lc-nsc-bubble))}.lc-next-step-card--soft.lc-next-step-card--warning{--lc-nsc-fill: var(--color-next-step-soft-warning, var(--color-warning-subtle));--lc-nsc-ink: var(--color-on-warning-subtle);--lc-nsc-ring: color-mix(in srgb, var(--color-warning) 45%, var(--lc-nsc-bubble))}.lc-next-step-card--soft.lc-next-step-card--info{--lc-nsc-fill: var(--color-info-subtle);--lc-nsc-ink: var(--color-on-info-subtle);--lc-nsc-ring: color-mix(in srgb, var(--color-info) 45%, var(--lc-nsc-bubble))}.lc-next-step-card--soft .lc-next-step-card__icon{width:3rem;height:3rem;background:var(--lc-nsc-bubble);box-shadow:0 0 0 1px var(--lc-nsc-ring);color:var(--lc-nsc-ink)}.lc-next-step-card--soft .lc-next-step-card__title{font-size:1.25rem;font-weight:var(--font-weight-bold, 700);line-height:1.2;letter-spacing:-.025em}.lc-next-step-card--soft .lc-next-step-card__message,.lc-next-step-card--soft .lc-next-step-card__custom-message{margin:0;font-size:var(--font-size-base, 1rem);line-height:1.5}.lc-next-step-card--soft .lc-next-step-card__content{margin-top:0}.lc-next-step-card--soft .lc-next-step-card__meta{gap:.625rem;margin-top:0;padding-top:0;border-top:0;font-size:var(--font-size-sm, .875rem);line-height:1.5}.lc-next-step-card--soft .lc-next-step-card__actions{gap:.75rem}.lc-next-step-card--soft.lc-next-step-card--actions-stacked .lc-next-step-card__actions{gap:.5rem}@container lc-next-step-card (width < 30rem){.lc-next-step-card{display:flex;flex-wrap:wrap;align-items:center;column-gap:var(--lc-nsc-narrow-icon-gap, var(--lc-density-gap-md, 1rem));row-gap:var(--lc-nsc-narrow-row-gap, var(--lc-density-gap-sm, .5rem));padding:var(--lc-density-padding-md, var(--spacing-4, 1rem))}.lc-next-step-card__body{display:contents}.lc-next-step-card__title{flex:1 1 0%;max-width:100%}.lc-next-step-card__message,.lc-next-step-card__custom-message,.lc-next-step-card__content,.lc-next-step-card__blockers,.lc-next-step-card__meta,.lc-next-step-card__actions{flex:1 1 100%;min-width:0;margin-top:0}.lc-next-step-card__message{margin:0}.lc-next-step-card__actions{margin-left:0;padding-top:var(--lc-nsc-narrow-actions-offset, var(--lc-density-gap-sm, .5rem));--lc-btn-overflow-wrap: anywhere}:host ::ng-deep .lc-next-step-card__actions>*,:host ::ng-deep .lc-next-step-card__actions>.lc-next-step-card__actions-slot>*{flex:1 1 auto;min-width:0}:host ::ng-deep .lc-next-step-card__actions>lc-button>.btn,:host ::ng-deep .lc-next-step-card__actions>.lc-next-step-card__actions-slot>lc-button>.btn{width:100%}.lc-next-step-card--soft{--lc-nsc-narrow-icon-gap: .875rem;--lc-nsc-narrow-row-gap: .875rem;--lc-nsc-narrow-actions-offset: .25rem;padding:1.5rem}}@container lc-next-step-card (width >= 30rem){.lc-next-step-card--soft .lc-next-step-card__body{display:flex;flex-direction:column;gap:.5rem}@media(min-width:64rem){.lc-next-step-card--soft{gap:1.75rem;padding:2rem 2.25rem;border-radius:1.75rem}.lc-next-step-card--soft .lc-next-step-card__icon{width:3.5rem;height:3.5rem}.lc-next-step-card--soft .lc-next-step-card__title{font-size:1.5rem}.lc-next-step-card--soft .lc-next-step-card__message,.lc-next-step-card--soft .lc-next-step-card__custom-message{font-size:1.0625rem}.lc-next-step-card--soft .lc-next-step-card__meta{font-size:var(--font-size-base, 1rem)}}@media(min-width:90rem){.lc-next-step-card--soft{padding:2.25rem 2.5rem}.lc-next-step-card--soft .lc-next-step-card__icon{width:3.75rem;height:3.75rem}.lc-next-step-card--soft .lc-next-step-card__title{font-size:1.75rem}.lc-next-step-card--soft .lc-next-step-card__message,.lc-next-step-card--soft .lc-next-step-card__custom-message{font-size:var(--font-size-lg, 1.125rem)}}}\n"],
|
|
203
214
|
dependencies: [{
|
|
204
215
|
kind: "component",
|
|
@@ -206,6 +217,7 @@ var NextStepCardComponent = class NextStepCardComponent {
|
|
|
206
217
|
selector: "lc-button",
|
|
207
218
|
inputs: [
|
|
208
219
|
"variant",
|
|
220
|
+
"tone",
|
|
209
221
|
"size",
|
|
210
222
|
"disabled",
|
|
211
223
|
"loading",
|
|
@@ -262,7 +274,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
262
274
|
ICON_EXTERNAL_LINK
|
|
263
275
|
])],
|
|
264
276
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
265
|
-
template: "<div [class]=\"cardClasses()\" role=\"region\" [attr.aria-label]=\"cardTitle()\">\n <div class=\"lc-next-step-card__icon\" aria-hidden=\"true\">\n <lc-icon [name]=\"icon()\" size=\"md\" [decorative]=\"true\" />\n </div>\n\n <div class=\"lc-next-step-card__body\">\n @switch (titleTag()) {\n @case ('h2') {\n <h2 class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </h2>\n }\n @case ('h3') {\n <h3 class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </h3>\n }\n @default {\n <div class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </div>\n }\n }\n @if (message()) {\n <p class=\"lc-next-step-card__message\">{{ message() }}</p>\n }\n <div class=\"lc-next-step-card__custom-message\">\n <ng-content />\n </div>\n <!-- Form-safe body: no inherited message text styles. -->\n <div class=\"lc-next-step-card__content\">\n <ng-content select=\"[slot='body']\" />\n </div>\n <div class=\"lc-next-step-card__blockers\">\n <ng-content select=\"[slot='blockers']\" />\n </div>\n <div class=\"lc-next-step-card__meta\">\n <ng-content select=\"[slot='meta']\" />\n </div>\n </div>\n\n <div class=\"lc-next-step-card__actions\" [class.lc-next-step-card__actions--empty]=\"!hasActions()\">\n <div #actionsSlot class=\"lc-next-step-card__actions-slot\">\n <ng-content select=\"[slot='actions']\" />\n </div>\n @if (!hasProjectedActions()) {\n @if (secondaryLabel()) {\n <lc-button variant=\"ghost\" [size]=\"actionSize()\" (clicked)=\"secondaryClick.emit()\">\n {{ secondaryLabel() }}\n <lc-icon slot=\"icon-after\" name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </lc-button>\n }\n @if (showLink()) {\n <a\n class=\"btn btn-secondary btn-{{ actionSize() }} lc-next-step-card__link\"\n [href]=\"linkHref()\"\n [attr.target]=\"linkTarget()\"\n [attr.rel]=\"linkRel()\"\n >\n <lc-icon name=\"external-link\" size=\"sm\" [decorative]=\"true\" />\n {{ linkLabel() }}\n </a>\n } @else if (primaryLabel()) {\n <lc-button\n variant=\"primary\"\n [size]=\"actionSize()\"\n [loading]=\"primaryLoading()\"\n [disabled]=\"primaryDisabled()\"\n [disabledReason]=\"primaryDisabledReason()\"\n (clicked)=\"primaryClick.emit()\"\n >\n @if (primaryIcon()) {\n <lc-icon slot=\"icon-before\" [name]=\"primaryIcon()!\" size=\"sm\" [decorative]=\"true\" />\n }\n {{ primaryLabel() }}\n </lc-button>\n }\n }\n </div>\n</div>\n",
|
|
277
|
+
template: "<div [class]=\"cardClasses()\" role=\"region\" [attr.aria-label]=\"cardTitle()\">\n <div class=\"lc-next-step-card__icon\" aria-hidden=\"true\">\n <lc-icon [name]=\"icon()\" size=\"md\" [decorative]=\"true\" />\n </div>\n\n <div class=\"lc-next-step-card__body\">\n @switch (titleTag()) {\n @case ('h2') {\n <h2 class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </h2>\n }\n @case ('h3') {\n <h3 class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </h3>\n }\n @default {\n <div class=\"lc-next-step-card__title\" [attr.aria-live]=\"announce() ? 'polite' : null\">\n {{ cardTitle() }}\n </div>\n }\n }\n @if (message()) {\n <p class=\"lc-next-step-card__message\">{{ message() }}</p>\n }\n <div class=\"lc-next-step-card__custom-message\">\n <ng-content />\n </div>\n <!-- Form-safe body: no inherited message text styles. -->\n <div class=\"lc-next-step-card__content\">\n <ng-content select=\"[slot='body']\" />\n </div>\n <div class=\"lc-next-step-card__blockers\">\n <ng-content select=\"[slot='blockers']\" />\n </div>\n <div class=\"lc-next-step-card__meta\">\n <ng-content select=\"[slot='meta']\" />\n </div>\n </div>\n\n <div class=\"lc-next-step-card__actions\" [class.lc-next-step-card__actions--empty]=\"!hasActions()\">\n <div #actionsSlot class=\"lc-next-step-card__actions-slot\">\n <ng-content select=\"[slot='actions']\" />\n </div>\n @if (!hasProjectedActions() && actionsStyle() === 'equal') {\n <!-- Two answers of the same weight (3.16, BA-5): the primary first, both outline in the primary tone. -->\n @if (showLink()) {\n <a\n class=\"btn btn-secondary btn-{{ actionSize() }} lc-next-step-card__link\"\n [href]=\"linkHref()\"\n [attr.target]=\"linkTarget()\"\n [attr.rel]=\"linkRel()\"\n >\n <lc-icon name=\"external-link\" size=\"sm\" [decorative]=\"true\" />\n {{ linkLabel() }}\n </a>\n } @else if (primaryLabel()) {\n <lc-button\n variant=\"outline\"\n tone=\"primary\"\n [size]=\"actionSize()\"\n [loading]=\"primaryLoading()\"\n [disabled]=\"primaryDisabled()\"\n [disabledReason]=\"primaryDisabledReason()\"\n (clicked)=\"primaryClick.emit()\"\n >\n @if (primaryIcon()) {\n <lc-icon slot=\"icon-before\" [name]=\"primaryIcon()!\" size=\"sm\" [decorative]=\"true\" />\n }\n {{ primaryLabel() }}\n </lc-button>\n }\n @if (secondaryLabel()) {\n <lc-button variant=\"outline\" tone=\"primary\" [size]=\"actionSize()\" (clicked)=\"secondaryClick.emit()\">\n {{ secondaryLabel() }}\n </lc-button>\n }\n } @else if (!hasProjectedActions()) {\n @if (secondaryLabel()) {\n <lc-button variant=\"ghost\" [size]=\"actionSize()\" (clicked)=\"secondaryClick.emit()\">\n {{ secondaryLabel() }}\n <lc-icon slot=\"icon-after\" name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </lc-button>\n }\n @if (showLink()) {\n <a\n class=\"btn btn-secondary btn-{{ actionSize() }} lc-next-step-card__link\"\n [href]=\"linkHref()\"\n [attr.target]=\"linkTarget()\"\n [attr.rel]=\"linkRel()\"\n >\n <lc-icon name=\"external-link\" size=\"sm\" [decorative]=\"true\" />\n {{ linkLabel() }}\n </a>\n } @else if (primaryLabel()) {\n <lc-button\n variant=\"primary\"\n [size]=\"actionSize()\"\n [loading]=\"primaryLoading()\"\n [disabled]=\"primaryDisabled()\"\n [disabledReason]=\"primaryDisabledReason()\"\n (clicked)=\"primaryClick.emit()\"\n >\n @if (primaryIcon()) {\n <lc-icon slot=\"icon-before\" [name]=\"primaryIcon()!\" size=\"sm\" [decorative]=\"true\" />\n }\n {{ primaryLabel() }}\n </lc-button>\n }\n }\n </div>\n</div>\n",
|
|
266
278
|
styles: [":host{display:block;inline-size:100%;container:lc-next-step-card/inline-size}.lc-next-step-card{display:flex;align-items:flex-start;flex-wrap:wrap;gap:var(--lc-density-gap-md, var(--spacing-4, 1rem));padding:var(--lc-density-padding-md, var(--spacing-4, 1rem)) var(--lc-density-padding-lg, var(--spacing-6, 1.5rem));background:var(--color-surface);border:1px solid var(--color-border);border-left:4px solid var(--lc-nsc-rail);border-radius:var(--border-radius-lg, .75rem)}.lc-next-step-card--neutral{--lc-nsc-rail: var(--color-border);--lc-nsc-tint: var(--color-surface-hover);--lc-nsc-ink: var(--color-text-secondary)}.lc-next-step-card--primary{--lc-nsc-rail: var(--color-primary);--lc-nsc-tint: var(--color-primary-subtle);--lc-nsc-ink: var(--color-on-primary-subtle)}.lc-next-step-card--success{--lc-nsc-rail: var(--color-success);--lc-nsc-tint: var(--color-success-subtle);--lc-nsc-ink: var(--color-on-success-subtle)}.lc-next-step-card--warning{--lc-nsc-rail: var(--color-warning);--lc-nsc-tint: var(--color-warning-subtle);--lc-nsc-ink: var(--color-on-warning-subtle)}.lc-next-step-card--info{--lc-nsc-rail: var(--color-info);--lc-nsc-tint: var(--color-info-subtle);--lc-nsc-ink: var(--color-on-info-subtle)}.lc-next-step-card__icon{flex:none;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border-radius:999px;background:var(--lc-nsc-tint);color:var(--lc-nsc-ink)}.lc-next-step-card__body{flex:1 1 16rem;min-width:0}.lc-next-step-card__title{margin:0;font-family:inherit;font-size:var(--typography-font-size-base, 1rem);font-weight:var(--typography-font-weight-semibold, 600);line-height:var(--line-height-tight, 1.25);color:var(--color-text-primary);letter-spacing:-.01em;overflow-wrap:break-word}.lc-next-step-card__message{margin:.2rem 0 0;font-size:var(--typography-font-size-sm, .875rem);line-height:1.55;color:var(--color-text-secondary)}.lc-next-step-card__custom-message{font-size:var(--typography-font-size-sm, .875rem);line-height:1.55;color:var(--color-text-secondary)}.lc-next-step-card__custom-message:empty{display:none}:host ::ng-deep .lc-next-step-card__custom-message>p{margin:.2rem 0 0}.lc-next-step-card__content{margin-top:var(--lc-density-gap-sm, .5rem);min-width:0}.lc-next-step-card__content:empty{display:none}.lc-next-step-card__blockers{display:flex;flex-direction:column;gap:.25rem;margin-top:var(--lc-density-gap-sm, .5rem);padding-top:var(--lc-density-gap-sm, .5rem);border-top:1px solid var(--color-border-subtle, var(--color-border));font-size:var(--typography-font-size-sm, .875rem);color:var(--color-text-secondary)}.lc-next-step-card__blockers:empty{display:none}:host ::ng-deep .lc-next-step-card__blockers>*{display:flex;align-items:baseline;gap:.5rem;margin:0}:host ::ng-deep .lc-next-step-card__blockers>*:before{content:\"\";flex:none;width:7px;height:7px;border-radius:999px;background:var(--lc-nsc-rail);transform:translateY(-1px)}.lc-next-step-card__meta{display:flex;align-items:center;gap:.5rem;margin-top:var(--lc-density-gap-sm, .5rem);padding-top:var(--lc-density-gap-sm, .5rem);border-top:1px solid var(--color-border-subtle, var(--color-border));font-size:var(--typography-font-size-xs, .8125rem);color:var(--color-text-tertiary)}.lc-next-step-card__meta:empty{display:none}.lc-next-step-card__actions{display:flex;align-items:center;flex-wrap:wrap;gap:var(--lc-density-gap-sm, .5rem);margin-left:auto}.lc-next-step-card__actions--empty{display:none}.lc-next-step-card__actions-slot{display:contents}.lc-next-step-card__link{display:inline-flex;align-items:center;gap:.375rem;text-decoration:none}:host ::ng-deep .lc-next-step-card__actions:has(.btn-full-width){flex:1 1 100%;margin-left:0}:host ::ng-deep .lc-next-step-card__actions:has(.btn-full-width)>*,:host ::ng-deep .lc-next-step-card__actions:has(.btn-full-width)>.lc-next-step-card__actions-slot>*{flex:1 1 auto;min-width:0}:host ::ng-deep .lc-next-step-card__actions:has(.btn-full-width)>lc-button>.btn,:host ::ng-deep .lc-next-step-card__actions:has(.btn-full-width)>.lc-next-step-card__actions-slot>lc-button>.btn{width:100%}.lc-next-step-card--actions-stacked .lc-next-step-card__actions{flex:1 1 100%;flex-direction:column;flex-wrap:nowrap;align-items:stretch;gap:.5rem;margin-left:0}:host ::ng-deep .lc-next-step-card--actions-stacked .lc-next-step-card__actions>*,:host ::ng-deep .lc-next-step-card--actions-stacked .lc-next-step-card__actions>.lc-next-step-card__actions-slot>*{flex:1 1 auto;min-width:0}:host ::ng-deep .lc-next-step-card--actions-stacked .lc-next-step-card__actions>lc-button>.btn,:host ::ng-deep .lc-next-step-card--actions-stacked .lc-next-step-card__actions>.lc-next-step-card__actions-slot>lc-button>.btn{width:100%}.lc-next-step-card--soft{--lc-nsc-bubble: var(--color-bubble, var(--color-surface));--lc-nsc-ring: var(--color-bubble-ring, var(--color-border-strong));--lc-nsc-ink: var(--color-bubble-icon, var(--color-link, var(--color-primary)));--lc-nsc-fill: var(--color-next-step-soft-neutral, var(--color-surface-muted));align-items:center;gap:1.25rem;padding:1.5rem 2rem;background:var(--lc-nsc-fill);border:0;border-radius:1.5rem;box-shadow:none}.lc-next-step-card--soft.lc-next-step-card--primary{--lc-nsc-fill: var(--color-next-step-soft-primary, var(--color-primary-subtle))}.lc-next-step-card--soft.lc-next-step-card--success{--lc-nsc-fill: var(--color-next-step-soft-success, var(--color-success-subtle));--lc-nsc-ink: var(--color-on-success-subtle);--lc-nsc-ring: color-mix(in srgb, var(--color-success) 45%, var(--lc-nsc-bubble))}.lc-next-step-card--soft.lc-next-step-card--warning{--lc-nsc-fill: var(--color-next-step-soft-warning, var(--color-warning-subtle));--lc-nsc-ink: var(--color-on-warning-subtle);--lc-nsc-ring: color-mix(in srgb, var(--color-warning) 45%, var(--lc-nsc-bubble))}.lc-next-step-card--soft.lc-next-step-card--info{--lc-nsc-fill: var(--color-info-subtle);--lc-nsc-ink: var(--color-on-info-subtle);--lc-nsc-ring: color-mix(in srgb, var(--color-info) 45%, var(--lc-nsc-bubble))}.lc-next-step-card--soft .lc-next-step-card__icon{width:3rem;height:3rem;background:var(--lc-nsc-bubble);box-shadow:0 0 0 1px var(--lc-nsc-ring);color:var(--lc-nsc-ink)}.lc-next-step-card--soft .lc-next-step-card__title{font-size:1.25rem;font-weight:var(--font-weight-bold, 700);line-height:1.2;letter-spacing:-.025em}.lc-next-step-card--soft .lc-next-step-card__message,.lc-next-step-card--soft .lc-next-step-card__custom-message{margin:0;font-size:var(--font-size-base, 1rem);line-height:1.5}.lc-next-step-card--soft .lc-next-step-card__content{margin-top:0}.lc-next-step-card--soft .lc-next-step-card__meta{gap:.625rem;margin-top:0;padding-top:0;border-top:0;font-size:var(--font-size-sm, .875rem);line-height:1.5}.lc-next-step-card--soft .lc-next-step-card__actions{gap:.75rem}.lc-next-step-card--soft.lc-next-step-card--actions-stacked .lc-next-step-card__actions{gap:.5rem}@container lc-next-step-card (width < 30rem){.lc-next-step-card{display:flex;flex-wrap:wrap;align-items:center;column-gap:var(--lc-nsc-narrow-icon-gap, var(--lc-density-gap-md, 1rem));row-gap:var(--lc-nsc-narrow-row-gap, var(--lc-density-gap-sm, .5rem));padding:var(--lc-density-padding-md, var(--spacing-4, 1rem))}.lc-next-step-card__body{display:contents}.lc-next-step-card__title{flex:1 1 0%;max-width:100%}.lc-next-step-card__message,.lc-next-step-card__custom-message,.lc-next-step-card__content,.lc-next-step-card__blockers,.lc-next-step-card__meta,.lc-next-step-card__actions{flex:1 1 100%;min-width:0;margin-top:0}.lc-next-step-card__message{margin:0}.lc-next-step-card__actions{margin-left:0;padding-top:var(--lc-nsc-narrow-actions-offset, var(--lc-density-gap-sm, .5rem));--lc-btn-overflow-wrap: anywhere}:host ::ng-deep .lc-next-step-card__actions>*,:host ::ng-deep .lc-next-step-card__actions>.lc-next-step-card__actions-slot>*{flex:1 1 auto;min-width:0}:host ::ng-deep .lc-next-step-card__actions>lc-button>.btn,:host ::ng-deep .lc-next-step-card__actions>.lc-next-step-card__actions-slot>lc-button>.btn{width:100%}.lc-next-step-card--soft{--lc-nsc-narrow-icon-gap: .875rem;--lc-nsc-narrow-row-gap: .875rem;--lc-nsc-narrow-actions-offset: .25rem;padding:1.5rem}}@container lc-next-step-card (width >= 30rem){.lc-next-step-card--soft .lc-next-step-card__body{display:flex;flex-direction:column;gap:.5rem}@media(min-width:64rem){.lc-next-step-card--soft{gap:1.75rem;padding:2rem 2.25rem;border-radius:1.75rem}.lc-next-step-card--soft .lc-next-step-card__icon{width:3.5rem;height:3.5rem}.lc-next-step-card--soft .lc-next-step-card__title{font-size:1.5rem}.lc-next-step-card--soft .lc-next-step-card__message,.lc-next-step-card--soft .lc-next-step-card__custom-message{font-size:1.0625rem}.lc-next-step-card--soft .lc-next-step-card__meta{font-size:var(--font-size-base, 1rem)}}@media(min-width:90rem){.lc-next-step-card--soft{padding:2.25rem 2.5rem}.lc-next-step-card--soft .lc-next-step-card__icon{width:3.75rem;height:3.75rem}.lc-next-step-card--soft .lc-next-step-card__title{font-size:1.75rem}.lc-next-step-card--soft .lc-next-step-card__message,.lc-next-step-card--soft .lc-next-step-card__custom-message{font-size:var(--font-size-lg, 1.125rem)}}}\n"]
|
|
267
279
|
}]
|
|
268
280
|
}],
|
|
@@ -324,6 +336,14 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
324
336
|
required: false
|
|
325
337
|
}]
|
|
326
338
|
}],
|
|
339
|
+
actionsStyle: [{
|
|
340
|
+
type: i0.Input,
|
|
341
|
+
args: [{
|
|
342
|
+
isSignal: true,
|
|
343
|
+
alias: "actionsStyle",
|
|
344
|
+
required: false
|
|
345
|
+
}]
|
|
346
|
+
}],
|
|
327
347
|
message: [{
|
|
328
348
|
type: i0.Input,
|
|
329
349
|
args: [{
|