@lifecorner/angular-ui-kit 3.7.0 → 3.9.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.
Files changed (69) hide show
  1. package/README.md +1 -0
  2. package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs +4 -4
  3. package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs.map +1 -1
  4. package/fesm2022/lifecorner-angular-ui-kit-button.mjs +39 -6
  5. package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -1
  6. package/fesm2022/lifecorner-angular-ui-kit-character-svg.mjs +91 -0
  7. package/fesm2022/lifecorner-angular-ui-kit-character-svg.mjs.map +1 -0
  8. package/fesm2022/lifecorner-angular-ui-kit-character.mjs +138 -0
  9. package/fesm2022/lifecorner-angular-ui-kit-character.mjs.map +1 -0
  10. package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs +2 -1
  11. package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs.map +1 -1
  12. package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs +2 -1
  13. package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs.map +1 -1
  14. package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs +2 -1
  15. package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs.map +1 -1
  16. package/fesm2022/lifecorner-angular-ui-kit-header.mjs +2 -1
  17. package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
  18. package/fesm2022/lifecorner-angular-ui-kit-list.mjs +2 -1
  19. package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
  20. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +2 -1
  21. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -1
  22. package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs +2 -2
  23. package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs.map +1 -1
  24. package/fesm2022/lifecorner-angular-ui-kit-skeleton.mjs +2 -2
  25. package/fesm2022/lifecorner-angular-ui-kit-skeleton.mjs.map +1 -1
  26. package/fesm2022/lifecorner-angular-ui-kit-table.mjs +2 -1
  27. package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
  28. package/fesm2022/lifecorner-angular-ui-kit.mjs +2 -0
  29. package/package.json +12 -1
  30. package/src/assets/README.md +4 -0
  31. package/src/assets/character/all-done-dark.svg +1 -0
  32. package/src/assets/character/all-done-light.svg +1 -0
  33. package/src/assets/character/calm-dark.svg +1 -0
  34. package/src/assets/character/calm-light.svg +1 -0
  35. package/src/assets/character/comforts-dark.svg +1 -0
  36. package/src/assets/character/comforts-light.svg +1 -0
  37. package/src/assets/character/connection-paused-dark.svg +1 -0
  38. package/src/assets/character/connection-paused-light.svg +1 -0
  39. package/src/assets/character/connects-dark.svg +1 -0
  40. package/src/assets/character/connects-light.svg +1 -0
  41. package/src/assets/character/discovered-dark.svg +1 -0
  42. package/src/assets/character/discovered-light.svg +1 -0
  43. package/src/assets/character/happy-dark.svg +1 -0
  44. package/src/assets/character/happy-light.svg +1 -0
  45. package/src/assets/character/hello-dark.svg +1 -0
  46. package/src/assets/character/hello-light.svg +1 -0
  47. package/src/assets/character/in-his-corner-dark.svg +1 -0
  48. package/src/assets/character/in-his-corner-light.svg +1 -0
  49. package/src/assets/character/resting-dark.svg +1 -0
  50. package/src/assets/character/resting-light.svg +1 -0
  51. package/src/assets/character/see-you-dark.svg +1 -0
  52. package/src/assets/character/see-you-light.svg +1 -0
  53. package/src/assets/character/shows-the-way-dark.svg +1 -0
  54. package/src/assets/character/shows-the-way-light.svg +1 -0
  55. package/src/assets/character/thinking-dark.svg +1 -0
  56. package/src/assets/character/thinking-light.svg +1 -0
  57. package/src/assets/character/welcomes-member-dark.svg +1 -0
  58. package/src/assets/character/welcomes-member-light.svg +1 -0
  59. package/src/styles/_horizon.scss +95 -9
  60. package/src/styles/horizon.figure.spec.ts +79 -0
  61. package/src/styles/horizon.shell.spec.ts +67 -0
  62. package/src/styles/horizon.spec.ts +6 -4
  63. package/types/lifecorner-angular-ui-kit-app-shell.d.ts +15 -4
  64. package/types/lifecorner-angular-ui-kit-button.d.ts +30 -0
  65. package/types/lifecorner-angular-ui-kit-character-svg.d.ts +44 -0
  66. package/types/lifecorner-angular-ui-kit-character.d.ts +104 -0
  67. package/types/lifecorner-angular-ui-kit-page-header.d.ts +6 -1
  68. package/types/lifecorner-angular-ui-kit-skeleton.d.ts +7 -1
  69. package/types/lifecorner-angular-ui-kit.d.ts +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"lifecorner-angular-ui-kit-choice-prompt.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/choice-prompt/choice-prompt.component.ts","../../../../libs/angular-ui-kit/src/lib/choice-prompt/choice-prompt.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n computed,\n effect,\n input,\n isDevMode,\n output,\n signal,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\n\n/** One selectable answer of an `lc-choice-prompt`. */\nexport interface ChoicePromptOption {\n id: string;\n label: string;\n /** Optional second line inside the option button. */\n description?: string;\n /** Marks the recommended answer: badge + first position. */\n recommended?: boolean;\n}\n\n/** A subordinate exit of the prompt (e.g. \"Selbst gelöst\" / \"Ignorieren\"). */\nexport interface ChoicePromptSecondaryAction {\n id: string;\n label: string;\n tooltip?: string;\n}\n\n/** Payload of the `(decided)` output — exactly one of the two fields is set. */\nexport interface ChoicePromptDecision {\n optionId?: string;\n customText?: string;\n}\n\nexport type ChoicePromptSize = 'sm' | 'md';\n\n/**\n * Inline decision prompt: predefined answer options (with a marked\n * recommendation) plus an optional free-text answer — no modal, directly in\n * the flow.\n *\n * Features:\n * - Options as buttons; `recommended` carries the badge and is sorted first\n * - Free-text lane behind a toggle link (`allowCustom`), submit via button or\n * Enter; empty text is never submittable\n * - `busy` after a decision: the clicked option shows a spinner, everything\n * else is disabled — prevents double submits. Focus stays on the triggering\n * element when `busy` ends.\n * - `disabled` requires a `disabledReason` (tooltip); missing reason logs a\n * dev warning\n * - Subordinate exits via `secondaryActions`\n * - `role=\"group\"` labelled via `promptLabel` (the question itself lives in\n * the surrounding layout)\n *\n * @example\n * ```html\n * <lc-choice-prompt\n * promptLabel=\"Wie soll der Konflikt gelöst werden?\"\n * [options]=\"[\n * { id: 'a', label: 'Variante A übernehmen', recommended: true },\n * { id: 'b', label: 'Beide behalten' },\n * ]\"\n * [busy]=\"saving()\"\n * (decided)=\"resolve($event)\"\n * />\n * ```\n */\n@Component({\n selector: 'lc-choice-prompt',\n standalone: true,\n imports: [ButtonComponent],\n templateUrl: './choice-prompt.component.html',\n styleUrls: ['./choice-prompt.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ChoicePromptComponent {\n /** Answer options. The recommended option is sorted to the front. */\n options = input.required<ChoicePromptOption[]>();\n\n /**\n * Whether the free-text lane is offered.\n * @default true\n */\n allowCustom = input<boolean>(true);\n\n /** Label of the link that opens the free-text lane. */\n customToggleLabel = input<string>('Eigene Antwort …');\n\n /** Placeholder of the free-text input. */\n customPlaceholder = input<string>('');\n\n /** Label of the free-text submit button. */\n submitLabel = input<string>('Übernehmen');\n\n /**\n * Set after a decision while it is being processed: the chosen element shows\n * a spinner, every other interaction is blocked (including Enter in the\n * free-text input).\n * @default false\n */\n busy = input<boolean>(false);\n\n /** Disables the whole prompt. Requires `disabledReason`. */\n disabled = input<boolean>(false);\n\n /** Why the prompt is disabled — shown as tooltip. */\n disabledReason = input<string>('');\n\n /** Subordinate exits, rendered as quiet text buttons after the options. */\n secondaryActions = input<ChoicePromptSecondaryAction[]>([]);\n\n /**\n * `sm` for dense lists (inbox rows).\n * @default 'md'\n */\n size = input<ChoicePromptSize>('md');\n\n /** Accessible name of the group — the question shown in the surroundings. */\n promptLabel = input<string>('');\n\n /** Label of the recommendation badge. */\n recommendedLabel = input<string>('Empfehlung');\n\n /** Fires immediately on option click, or on free-text submit. */\n decided = output<ChoicePromptDecision>();\n\n /** Fires with the id of a clicked secondary action. */\n secondaryAction = output<string>();\n\n /** Whether the free-text lane is open. */\n protected customOpen = signal(false);\n\n /** Current free-text value. */\n protected customText = signal('');\n\n /** Option that triggered the pending decision (spinner + focus anchor). */\n protected pendingOptionId = signal<string | null>(null);\n\n /** Whether the pending decision came from the free-text lane. */\n protected pendingCustom = signal(false);\n\n private customInput = viewChild<ElementRef<HTMLInputElement>>('customInput');\n private optionButtons = viewChildren<ElementRef<HTMLButtonElement>>('optionButton');\n private submitButton = viewChild<ButtonComponent>('submitButton');\n\n /** Options with the recommended one(s) first, original order otherwise. */\n protected sortedOptions = computed(() => {\n const options = this.options();\n return [...options.filter((o) => o.recommended), ...options.filter((o) => !o.recommended)];\n });\n\n /** No interaction while busy or disabled. */\n protected locked = computed(() => this.busy() || this.disabled());\n\n protected canSubmitCustom = computed(\n () => this.customText().trim().length > 0 && !this.locked(),\n );\n\n protected disabledTitle = computed(() =>\n this.disabled() && this.disabledReason() ? this.disabledReason() : null,\n );\n\n protected groupClasses = computed(() =>\n ['lc-choice-prompt', `lc-choice-prompt--${this.size()}`].join(' '),\n );\n\n constructor() {\n effect(() => {\n if (isDevMode() && this.disabled() && !this.disabledReason()) {\n console.warn(\n '[lc-choice-prompt] `disabled` is set without a `disabledReason`. ' +\n 'A disabled prompt must explain why (shown as tooltip).',\n );\n }\n });\n\n // When busy ends, focus returns to the element that triggered the\n // decision, then the pending markers reset.\n let wasBusy = false;\n effect(() => {\n const busy = this.busy();\n if (wasBusy && !busy) {\n this.restoreFocus();\n this.pendingOptionId.set(null);\n this.pendingCustom.set(false);\n }\n wasBusy = busy;\n });\n }\n\n protected isPendingOption(id: string): boolean {\n return this.busy() && this.pendingOptionId() === id;\n }\n\n protected chooseOption(option: ChoicePromptOption): void {\n if (this.locked()) return;\n this.pendingOptionId.set(option.id);\n this.pendingCustom.set(false);\n this.decided.emit({ optionId: option.id });\n }\n\n protected openCustom(): void {\n if (this.locked()) return;\n this.customOpen.set(true);\n // Focus the input once it is rendered.\n setTimeout(() => this.customInput()?.nativeElement.focus());\n }\n\n protected onCustomInput(event: Event): void {\n this.customText.set((event.target as HTMLInputElement).value);\n }\n\n protected submitCustom(): void {\n const text = this.customText().trim();\n if (!text || this.locked()) return;\n this.pendingCustom.set(true);\n this.pendingOptionId.set(null);\n this.decided.emit({ customText: text });\n }\n\n protected triggerSecondary(action: ChoicePromptSecondaryAction): void {\n if (this.locked()) return;\n this.secondaryAction.emit(action.id);\n }\n\n private restoreFocus(): void {\n const pendingId = this.pendingOptionId();\n if (pendingId !== null) {\n const button = this.optionButtons().find(\n (ref) => ref.nativeElement.dataset['optionId'] === pendingId,\n );\n button?.nativeElement.focus();\n } else if (this.pendingCustom()) {\n this.submitButton()?.focus();\n }\n }\n}\n","<div\n [class]=\"groupClasses()\"\n role=\"group\"\n [attr.aria-label]=\"promptLabel() || null\"\n [attr.aria-busy]=\"busy() ? 'true' : null\"\n>\n <div class=\"lc-choice-prompt__options\">\n @for (option of sortedOptions(); track option.id) {\n <!-- The busy (clicked) option keeps focus: aria-disabled instead of the\n native attribute, the click handler is guarded via locked(). -->\n <button\n #optionButton\n type=\"button\"\n class=\"lc-choice-prompt__option\"\n [class.lc-choice-prompt__option--recommended]=\"option.recommended\"\n [class.lc-choice-prompt__option--busy]=\"isPendingOption(option.id)\"\n [attr.data-option-id]=\"option.id\"\n [disabled]=\"locked() && !isPendingOption(option.id)\"\n [attr.aria-disabled]=\"locked() ? 'true' : null\"\n [attr.title]=\"disabledTitle()\"\n (click)=\"chooseOption(option)\"\n >\n <span class=\"lc-choice-prompt__option-main\">\n @if (isPendingOption(option.id)) {\n <span class=\"lc-choice-prompt__spinner\" aria-hidden=\"true\"></span>\n }\n <span class=\"lc-choice-prompt__option-label\">{{ option.label }}</span>\n @if (option.recommended) {\n <span class=\"lc-choice-prompt__badge\">{{ recommendedLabel() }}</span>\n }\n </span>\n @if (option.description) {\n <span class=\"lc-choice-prompt__option-description\">{{ option.description }}</span>\n }\n </button>\n }\n\n @if (allowCustom() && !customOpen()) {\n <button\n type=\"button\"\n class=\"lc-choice-prompt__custom-toggle\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle()\"\n (click)=\"openCustom()\"\n >\n {{ customToggleLabel() }}\n </button>\n }\n\n @for (action of secondaryActions(); track action.id) {\n <button\n type=\"button\"\n class=\"lc-choice-prompt__secondary\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle() ?? action.tooltip ?? null\"\n (click)=\"triggerSecondary(action)\"\n >\n {{ action.label }}\n </button>\n }\n </div>\n\n @if (allowCustom() && customOpen()) {\n <div class=\"lc-choice-prompt__custom\">\n <input\n #customInput\n type=\"text\"\n class=\"lc-choice-prompt__input\"\n [placeholder]=\"customPlaceholder()\"\n [value]=\"customText()\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle()\"\n [attr.aria-label]=\"customToggleLabel()\"\n (input)=\"onCustomInput($event)\"\n (keydown.enter)=\"submitCustom()\"\n />\n <lc-button\n #submitButton\n variant=\"primary\"\n [size]=\"size() === 'sm' ? 'xs' : 'sm'\"\n [loading]=\"busy() && pendingCustom()\"\n [disabled]=\"!canSubmitCustom()\"\n [disabledReason]=\"disabledTitle() ?? ''\"\n (clicked)=\"submitCustom()\"\n >\n {{ submitLabel() }}\n </lc-button>\n </div>\n }\n</div>\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-choice-prompt.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/choice-prompt/choice-prompt.component.ts","../../../../libs/angular-ui-kit/src/lib/choice-prompt/choice-prompt.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n computed,\n effect,\n input,\n isDevMode,\n output,\n signal,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\n\n/** One selectable answer of an `lc-choice-prompt`. */\nexport interface ChoicePromptOption {\n id: string;\n label: string;\n /** Optional second line inside the option button. */\n description?: string;\n /** Marks the recommended answer: badge + first position. */\n recommended?: boolean;\n}\n\n/** A subordinate exit of the prompt (e.g. \"Selbst gelöst\" / \"Ignorieren\"). */\nexport interface ChoicePromptSecondaryAction {\n id: string;\n label: string;\n tooltip?: string;\n}\n\n/** Payload of the `(decided)` output — exactly one of the two fields is set. */\nexport interface ChoicePromptDecision {\n optionId?: string;\n customText?: string;\n}\n\nexport type ChoicePromptSize = 'sm' | 'md';\n\n/**\n * Inline decision prompt: predefined answer options (with a marked\n * recommendation) plus an optional free-text answer — no modal, directly in\n * the flow.\n *\n * Features:\n * - Options as buttons; `recommended` carries the badge and is sorted first\n * - Free-text lane behind a toggle link (`allowCustom`), submit via button or\n * Enter; empty text is never submittable\n * - `busy` after a decision: the clicked option shows a spinner, everything\n * else is disabled — prevents double submits. Focus stays on the triggering\n * element when `busy` ends.\n * - `disabled` requires a `disabledReason` (tooltip); missing reason logs a\n * dev warning\n * - Subordinate exits via `secondaryActions`\n * - `role=\"group\"` labelled via `promptLabel` (the question itself lives in\n * the surrounding layout)\n *\n * @example\n * ```html\n * <lc-choice-prompt\n * promptLabel=\"Wie soll der Konflikt gelöst werden?\"\n * [options]=\"[\n * { id: 'a', label: 'Variante A übernehmen', recommended: true },\n * { id: 'b', label: 'Beide behalten' },\n * ]\"\n * [busy]=\"saving()\"\n * (decided)=\"resolve($event)\"\n * />\n * ```\n */\n@Component({\n selector: 'lc-choice-prompt',\n standalone: true,\n imports: [ButtonComponent],\n templateUrl: './choice-prompt.component.html',\n styleUrls: ['./choice-prompt.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ChoicePromptComponent {\n /** Answer options. The recommended option is sorted to the front. */\n options = input.required<ChoicePromptOption[]>();\n\n /**\n * Whether the free-text lane is offered.\n * @default true\n */\n allowCustom = input<boolean>(true);\n\n /** Label of the link that opens the free-text lane. */\n customToggleLabel = input<string>('Eigene Antwort …');\n\n /** Placeholder of the free-text input. */\n customPlaceholder = input<string>('');\n\n /** Label of the free-text submit button. */\n submitLabel = input<string>('Übernehmen');\n\n /**\n * Set after a decision while it is being processed: the chosen element shows\n * a spinner, every other interaction is blocked (including Enter in the\n * free-text input).\n * @default false\n */\n busy = input<boolean>(false);\n\n /** Disables the whole prompt. Requires `disabledReason`. */\n disabled = input<boolean>(false);\n\n /** Why the prompt is disabled — shown as tooltip. */\n disabledReason = input<string>('');\n\n /** Subordinate exits, rendered as quiet text buttons after the options. */\n secondaryActions = input<ChoicePromptSecondaryAction[]>([]);\n\n /**\n * `sm` for dense lists (inbox rows).\n * @default 'md'\n */\n size = input<ChoicePromptSize>('md');\n\n /** Accessible name of the group — the question shown in the surroundings. */\n promptLabel = input<string>('');\n\n /** Label of the recommendation badge. */\n recommendedLabel = input<string>('Empfehlung');\n\n /** Fires immediately on option click, or on free-text submit. */\n decided = output<ChoicePromptDecision>();\n\n /** Fires with the id of a clicked secondary action. */\n secondaryAction = output<string>();\n\n /** Whether the free-text lane is open. */\n protected customOpen = signal(false);\n\n /** Current free-text value. */\n protected customText = signal('');\n\n /** Option that triggered the pending decision (spinner + focus anchor). */\n protected pendingOptionId = signal<string | null>(null);\n\n /** Whether the pending decision came from the free-text lane. */\n protected pendingCustom = signal(false);\n\n private customInput = viewChild<ElementRef<HTMLInputElement>>('customInput');\n private optionButtons = viewChildren<ElementRef<HTMLButtonElement>>('optionButton');\n private submitButton = viewChild<ButtonComponent>('submitButton');\n\n /** Options with the recommended one(s) first, original order otherwise. */\n protected sortedOptions = computed(() => {\n const options = this.options();\n return [...options.filter((o) => o.recommended), ...options.filter((o) => !o.recommended)];\n });\n\n /** No interaction while busy or disabled. */\n protected locked = computed(() => this.busy() || this.disabled());\n\n protected canSubmitCustom = computed(\n () => this.customText().trim().length > 0 && !this.locked(),\n );\n\n protected disabledTitle = computed(() =>\n this.disabled() && this.disabledReason() ? this.disabledReason() : null,\n );\n\n protected groupClasses = computed(() =>\n ['lc-choice-prompt', `lc-choice-prompt--${this.size()}`].join(' '),\n );\n\n constructor() {\n effect(() => {\n if (isDevMode() && this.disabled() && !this.disabledReason()) {\n console.warn(\n '[lc-choice-prompt] `disabled` is set without a `disabledReason`. ' +\n 'A disabled prompt must explain why (shown as tooltip).',\n );\n }\n });\n\n // When busy ends, focus returns to the element that triggered the\n // decision, then the pending markers reset.\n let wasBusy = false;\n effect(() => {\n const busy = this.busy();\n if (wasBusy && !busy) {\n this.restoreFocus();\n this.pendingOptionId.set(null);\n this.pendingCustom.set(false);\n }\n wasBusy = busy;\n });\n }\n\n protected isPendingOption(id: string): boolean {\n return this.busy() && this.pendingOptionId() === id;\n }\n\n protected chooseOption(option: ChoicePromptOption): void {\n if (this.locked()) return;\n this.pendingOptionId.set(option.id);\n this.pendingCustom.set(false);\n this.decided.emit({ optionId: option.id });\n }\n\n protected openCustom(): void {\n if (this.locked()) return;\n this.customOpen.set(true);\n // Focus the input once it is rendered.\n setTimeout(() => this.customInput()?.nativeElement.focus());\n }\n\n protected onCustomInput(event: Event): void {\n this.customText.set((event.target as HTMLInputElement).value);\n }\n\n protected submitCustom(): void {\n const text = this.customText().trim();\n if (!text || this.locked()) return;\n this.pendingCustom.set(true);\n this.pendingOptionId.set(null);\n this.decided.emit({ customText: text });\n }\n\n protected triggerSecondary(action: ChoicePromptSecondaryAction): void {\n if (this.locked()) return;\n this.secondaryAction.emit(action.id);\n }\n\n private restoreFocus(): void {\n const pendingId = this.pendingOptionId();\n if (pendingId !== null) {\n const button = this.optionButtons().find(\n (ref) => ref.nativeElement.dataset['optionId'] === pendingId,\n );\n button?.nativeElement.focus();\n } else if (this.pendingCustom()) {\n this.submitButton()?.focus();\n }\n }\n}\n","<div\n [class]=\"groupClasses()\"\n role=\"group\"\n [attr.aria-label]=\"promptLabel() || null\"\n [attr.aria-busy]=\"busy() ? 'true' : null\"\n>\n <div class=\"lc-choice-prompt__options\">\n @for (option of sortedOptions(); track option.id) {\n <!-- The busy (clicked) option keeps focus: aria-disabled instead of the\n native attribute, the click handler is guarded via locked(). -->\n <button\n #optionButton\n type=\"button\"\n class=\"lc-choice-prompt__option\"\n [class.lc-choice-prompt__option--recommended]=\"option.recommended\"\n [class.lc-choice-prompt__option--busy]=\"isPendingOption(option.id)\"\n [attr.data-option-id]=\"option.id\"\n [disabled]=\"locked() && !isPendingOption(option.id)\"\n [attr.aria-disabled]=\"locked() ? 'true' : null\"\n [attr.title]=\"disabledTitle()\"\n (click)=\"chooseOption(option)\"\n >\n <span class=\"lc-choice-prompt__option-main\">\n @if (isPendingOption(option.id)) {\n <span class=\"lc-choice-prompt__spinner\" aria-hidden=\"true\"></span>\n }\n <span class=\"lc-choice-prompt__option-label\">{{ option.label }}</span>\n @if (option.recommended) {\n <span class=\"lc-choice-prompt__badge\">{{ recommendedLabel() }}</span>\n }\n </span>\n @if (option.description) {\n <span class=\"lc-choice-prompt__option-description\">{{ option.description }}</span>\n }\n </button>\n }\n\n @if (allowCustom() && !customOpen()) {\n <button\n type=\"button\"\n class=\"lc-choice-prompt__custom-toggle\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle()\"\n (click)=\"openCustom()\"\n >\n {{ customToggleLabel() }}\n </button>\n }\n\n @for (action of secondaryActions(); track action.id) {\n <button\n type=\"button\"\n class=\"lc-choice-prompt__secondary\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle() ?? action.tooltip ?? null\"\n (click)=\"triggerSecondary(action)\"\n >\n {{ action.label }}\n </button>\n }\n </div>\n\n @if (allowCustom() && customOpen()) {\n <div class=\"lc-choice-prompt__custom\">\n <input\n #customInput\n type=\"text\"\n class=\"lc-choice-prompt__input\"\n [placeholder]=\"customPlaceholder()\"\n [value]=\"customText()\"\n [disabled]=\"locked()\"\n [attr.title]=\"disabledTitle()\"\n [attr.aria-label]=\"customToggleLabel()\"\n (input)=\"onCustomInput($event)\"\n (keydown.enter)=\"submitCustom()\"\n />\n <lc-button\n #submitButton\n variant=\"primary\"\n [size]=\"size() === 'sm' ? 'xs' : 'sm'\"\n [loading]=\"busy() && pendingCustom()\"\n [disabled]=\"!canSubmitCustom()\"\n [disabledReason]=\"disabledTitle() ?? ''\"\n (clicked)=\"submitCustom()\"\n >\n {{ submitLabel() }}\n </lc-button>\n </div>\n }\n</div>\n"],"mappings":"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"}
@@ -211,7 +211,8 @@ var ConfirmDialogComponent = class ConfirmDialogComponent {
211
211
  "type",
212
212
  "title",
213
213
  "disabledReason",
214
- "inline"
214
+ "inline",
215
+ "flush"
215
216
  ],
216
217
  outputs: [
217
218
  "clicked",
@@ -1 +1 @@
1
- {"version":3,"file":"lifecorner-angular-ui-kit-confirm-dialog.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/confirm-dialog/confirm-dialog.component.ts","../../../../libs/angular-ui-kit/src/lib/confirm-dialog/confirm-dialog.component.html","../../../../libs/angular-ui-kit/src/lib/confirm-dialog/confirm.service.ts"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n input,\n output,\n signal,\n computed,\n effect,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_EXCLAMATION_CIRCLE, ICON_EXCLAMATION_TRIANGLE } from '@lifecorner/angular-ui-kit/icons';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\nimport { InputComponent } from '@lifecorner/angular-ui-kit/input';\nimport { ModalComponent, ModalPlacement } from '@lifecorner/angular-ui-kit/modal';\n\nexport type ConfirmDialogVariant = 'default' | 'destructive' | 'warning';\n\n/** Size of the confirm and cancel buttons (`lg` = 48.5 px, a 44 px target). */\nexport type ConfirmDialogButtonSize = 'sm' | 'md' | 'lg';\n\nexport interface RequireTextConfig {\n prompt: string;\n expected: string;\n}\n\n/**\n * Confirm dialog component for confirming user actions.\n *\n * Builds on `<lc-modal>` to provide a standardized confirmation pattern\n * with optional destructive variant and text-matching confirmation.\n *\n * The dialog is named by its title (`aria-labelledby`); `[slot='preview']`\n * shows what the action affects below the message; `confirmLoading` keeps the\n * dialog open with a busy confirm button while the action runs.\n *\n * @example\n * ```html\n * <lc-confirm-dialog\n * [open]=\"showConfirm()\"\n * variant=\"destructive\"\n * title=\"Delete project?\"\n * message=\"This cannot be undone.\"\n * (confirmed)=\"onDelete()\"\n * (cancelled)=\"showConfirm.set(false)\"\n * />\n * ```\n */\n@Component({\n selector: 'lc-confirm-dialog',\n standalone: true,\n imports: [FormsModule, IconComponent, ButtonComponent, ModalComponent, InputComponent],\n viewProviders: [ɵprovideKitIcons([ICON_EXCLAMATION_TRIANGLE, ICON_EXCLAMATION_CIRCLE])],\n templateUrl: './confirm-dialog.component.html',\n styleUrls: ['./confirm-dialog.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ConfirmDialogComponent {\n private static nextId = 0;\n\n /** Whether the dialog is open */\n readonly open = input<boolean>(false);\n\n /** Dialog variant */\n readonly variant = input<ConfirmDialogVariant>('default');\n\n /** Dialog title */\n readonly title = input.required<string>();\n\n /** Dialog message */\n readonly message = input.required<string>();\n\n /** Confirm button label */\n readonly confirmLabel = input<string>('Confirm');\n\n /** Cancel button label */\n readonly cancelLabel = input<string>('Cancel');\n\n /** Icon name (auto-set by variant if not provided) */\n readonly icon = input<string>();\n\n /** Require text match to enable confirm */\n readonly requireText = input<RequireTextConfig>();\n\n /** Accessible name of the close button in the header. */\n readonly closeAriaLabel = input('Close modal');\n\n /**\n * Shows a spinner on the confirm button and blocks a second confirm while\n * the action runs; the app closes the dialog when it is done.\n * @default false\n */\n readonly confirmLoading = input<boolean>(false);\n\n /**\n * Size of the confirm and cancel buttons: `md` (3.2) or `lg` (48.5 px, the\n * 44 px touch target), or `sm`.\n * @default 'md'\n */\n readonly buttonSize = input<ConfirmDialogButtonSize>('md');\n\n /**\n * Where the dialog sits (passed to `lc-modal`): `center` (3.2), `auto` (a\n * bottom sheet below 640 px) or `sheet`.\n * @default 'center'\n */\n readonly placement = input<ModalPlacement>('center');\n\n /** Id of the title, which names the dialog. */\n protected readonly titleId = `lc-confirm-title-${++ConfirmDialogComponent.nextId}`;\n\n /** Emitted when user confirms */\n readonly confirmed = output<void>();\n\n /** Emitted when user cancels */\n readonly cancelled = output<void>();\n\n /** Internal text input value */\n protected inputValue = signal('');\n\n /** Resolved icon name */\n protected resolvedIcon = computed(() => {\n const icon = this.icon();\n if (icon) return icon;\n switch (this.variant()) {\n case 'destructive':\n return 'exclamation-triangle';\n case 'warning':\n return 'exclamation-circle';\n default:\n // Tabler name — 'question-mark-circle' has no alias and rendered a placeholder\n return 'help-circle';\n }\n });\n\n /** Resolved icon color */\n protected iconColor = computed(() => {\n switch (this.variant()) {\n case 'destructive':\n return 'var(--color-error-default)';\n case 'warning':\n return 'var(--color-warning-default)';\n default:\n return 'var(--color-primary-600)';\n }\n });\n\n /** Confirm button variant */\n protected confirmButtonVariant = computed(() => {\n switch (this.variant()) {\n case 'destructive':\n return 'danger';\n case 'warning':\n return 'warning';\n default:\n return 'primary';\n }\n });\n\n /** Whether confirm is allowed (text match check) */\n protected confirmAllowed = computed(() => {\n const req = this.requireText();\n if (!req) return true;\n return this.inputValue() === req.expected;\n });\n\n constructor() {\n // Reset input when dialog opens\n effect(() => {\n if (this.open()) {\n this.inputValue.set('');\n }\n });\n }\n\n /**\n * Confirm via button click or Enter inside the require-text input.\n * Enter is deliberately NOT handled on the whole dialog: the focus trap\n * lands on the close/cancel buttons first, and Enter there must activate\n * *that* button, never the (possibly destructive) confirm action.\n */\n protected onConfirm(): void {\n if (!this.confirmAllowed() || this.confirmLoading()) return;\n this.confirmed.emit();\n }\n\n protected onCancel(): void {\n this.cancelled.emit();\n }\n\n protected onModalClose(): void {\n this.cancelled.emit();\n }\n\n protected onInputChange(value: string | number): void {\n this.inputValue.set(String(value));\n }\n}\n","<lc-modal\n [open]=\"open()\"\n size=\"sm\"\n [placement]=\"placement()\"\n [showCloseButton]=\"true\"\n [closeAriaLabel]=\"closeAriaLabel()\"\n [ariaLabelledBy]=\"titleId\"\n (openChange)=\"$event ? null : onModalClose()\"\n>\n <div slot=\"header\">\n <div class=\"lc-confirm__header\">\n <lc-icon\n [name]=\"resolvedIcon()\"\n size=\"md\"\n [color]=\"iconColor()\"\n [decorative]=\"true\"\n />\n <h2 [id]=\"titleId\">{{ title() }}</h2>\n </div>\n </div>\n\n <div slot=\"body\">\n <p class=\"lc-confirm__message\">{{ message() }}</p>\n\n <div class=\"lc-confirm__preview\">\n <ng-content select=\"[slot='preview']\" />\n </div>\n\n @if (requireText(); as req) {\n <div class=\"lc-confirm__require-text\">\n <!-- lc-input renders the prompt as an associated <label for> -->\n <lc-input\n [label]=\"req.prompt\"\n [placeholder]=\"req.expected\"\n (valueChange)=\"onInputChange($event)\"\n (enterPressed)=\"onConfirm()\"\n />\n </div>\n }\n </div>\n\n <div slot=\"footer\" class=\"lc-confirm__footer\">\n <lc-button\n variant=\"ghost\"\n [size]=\"buttonSize()\"\n (clicked)=\"onCancel()\"\n >\n {{ cancelLabel() }}\n </lc-button>\n <lc-button\n [variant]=\"confirmButtonVariant()\"\n [size]=\"buttonSize()\"\n [disabled]=\"!confirmAllowed()\"\n [loading]=\"confirmLoading()\"\n (clicked)=\"onConfirm()\"\n >\n {{ confirmLabel() }}\n </lc-button>\n </div>\n</lc-modal>\n","import {\n Injectable,\n ApplicationRef,\n createComponent,\n EnvironmentInjector,\n inject,\n} from '@angular/core';\nimport {\n ConfirmDialogButtonSize,\n ConfirmDialogComponent,\n ConfirmDialogVariant,\n RequireTextConfig,\n} from './confirm-dialog.component';\nimport type { ModalPlacement } from '@lifecorner/angular-ui-kit/modal';\n\nexport interface ConfirmOptions {\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: ConfirmDialogVariant;\n icon?: string;\n requireText?: RequireTextConfig;\n /** Accessible name of the close button (3.3). */\n closeAriaLabel?: string;\n /** Size of both buttons (3.3): `lg` for a 44 px touch target. */\n buttonSize?: ConfirmDialogButtonSize;\n /** `center`, `auto` (a bottom sheet below 640 px) or `sheet` (3.3). */\n placement?: ModalPlacement;\n}\n\n/**\n * Imperative confirm dialog service.\n *\n * @example\n * ```ts\n * const ok = await this.confirmService.confirm({\n * title: 'Delete item?',\n * message: 'This cannot be undone.',\n * });\n * if (ok) { ... }\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class ConfirmService {\n private readonly appRef = inject(ApplicationRef);\n private readonly injector = inject(EnvironmentInjector);\n\n /**\n * Show a confirmation dialog and return a promise that resolves\n * to true (confirmed) or false (cancelled).\n */\n confirm(opts: ConfirmOptions): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n // Create a host element\n const hostEl = document.createElement('div');\n document.body.appendChild(hostEl);\n\n const componentRef = createComponent(ConfirmDialogComponent, {\n hostElement: hostEl,\n environmentInjector: this.injector,\n });\n\n // Set inputs\n componentRef.setInput('open', true);\n componentRef.setInput('title', opts.title);\n componentRef.setInput('message', opts.message);\n if (opts.confirmLabel) componentRef.setInput('confirmLabel', opts.confirmLabel);\n if (opts.cancelLabel) componentRef.setInput('cancelLabel', opts.cancelLabel);\n if (opts.variant) componentRef.setInput('variant', opts.variant);\n if (opts.icon) componentRef.setInput('icon', opts.icon);\n if (opts.requireText) componentRef.setInput('requireText', opts.requireText);\n if (opts.closeAriaLabel) componentRef.setInput('closeAriaLabel', opts.closeAriaLabel);\n if (opts.buttonSize) componentRef.setInput('buttonSize', opts.buttonSize);\n if (opts.placement) componentRef.setInput('placement', opts.placement);\n\n const cleanup = () => {\n this.appRef.detachView(componentRef.hostView);\n componentRef.destroy();\n hostEl.remove();\n };\n\n componentRef.instance.confirmed.subscribe(() => {\n cleanup();\n resolve(true);\n });\n\n componentRef.instance.cancelled.subscribe(() => {\n cleanup();\n resolve(false);\n });\n\n this.appRef.attachView(componentRef.hostView);\n });\n }\n\n /**\n * Show a destructive confirmation dialog.\n * Shorthand for `confirm({ ...opts, variant: 'destructive' })`.\n */\n destructive(opts: Omit<ConfirmOptions, 'variant'>): Promise<boolean> {\n return this.confirm({ ...opts, variant: 'destructive' });\n }\n\n /**\n * Show a warning confirmation dialog.\n * Shorthand for `confirm({ ...opts, variant: 'warning' })`.\n */\n warning(opts: Omit<ConfirmOptions, 'variant'>): Promise<boolean> {\n return this.confirm({ ...opts, variant: 'warning' });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-confirm-dialog.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/confirm-dialog/confirm-dialog.component.ts","../../../../libs/angular-ui-kit/src/lib/confirm-dialog/confirm-dialog.component.html","../../../../libs/angular-ui-kit/src/lib/confirm-dialog/confirm.service.ts"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n input,\n output,\n signal,\n computed,\n effect,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_EXCLAMATION_CIRCLE, ICON_EXCLAMATION_TRIANGLE } from '@lifecorner/angular-ui-kit/icons';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\nimport { InputComponent } from '@lifecorner/angular-ui-kit/input';\nimport { ModalComponent, ModalPlacement } from '@lifecorner/angular-ui-kit/modal';\n\nexport type ConfirmDialogVariant = 'default' | 'destructive' | 'warning';\n\n/** Size of the confirm and cancel buttons (`lg` = 48.5 px, a 44 px target). */\nexport type ConfirmDialogButtonSize = 'sm' | 'md' | 'lg';\n\nexport interface RequireTextConfig {\n prompt: string;\n expected: string;\n}\n\n/**\n * Confirm dialog component for confirming user actions.\n *\n * Builds on `<lc-modal>` to provide a standardized confirmation pattern\n * with optional destructive variant and text-matching confirmation.\n *\n * The dialog is named by its title (`aria-labelledby`); `[slot='preview']`\n * shows what the action affects below the message; `confirmLoading` keeps the\n * dialog open with a busy confirm button while the action runs.\n *\n * @example\n * ```html\n * <lc-confirm-dialog\n * [open]=\"showConfirm()\"\n * variant=\"destructive\"\n * title=\"Delete project?\"\n * message=\"This cannot be undone.\"\n * (confirmed)=\"onDelete()\"\n * (cancelled)=\"showConfirm.set(false)\"\n * />\n * ```\n */\n@Component({\n selector: 'lc-confirm-dialog',\n standalone: true,\n imports: [FormsModule, IconComponent, ButtonComponent, ModalComponent, InputComponent],\n viewProviders: [ɵprovideKitIcons([ICON_EXCLAMATION_TRIANGLE, ICON_EXCLAMATION_CIRCLE])],\n templateUrl: './confirm-dialog.component.html',\n styleUrls: ['./confirm-dialog.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ConfirmDialogComponent {\n private static nextId = 0;\n\n /** Whether the dialog is open */\n readonly open = input<boolean>(false);\n\n /** Dialog variant */\n readonly variant = input<ConfirmDialogVariant>('default');\n\n /** Dialog title */\n readonly title = input.required<string>();\n\n /** Dialog message */\n readonly message = input.required<string>();\n\n /** Confirm button label */\n readonly confirmLabel = input<string>('Confirm');\n\n /** Cancel button label */\n readonly cancelLabel = input<string>('Cancel');\n\n /** Icon name (auto-set by variant if not provided) */\n readonly icon = input<string>();\n\n /** Require text match to enable confirm */\n readonly requireText = input<RequireTextConfig>();\n\n /** Accessible name of the close button in the header. */\n readonly closeAriaLabel = input('Close modal');\n\n /**\n * Shows a spinner on the confirm button and blocks a second confirm while\n * the action runs; the app closes the dialog when it is done.\n * @default false\n */\n readonly confirmLoading = input<boolean>(false);\n\n /**\n * Size of the confirm and cancel buttons: `md` (3.2) or `lg` (48.5 px, the\n * 44 px touch target), or `sm`.\n * @default 'md'\n */\n readonly buttonSize = input<ConfirmDialogButtonSize>('md');\n\n /**\n * Where the dialog sits (passed to `lc-modal`): `center` (3.2), `auto` (a\n * bottom sheet below 640 px) or `sheet`.\n * @default 'center'\n */\n readonly placement = input<ModalPlacement>('center');\n\n /** Id of the title, which names the dialog. */\n protected readonly titleId = `lc-confirm-title-${++ConfirmDialogComponent.nextId}`;\n\n /** Emitted when user confirms */\n readonly confirmed = output<void>();\n\n /** Emitted when user cancels */\n readonly cancelled = output<void>();\n\n /** Internal text input value */\n protected inputValue = signal('');\n\n /** Resolved icon name */\n protected resolvedIcon = computed(() => {\n const icon = this.icon();\n if (icon) return icon;\n switch (this.variant()) {\n case 'destructive':\n return 'exclamation-triangle';\n case 'warning':\n return 'exclamation-circle';\n default:\n // Tabler name — 'question-mark-circle' has no alias and rendered a placeholder\n return 'help-circle';\n }\n });\n\n /** Resolved icon color */\n protected iconColor = computed(() => {\n switch (this.variant()) {\n case 'destructive':\n return 'var(--color-error-default)';\n case 'warning':\n return 'var(--color-warning-default)';\n default:\n return 'var(--color-primary-600)';\n }\n });\n\n /** Confirm button variant */\n protected confirmButtonVariant = computed(() => {\n switch (this.variant()) {\n case 'destructive':\n return 'danger';\n case 'warning':\n return 'warning';\n default:\n return 'primary';\n }\n });\n\n /** Whether confirm is allowed (text match check) */\n protected confirmAllowed = computed(() => {\n const req = this.requireText();\n if (!req) return true;\n return this.inputValue() === req.expected;\n });\n\n constructor() {\n // Reset input when dialog opens\n effect(() => {\n if (this.open()) {\n this.inputValue.set('');\n }\n });\n }\n\n /**\n * Confirm via button click or Enter inside the require-text input.\n * Enter is deliberately NOT handled on the whole dialog: the focus trap\n * lands on the close/cancel buttons first, and Enter there must activate\n * *that* button, never the (possibly destructive) confirm action.\n */\n protected onConfirm(): void {\n if (!this.confirmAllowed() || this.confirmLoading()) return;\n this.confirmed.emit();\n }\n\n protected onCancel(): void {\n this.cancelled.emit();\n }\n\n protected onModalClose(): void {\n this.cancelled.emit();\n }\n\n protected onInputChange(value: string | number): void {\n this.inputValue.set(String(value));\n }\n}\n","<lc-modal\n [open]=\"open()\"\n size=\"sm\"\n [placement]=\"placement()\"\n [showCloseButton]=\"true\"\n [closeAriaLabel]=\"closeAriaLabel()\"\n [ariaLabelledBy]=\"titleId\"\n (openChange)=\"$event ? null : onModalClose()\"\n>\n <div slot=\"header\">\n <div class=\"lc-confirm__header\">\n <lc-icon\n [name]=\"resolvedIcon()\"\n size=\"md\"\n [color]=\"iconColor()\"\n [decorative]=\"true\"\n />\n <h2 [id]=\"titleId\">{{ title() }}</h2>\n </div>\n </div>\n\n <div slot=\"body\">\n <p class=\"lc-confirm__message\">{{ message() }}</p>\n\n <div class=\"lc-confirm__preview\">\n <ng-content select=\"[slot='preview']\" />\n </div>\n\n @if (requireText(); as req) {\n <div class=\"lc-confirm__require-text\">\n <!-- lc-input renders the prompt as an associated <label for> -->\n <lc-input\n [label]=\"req.prompt\"\n [placeholder]=\"req.expected\"\n (valueChange)=\"onInputChange($event)\"\n (enterPressed)=\"onConfirm()\"\n />\n </div>\n }\n </div>\n\n <div slot=\"footer\" class=\"lc-confirm__footer\">\n <lc-button\n variant=\"ghost\"\n [size]=\"buttonSize()\"\n (clicked)=\"onCancel()\"\n >\n {{ cancelLabel() }}\n </lc-button>\n <lc-button\n [variant]=\"confirmButtonVariant()\"\n [size]=\"buttonSize()\"\n [disabled]=\"!confirmAllowed()\"\n [loading]=\"confirmLoading()\"\n (clicked)=\"onConfirm()\"\n >\n {{ confirmLabel() }}\n </lc-button>\n </div>\n</lc-modal>\n","import {\n Injectable,\n ApplicationRef,\n createComponent,\n EnvironmentInjector,\n inject,\n} from '@angular/core';\nimport {\n ConfirmDialogButtonSize,\n ConfirmDialogComponent,\n ConfirmDialogVariant,\n RequireTextConfig,\n} from './confirm-dialog.component';\nimport type { ModalPlacement } from '@lifecorner/angular-ui-kit/modal';\n\nexport interface ConfirmOptions {\n title: string;\n message: string;\n confirmLabel?: string;\n cancelLabel?: string;\n variant?: ConfirmDialogVariant;\n icon?: string;\n requireText?: RequireTextConfig;\n /** Accessible name of the close button (3.3). */\n closeAriaLabel?: string;\n /** Size of both buttons (3.3): `lg` for a 44 px touch target. */\n buttonSize?: ConfirmDialogButtonSize;\n /** `center`, `auto` (a bottom sheet below 640 px) or `sheet` (3.3). */\n placement?: ModalPlacement;\n}\n\n/**\n * Imperative confirm dialog service.\n *\n * @example\n * ```ts\n * const ok = await this.confirmService.confirm({\n * title: 'Delete item?',\n * message: 'This cannot be undone.',\n * });\n * if (ok) { ... }\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class ConfirmService {\n private readonly appRef = inject(ApplicationRef);\n private readonly injector = inject(EnvironmentInjector);\n\n /**\n * Show a confirmation dialog and return a promise that resolves\n * to true (confirmed) or false (cancelled).\n */\n confirm(opts: ConfirmOptions): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n // Create a host element\n const hostEl = document.createElement('div');\n document.body.appendChild(hostEl);\n\n const componentRef = createComponent(ConfirmDialogComponent, {\n hostElement: hostEl,\n environmentInjector: this.injector,\n });\n\n // Set inputs\n componentRef.setInput('open', true);\n componentRef.setInput('title', opts.title);\n componentRef.setInput('message', opts.message);\n if (opts.confirmLabel) componentRef.setInput('confirmLabel', opts.confirmLabel);\n if (opts.cancelLabel) componentRef.setInput('cancelLabel', opts.cancelLabel);\n if (opts.variant) componentRef.setInput('variant', opts.variant);\n if (opts.icon) componentRef.setInput('icon', opts.icon);\n if (opts.requireText) componentRef.setInput('requireText', opts.requireText);\n if (opts.closeAriaLabel) componentRef.setInput('closeAriaLabel', opts.closeAriaLabel);\n if (opts.buttonSize) componentRef.setInput('buttonSize', opts.buttonSize);\n if (opts.placement) componentRef.setInput('placement', opts.placement);\n\n const cleanup = () => {\n this.appRef.detachView(componentRef.hostView);\n componentRef.destroy();\n hostEl.remove();\n };\n\n componentRef.instance.confirmed.subscribe(() => {\n cleanup();\n resolve(true);\n });\n\n componentRef.instance.cancelled.subscribe(() => {\n cleanup();\n resolve(false);\n });\n\n this.appRef.attachView(componentRef.hostView);\n });\n }\n\n /**\n * Show a destructive confirmation dialog.\n * Shorthand for `confirm({ ...opts, variant: 'destructive' })`.\n */\n destructive(opts: Omit<ConfirmOptions, 'variant'>): Promise<boolean> {\n return this.confirm({ ...opts, variant: 'destructive' });\n }\n\n /**\n * Show a warning confirmation dialog.\n * Shorthand for `confirm({ ...opts, variant: 'warning' })`.\n */\n warning(opts: Omit<ConfirmOptions, 'variant'>): Promise<boolean> {\n return this.confirm({ ...opts, variant: 'warning' });\n }\n}\n"],"mappings":";;;;;;;;AAyDA,IAAa,yBAAb,MAAa,uBAAsB;CACzB,OAAO,SAAS;CAGf,OAAO,MAAe,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAG5B,UAAU,MAA4B,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAGhD,QAAQ,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAGhC,UAAU,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAGlC,eAAe,MAAc,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAGvC,cAAc,MAAc,UAAS,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAGrC,OAAO,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAGtB,cAAc,MAA0B,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAGxC,iBAAiB,MAAM,eAAc,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAOrC,iBAAiB,MAAe,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAOtC,aAAa,MAA+B,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAOjD,YAAY,MAAsB,UAAS,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAGjC,UAAU,oBAAoB,EAAE,uBAAuB;CAGjE,YAAY,OAAM;CAGlB,YAAY,OAAM;CAGjB,aAAa,OAAO,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAGvB,eAAe,eAAc;EACrC,MAAM,OAAO,KAAK,KAAI;EACtB,IAAI,MAAM,OAAO;EACjB,QAAQ,KAAK,QAAO,GAApB;GACE,KAAK,eACH,OAAO;GACT,KAAK,WACH,OAAO;GACT,SAEE,OAAO;EACX;CACF,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAGQ,YAAY,eAAc;EAClC,QAAQ,KAAK,QAAO,GAApB;GACE,KAAK,eACH,OAAO;GACT,KAAK,WACH,OAAO;GACT,SACE,OAAO;EACX;CACF,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;CAGQ,uBAAuB,eAAc;EAC7C,QAAQ,KAAK,QAAO,GAApB;GACE,KAAK,eACH,OAAO;GACT,KAAK,WACH,OAAO;GACT,SACE,OAAO;EACX;CACF,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,uBAAA,CAAA,+BAAA,CAAA,CAAA;CAGQ,iBAAiB,eAAc;EACvC,MAAM,MAAM,KAAK,YAAW;EAC5B,IAAI,CAAC,KAAK,OAAO;EACjB,OAAO,KAAK,WAAU,MAAO,IAAI;CACnC,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAEF,cAAA;EAEE,aAAY;GACV,IAAI,KAAK,KAAI,GACX,KAAK,WAAW,IAAI,EAAE;EAE1B,CAAC;CACH;CAQU,YAAS;EACjB,IAAI,CAAC,KAAK,eAAc,KAAM,KAAK,eAAc,GAAI;EACrD,KAAK,UAAU,KAAI;CACrB;CAEU,WAAQ;EAChB,KAAK,UAAU,KAAI;CACrB;CAEU,eAAY;EACpB,KAAK,UAAU,KAAI;CACrB;CAEU,cAAc,OAAsB;EAC5C,KAAK,WAAW,IAAI,OAAO,KAAK,CAAC;CACnC;CA3IW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAsB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAtB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAsB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,cAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,gBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,gBAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,WAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,SAAA;GAAA,WAAA;GAAA,WAAA;EAAA;EAAA,UAAA;EAAA,UCzDnC;EA4DA,QAAA,CAAA,khBAAA;EAAA,cAAA;GAAA;IAAA,MAAA;IAAA,MDTY;GAAW;GAAA;IAAA,MAAA;IAAA,MAAE;IAAa,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAe,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAc,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;GAAA;IAAA,MAAA;IAAA,MAAE;IAAc,UAAA;IAAA,QAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;KAAA;IAAA;IAAA,SAAA;KAAA;KAAA;KAAA;KAAA;IAAA;GAAA;EAAA;EAAA,eACtE,CAAC,iBAAiB,CAAC,2BAA2B,uBAAuB,CAAC,CAAC;EAAC,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AAK5E,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAsB,YAAA,CAAA;EATlC,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAmB,YACjB;GAAI,SACP;IAAC;IAAa;IAAe;IAAiB;IAAgB;GAAc;GAAC,eACvE,CAAC,iBAAiB,CAAC,2BAA2B,uBAAuB,CAAC,CAAC;GAAC,iBAGtE,wBAAwB;GAAM,UAAA;GAAA,QAAA,CAAA,khBAAA;EAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AEXjD,IAAa,iBAAb,MAAa,eAAc;CACR,SAAS,OAAO,cAAc;CAC9B,WAAW,OAAO,mBAAmB;CAMtD,QAAQ,MAAoB;EAC1B,OAAO,IAAI,SAAkB,YAAW;GAEtC,MAAM,SAAS,SAAS,cAAc,KAAK;GAC3C,SAAS,KAAK,YAAY,MAAM;GAEhC,MAAM,eAAe,gBAAgB,wBAAwB;IAC3D,aAAa;IACb,qBAAqB,KAAK;GAC3B,CAAA;GAGD,aAAa,SAAS,QAAQ,IAAI;GAClC,aAAa,SAAS,SAAS,KAAK,KAAK;GACzC,aAAa,SAAS,WAAW,KAAK,OAAO;GAC7C,IAAI,KAAK,cAAc,aAAa,SAAS,gBAAgB,KAAK,YAAY;GAC9E,IAAI,KAAK,aAAa,aAAa,SAAS,eAAe,KAAK,WAAW;GAC3E,IAAI,KAAK,SAAS,aAAa,SAAS,WAAW,KAAK,OAAO;GAC/D,IAAI,KAAK,MAAM,aAAa,SAAS,QAAQ,KAAK,IAAI;GACtD,IAAI,KAAK,aAAa,aAAa,SAAS,eAAe,KAAK,WAAW;GAC3E,IAAI,KAAK,gBAAgB,aAAa,SAAS,kBAAkB,KAAK,cAAc;GACpF,IAAI,KAAK,YAAY,aAAa,SAAS,cAAc,KAAK,UAAU;GACxE,IAAI,KAAK,WAAW,aAAa,SAAS,aAAa,KAAK,SAAS;GAErE,MAAM,gBAAe;IACnB,KAAK,OAAO,WAAW,aAAa,QAAQ;IAC5C,aAAa,QAAO;IACpB,OAAO,OAAM;GACf;GAEA,aAAa,SAAS,UAAU,gBAAe;IAC7C,QAAO;IACP,QAAQ,IAAI;GACd,CAAC;GAED,aAAa,SAAS,UAAU,gBAAe;IAC7C,QAAO;IACP,QAAQ,KAAK;GACf,CAAC;GAED,KAAK,OAAO,WAAW,aAAa,QAAQ;EAC9C,CAAC;CACH;CAMA,YAAY,MAAqC;EAC/C,OAAO,KAAK,QAAQ;GAAE,GAAG;GAAM,SAAS;EAAa,CAAE;CACzD;CAMA,QAAQ,MAAqC;EAC3C,OAAO,KAAK,QAAQ;GAAE,GAAG;GAAM,SAAS;EAAS,CAAE;CACrD;CAlEW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAc,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAd,OAAA,QAAA,GAAA,sBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAc,YADD;CAAM,CAAA;;AACnB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAc,YAAA,CAAA;EAD1B,MAAA;EAAW,MAAA,CAAA,EAAE,YAAY,OAAM,CAAE"}
@@ -179,7 +179,8 @@ var CopyFieldComponent = class CopyFieldComponent {
179
179
  "type",
180
180
  "title",
181
181
  "disabledReason",
182
- "inline"
182
+ "inline",
183
+ "flush"
183
184
  ],
184
185
  outputs: [
185
186
  "clicked",
@@ -1 +1 @@
1
- {"version":3,"file":"lifecorner-angular-ui-kit-copy-field.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/copy-field/copy-field.component.ts","../../../../libs/angular-ui-kit/src/lib/copy-field/copy-field.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n inject,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHECK } from '@lifecorner/angular-ui-kit/icons';\nimport { InputComponent } from '@lifecorner/angular-ui-kit/input';\n\n/** `stacked`: the button below the value at full width (phones); `inline`: beside it. */\nexport type CopyFieldLayout = 'stacked' | 'inline';\n\n/** How long the button says \"Copied\" (ms). */\nconst CONFIRMATION_MS = 2000;\n\n/**\n * A value to copy — an invitation link, a token, a command: the value\n * read-only and wrapping (never clipped), a 48.5 px copy button, and one\n * polite announcement after copying. If the clipboard refuses, the value is\n * selected so the person can copy it by hand.\n *\n * @example\n * ```html\n * <lc-copy-field label=\"Einladungslink\" [value]=\"link\" copyLabel=\"Kopieren\"\n * copiedLabel=\"Kopiert\" copiedAnnouncement=\"Link kopiert\" />\n * ```\n */\n@Component({\n selector: 'lc-copy-field',\n imports: [InputComponent, ButtonComponent, IconComponent],\n viewProviders: [ɵprovideKitIcons([ICON_CHECK])],\n templateUrl: './copy-field.component.html',\n styleUrl: './copy-field.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class CopyFieldComponent {\n /** Label of the value (its accessible name). */\n readonly label = input<string>('');\n\n /** The value to copy. */\n readonly value = input<string>('');\n\n /** Help below the value. */\n readonly helperText = input<string>();\n\n /** `stacked` (default): button below at full width; `inline`: button beside the value. */\n readonly layout = input<CopyFieldLayout>('stacked');\n\n /** Show the clipboard (and, after copying, check) icon in the button. */\n readonly showIcon = input<boolean>(true);\n\n /** Button label. */\n readonly copyLabel = input('Copy');\n\n /** Button label for two seconds after copying. */\n readonly copiedLabel = input('Copied');\n\n /** Spoken once after copying (polite live region). */\n readonly copiedAnnouncement = input('Copied to the clipboard');\n\n /** Emitted with the value after it was copied. */\n readonly copied = output<string>();\n\n /** Emitted when the clipboard refused; the value is then selected for copying by hand. */\n readonly copyFailed = output<void>();\n\n protected readonly isCopied = signal(false);\n\n private readonly field = viewChild(InputComponent);\n private timer: ReturnType<typeof setTimeout> | undefined;\n\n constructor() {\n inject(DestroyRef).onDestroy(() => clearTimeout(this.timer));\n }\n\n /** Copies the value; on refusal selects it instead. */\n async copy(): Promise<void> {\n const value = this.value();\n try {\n const clipboard = typeof navigator === 'undefined' ? undefined : navigator.clipboard;\n if (!clipboard) throw new Error('Clipboard API unavailable');\n await clipboard.writeText(value);\n } catch {\n this.copyFailed.emit();\n this.field()?.focus();\n this.field()?.select();\n return;\n }\n this.isCopied.set(true);\n this.copied.emit(value);\n clearTimeout(this.timer);\n this.timer = setTimeout(() => this.isCopied.set(false), CONFIRMATION_MS);\n }\n}\n","<div\n class=\"lc-copy-field\"\n [class.lc-copy-field--stacked]=\"layout() === 'stacked'\"\n [class.lc-copy-field--inline]=\"layout() === 'inline'\"\n>\n <div class=\"lc-copy-field__value\">\n <lc-input\n [label]=\"label()\"\n [value]=\"value()\"\n [helperText]=\"helperText()\"\n size=\"lg\"\n [readonly]=\"true\"\n [readonlyWrap]=\"true\"\n />\n </div>\n\n <div class=\"lc-copy-field__action\">\n <lc-button variant=\"outline\" size=\"lg\" [fullWidth]=\"layout() === 'stacked'\" (clicked)=\"copy()\">\n @if (showIcon()) {\n <lc-icon slot=\"icon-before\" [name]=\"isCopied() ? 'check' : 'clipboard-document'\" size=\"sm\" [decorative]=\"true\" />\n }\n {{ isCopied() ? copiedLabel() : copyLabel() }}\n </lc-button>\n </div>\n\n <span class=\"lc-copy-field__live\" role=\"status\" aria-live=\"polite\">{{ isCopied() ? copiedAnnouncement() : '' }}</span>\n</div>\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-copy-field.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/copy-field/copy-field.component.ts","../../../../libs/angular-ui-kit/src/lib/copy-field/copy-field.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n inject,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHECK } from '@lifecorner/angular-ui-kit/icons';\nimport { InputComponent } from '@lifecorner/angular-ui-kit/input';\n\n/** `stacked`: the button below the value at full width (phones); `inline`: beside it. */\nexport type CopyFieldLayout = 'stacked' | 'inline';\n\n/** How long the button says \"Copied\" (ms). */\nconst CONFIRMATION_MS = 2000;\n\n/**\n * A value to copy — an invitation link, a token, a command: the value\n * read-only and wrapping (never clipped), a 48.5 px copy button, and one\n * polite announcement after copying. If the clipboard refuses, the value is\n * selected so the person can copy it by hand.\n *\n * @example\n * ```html\n * <lc-copy-field label=\"Einladungslink\" [value]=\"link\" copyLabel=\"Kopieren\"\n * copiedLabel=\"Kopiert\" copiedAnnouncement=\"Link kopiert\" />\n * ```\n */\n@Component({\n selector: 'lc-copy-field',\n imports: [InputComponent, ButtonComponent, IconComponent],\n viewProviders: [ɵprovideKitIcons([ICON_CHECK])],\n templateUrl: './copy-field.component.html',\n styleUrl: './copy-field.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class CopyFieldComponent {\n /** Label of the value (its accessible name). */\n readonly label = input<string>('');\n\n /** The value to copy. */\n readonly value = input<string>('');\n\n /** Help below the value. */\n readonly helperText = input<string>();\n\n /** `stacked` (default): button below at full width; `inline`: button beside the value. */\n readonly layout = input<CopyFieldLayout>('stacked');\n\n /** Show the clipboard (and, after copying, check) icon in the button. */\n readonly showIcon = input<boolean>(true);\n\n /** Button label. */\n readonly copyLabel = input('Copy');\n\n /** Button label for two seconds after copying. */\n readonly copiedLabel = input('Copied');\n\n /** Spoken once after copying (polite live region). */\n readonly copiedAnnouncement = input('Copied to the clipboard');\n\n /** Emitted with the value after it was copied. */\n readonly copied = output<string>();\n\n /** Emitted when the clipboard refused; the value is then selected for copying by hand. */\n readonly copyFailed = output<void>();\n\n protected readonly isCopied = signal(false);\n\n private readonly field = viewChild(InputComponent);\n private timer: ReturnType<typeof setTimeout> | undefined;\n\n constructor() {\n inject(DestroyRef).onDestroy(() => clearTimeout(this.timer));\n }\n\n /** Copies the value; on refusal selects it instead. */\n async copy(): Promise<void> {\n const value = this.value();\n try {\n const clipboard = typeof navigator === 'undefined' ? undefined : navigator.clipboard;\n if (!clipboard) throw new Error('Clipboard API unavailable');\n await clipboard.writeText(value);\n } catch {\n this.copyFailed.emit();\n this.field()?.focus();\n this.field()?.select();\n return;\n }\n this.isCopied.set(true);\n this.copied.emit(value);\n clearTimeout(this.timer);\n this.timer = setTimeout(() => this.isCopied.set(false), CONFIRMATION_MS);\n }\n}\n","<div\n class=\"lc-copy-field\"\n [class.lc-copy-field--stacked]=\"layout() === 'stacked'\"\n [class.lc-copy-field--inline]=\"layout() === 'inline'\"\n>\n <div class=\"lc-copy-field__value\">\n <lc-input\n [label]=\"label()\"\n [value]=\"value()\"\n [helperText]=\"helperText()\"\n size=\"lg\"\n [readonly]=\"true\"\n [readonlyWrap]=\"true\"\n />\n </div>\n\n <div class=\"lc-copy-field__action\">\n <lc-button variant=\"outline\" size=\"lg\" [fullWidth]=\"layout() === 'stacked'\" (clicked)=\"copy()\">\n @if (showIcon()) {\n <lc-icon slot=\"icon-before\" [name]=\"isCopied() ? 'check' : 'clipboard-document'\" size=\"sm\" [decorative]=\"true\" />\n }\n {{ isCopied() ? copiedLabel() : copyLabel() }}\n </lc-button>\n </div>\n\n <span class=\"lc-copy-field__live\" role=\"status\" aria-live=\"polite\">{{ isCopied() ? copiedAnnouncement() : '' }}</span>\n</div>\n"],"mappings":"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"}
@@ -494,7 +494,8 @@ var HeaderComponent = class HeaderComponent {
494
494
  "type",
495
495
  "title",
496
496
  "disabledReason",
497
- "inline"
497
+ "inline",
498
+ "flush"
498
499
  ],
499
500
  outputs: [
500
501
  "clicked",
@@ -1 +1 @@
1
- {"version":3,"file":"lifecorner-angular-ui-kit-header.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/header/header.component.ts","../../../../libs/angular-ui-kit/src/lib/header/header.component.html"],"sourcesContent":["import {\n Component,\n ElementRef,\n Injector,\n input,\n output,\n signal,\n computed,\n inject,\n viewChild,\n afterRenderEffect,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { RouterModule } from '@angular/router';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\nimport { LogoComponent } from '@lifecorner/angular-ui-kit/logo';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_BARS_3, ICON_CHEVRON_DOWN, ICON_LOGOUT, ICON_MOON, ICON_SUN, ICON_USER } from '@lifecorner/angular-ui-kit/icons';\nimport { AvatarColor, AvatarComponent } from '@lifecorner/angular-ui-kit/avatar';\nimport { MenuComponent, MenuItem } from '@lifecorner/angular-ui-kit/menu';\nimport { ThemeService } from '@lifecorner/angular-ui-kit/theme';\n\n/** A link in the header's main navigation (`navItems`). */\nexport interface HeaderNavItem {\n /** Visible link text. */\n label: string;\n /** Plain URL — rendered as a native `href`, no router involved. */\n href: string;\n /** Marks the page the visitor is on (`aria-current=\"page\"` + underline). */\n current?: boolean;\n}\n\n/** Element used for the header title (`titleTag`). */\nexport type HeaderTitleTag = 'h1' | 'h2' | 'h3' | 'p' | 'span' | 'div';\n\n/**\n * Surface of the header: `default` is the bar on `--color-surface` with a\n * bottom border; `transparent` has no background and no border, for a header\n * that sits on the page (\"Weite\").\n */\nexport type HeaderVariant = 'default' | 'transparent';\n\n/**\n * What the account-menu button shows: `icon` (a user icon and a chevron) or\n * `avatar` (the person's initials avatar, `userName`, `userAvatarSrc`,\n * `userAvatarColor`, in a 48 px round button).\n */\nexport type HeaderUserMenuTrigger = 'icon' | 'avatar';\n\n/**\n * AppHeaderComponent - Global application header for the LifeCorner shell\n *\n * Features:\n * - Clickable logo for home navigation\n * - Optional title and subtitle display\n * - User profile dropdown with avatar, name, email, optional Profile link, and Logout\n * - Optional theme toggle button in header. By default the button toggles the\n * `ThemeService` itself and additionally emits `themeToggleClick`, so the\n * handler must NOT toggle again (that would undo the switch). To own the\n * toggling in the app, set `[autoToggleTheme]=\"false\"` and toggle in the\n * handler.\n * - Hamburger menu toggle for mobile sidebar; bind `sidenavOpen` (and\n * `sidenavId`) so the toggle exposes `aria-expanded` / `aria-controls`.\n * - OnPush change detection for performance\n *\n * Public, prerendered sites (no router, no JavaScript needed):\n * - `homeHref` makes the brand a plain link (instead of `routerLink=\"/\"`).\n * - `navItems` render a labelled main navigation (`<nav aria-label><ul>` with\n * `aria-current=\"page\"` on the current item); below 1024 px it moves to a\n * second row and wraps.\n * - `[slot='end']` takes content at the end of the first row (e.g. a language\n * link), `showUserMenu` hides the account menu, `titleTag` picks the title\n * element (the page keeps its own `<h1>`), `sticky` can be switched off.\n * App shell (\"Weite\", kit 3.3):\n * - `variant=\"transparent\"`: no background and no border, the header sits on\n * the page (pair it with `[sticky]=\"false\"`, a header without a surface\n * cannot stay over scrolling text).\n * - `userMenuTrigger=\"avatar\"`: the account button is the person's initials\n * avatar (`userAvatarColor` for the member colour, `userAvatarSrc` for a\n * photo) in a 48 px round button; the icon trigger is 44 px high in every\n * density.\n * - The subtitle (e.g. a household name) stays on one line and ends with \"…\";\n * the full text is its `title` and stays in the accessible text. It is shown\n * as typed (no uppercase).\n * - The account menu is at most `min(18rem, 100vw − 2rem)` wide; the name and\n * email in its header wrap instead of being cut.\n * - Every built-in label is an input (`homeAriaLabel`, `hamburgerAriaLabel`,\n * `userMenuAriaLabel`, `navAriaLabel`, `profileLabel`, `logoutLabel`,\n * `themeToDarkAriaLabel`, `themeToLightAriaLabel`, `contextAriaLabel`);\n * the defaults stay English.\n * - The `ThemeService` (which persists to localStorage) is only created when\n * the theme button is shown.\n *\n * @example\n * ```html\n * <lc-header\n * [logo]=\"'/assets/logo.svg'\"\n * [title]=\"'LifeCorner'\"\n * [subtitle]=\"'User Profile'\"\n * [userName]=\"'John Doe'\"\n * [userEmail]=\"'user@example.com'\"\n * [showHamburger]=\"true\"\n * [sidenavOpen]=\"sidenavOpen\"\n * sidenavId=\"app-sidenav\"\n * [showThemeButton]=\"true\"\n * [showProfileMenuItem]=\"true\"\n * (hamburgerClick)=\"toggleSidebar()\"\n * (themeToggleClick)=\"trackThemeToggle()\"\n * (profileClick)=\"navigateToProfile()\"\n * (logoutClick)=\"handleLogout()\"\n * />\n *\n * <!-- App-controlled theme: the header only reports the click -->\n * <lc-header\n * [showThemeButton]=\"true\"\n * [autoToggleTheme]=\"false\"\n * (themeToggleClick)=\"toggleTheme()\"\n * />\n *\n * <!-- Public site: plain links, labelled nav, language link at the end -->\n * <lc-header\n * size=\"sm\"\n * [sticky]=\"false\"\n * [showUserMenu]=\"false\"\n * homeHref=\"/de/\"\n * homeAriaLabel=\"Produkt – Startseite\"\n * navAriaLabel=\"Hauptnavigation\"\n * [navItems]=\"[\n * { label: 'Sicherheit', href: '/de/sicherheit', current: true },\n * { label: 'Roadmap', href: '/de/roadmap' }\n * ]\"\n * >\n * <a slot=\"end\" lcButton variant=\"ghost\" href=\"/en/security\" hreflang=\"en\" lang=\"en\">English</a>\n * </lc-header>\n * ```\n */\n@Component({\n selector: 'lc-header',\n standalone: true,\n imports: [\n NgTemplateOutlet,\n RouterModule,\n ButtonComponent,\n LogoComponent,\n IconComponent,\n AvatarComponent,\n MenuComponent,\n ],\n // Its own glyphs, and the profile menu's (lc-menu renders them in this view).\n viewProviders: [ɵprovideKitIcons([ICON_BARS_3, ICON_SUN, ICON_MOON, ICON_USER, ICON_CHEVRON_DOWN, ICON_LOGOUT])],\n templateUrl: './header.component.html',\n styleUrl: './header.component.scss',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'lc-header-host',\n },\n})\nexport class HeaderComponent {\n readonly theme = input<'light' | 'dark' | 'auto'>('auto');\n readonly logo = input('');\n /**\n * Render the brand block. On its own this shows the emblem; with `logo` set\n * it shows the full lockup. (It used to additionally require `logo` or\n * `title`, so `showLogo` alone rendered an empty 0px-wide brand area with no\n * error — an app could end up with no branding at all and no clue why.)\n */\n readonly showLogo = input(true);\n /** Custom URL for the full brand logo (forwarded to inner `<lc-logo>`). */\n readonly logoSrc = input('');\n /** Custom URL for the emblem-only brand logo. */\n readonly logoEmblemSrc = input('');\n /** Optional dark-theme URL for the full brand logo. */\n readonly logoDarkSrc = input('');\n /** Optional dark-theme URL for the emblem-only brand logo. */\n readonly logoDarkEmblemSrc = input('');\n /** Alt text for the brand logo (forwarded to inner `<lc-logo>`). */\n readonly logoAlt = input('');\n /** Size of the brand logo (forwarded to inner `<lc-logo>`). Defaults to `md`. */\n readonly logoSize = input<'xs' | 'sm' | 'md' | 'lg' | 'xl'>('md');\n /**\n * Overall header height. Useful to align the header with a sidebar brand block.\n * Maps to the same `min-height` scale the sidenav logo area uses:\n * `sm` 56px · `md` 64px (default) · `lg` 80px · `xl` 112px.\n */\n readonly size = input<'sm' | 'md' | 'lg' | 'xl'>('md');\n readonly title = input('');\n /**\n * Surface: `default` (the bar on `--color-surface` with a bottom border) or\n * `transparent` (no background, no border — the header sits on the page).\n */\n readonly variant = input<HeaderVariant>('default');\n /**\n * Element for the title. `h1` keeps the app-shell behaviour; on a site whose\n * pages carry their own `<h1>`, use `span` (or `p`/`div`).\n */\n readonly titleTag = input<HeaderTitleTag>('h1');\n /**\n * Second line under the title (e.g. the household name). One line, cut\n * with \"…\" when it does not fit; the full text is its `title` attribute.\n * Shown as typed.\n */\n readonly subtitle = input('');\n readonly userEmail = input('');\n readonly userName = input('');\n /**\n * What the account-menu button shows: `icon` (user icon and chevron) or\n * `avatar` (the initials of `userName` in a 48 px round button).\n */\n readonly userMenuTrigger = input<HeaderUserMenuTrigger>('icon');\n /** Photo for the account avatar (trigger and menu header); initials when empty or broken. */\n readonly userAvatarSrc = input('');\n /** Colour of the account avatar's initials: `default` or a member colour `member-1` … `member-6`. */\n readonly userAvatarColor = input<AvatarColor>('default');\n readonly showHamburger = input(false);\n /**\n * Open state of the sidenav the hamburger controls. When bound, the toggle\n * announces it via `aria-expanded`; leave `undefined` when the header does\n * not know (the attribute is then omitted rather than lying).\n */\n readonly sidenavOpen = input<boolean | undefined>(undefined);\n /** DOM id of the sidenav the hamburger controls (`aria-controls`). */\n readonly sidenavId = input('');\n readonly showThemeButton = input(false);\n /**\n * Whether the theme button toggles the `ThemeService` itself before emitting\n * `themeToggleClick`. Set to `false` when the app owns the theme switch and\n * toggles in the `(themeToggleClick)` handler — otherwise both would toggle\n * and the click would be a no-op.\n */\n readonly autoToggleTheme = input(true);\n readonly contextName = input('');\n readonly contextLabel = input('');\n readonly menuSize = input<'sm' | 'md' | 'lg'>('sm');\n readonly showProfileMenuItem = input(true);\n /** Render the account menu (avatar trigger with Profile/Logout). */\n readonly showUserMenu = input(true);\n /**\n * Plain URL for the brand link. When set, the brand is a native\n * `<a href>` — no router needed (static or prerendered sites). Empty keeps\n * `routerLink=\"/\"`.\n */\n readonly homeHref = input('');\n /**\n * Main navigation links, rendered as `<nav><ul><li><a href>` with\n * `aria-current=\"page\"` on the current one. On screens below 1024 px the\n * navigation takes a second row and wraps.\n */\n readonly navItems = input<readonly HeaderNavItem[]>([]);\n /** Keep the header at the top while scrolling (`position: sticky`). */\n readonly sticky = input(true);\n\n // Labels (defaults are English; translate them in the app).\n /** Accessible name of the brand link. */\n readonly homeAriaLabel = input('Go to home');\n /** Accessible name of the hamburger button. */\n readonly hamburgerAriaLabel = input('Toggle sidebar menu');\n /** Accessible name of the account menu trigger. */\n readonly userMenuAriaLabel = input('Open user menu');\n /** Accessible name of the `<nav>` around `navItems`. */\n readonly navAriaLabel = input('Main navigation');\n /** Label of the theme button while the light theme is active. */\n readonly themeToDarkAriaLabel = input('Switch to dark mode');\n /** Label of the theme button while the dark theme is active. */\n readonly themeToLightAriaLabel = input('Switch to light mode');\n /** Accessible name of the context button (`contextName`). */\n readonly contextAriaLabel = input('Context info');\n /** Label of the Profile entry in the account menu. */\n readonly profileLabel = input('Profile');\n /** Label of the Logout entry in the account menu. */\n readonly logoutLabel = input('Logout');\n\n readonly hamburgerClick = output<void>();\n readonly themeToggleClick = output<void>();\n readonly logoutClick = output<void>();\n readonly profileClick = output<void>();\n readonly contextClick = output<void>();\n\n private readonly injector = inject(Injector);\n private themeServiceInstance: ThemeService | null = null;\n\n /**\n * Resolved on first use, i.e. only when the theme button is shown: creating\n * the ThemeService reads and writes the theme class and localStorage, which a\n * site without a theme switch must not do.\n */\n protected get themeService(): ThemeService {\n return (this.themeServiceInstance ??= this.injector.get(ThemeService));\n }\n\n private readonly hamburger = viewChild('hamburger', { read: ElementRef<HTMLElement> });\n\n constructor() {\n // The hamburger is an <lc-button>; the ARIA state belongs on its native\n // <button> (the element that has the button role), not on the custom\n // element host — so it is reflected after render rather than bound in the\n // template.\n afterRenderEffect(() => {\n const button = this.hamburger()?.nativeElement.querySelector('button');\n if (!button) return;\n const open = this.sidenavOpen();\n const controls = this.sidenavId();\n if (open === undefined) {\n button.removeAttribute('aria-expanded');\n } else {\n button.setAttribute('aria-expanded', String(open));\n }\n if (controls) {\n button.setAttribute('aria-controls', controls);\n } else {\n button.removeAttribute('aria-controls');\n }\n });\n }\n\n /**\n * Get menu items for profile dropdown\n */\n protected readonly menuItems = computed<MenuItem[]>(() => {\n const items: MenuItem[] = [];\n\n // Add profile link if enabled\n if (this.showProfileMenuItem()) {\n items.push({\n id: 'profile',\n label: this.profileLabel(),\n icon: 'user',\n dividerAfter: true,\n });\n }\n\n // Add logout\n items.push({\n id: 'logout',\n label: this.logoutLabel(),\n icon: 'arrow-right-start-on-rectangle',\n variant: 'danger',\n });\n\n return items;\n });\n\n /**\n * Dropdown open state (using Angular signals)\n */\n private readonly dropdownOpen = signal<boolean>(false);\n\n /**\n * Get dropdown open state\n */\n isDropdownOpen(): boolean {\n return this.dropdownOpen();\n }\n\n /**\n * Toggle profile dropdown visibility\n */\n toggleDropdown(): void {\n this.dropdownOpen.set(!this.dropdownOpen());\n }\n\n /**\n * Close profile dropdown\n */\n closeDropdown(): void {\n this.dropdownOpen.set(false);\n }\n\n /**\n * Handle hamburger click\n */\n onHamburgerClick(): void {\n this.hamburgerClick.emit();\n }\n\n /**\n * Handle theme button click (separate button, not in menu). Toggles the\n * theme unless the app opted out via `autoToggleTheme`, then emits.\n */\n onThemeButtonClick(): void {\n if (this.autoToggleTheme()) {\n this.themeService.toggleTheme();\n }\n this.themeToggleClick.emit();\n }\n\n /**\n * Handle logout click\n */\n onLogoutClick(): void {\n this.logoutClick.emit();\n this.closeDropdown();\n }\n\n /**\n * Handle profile click\n */\n onProfileClick(): void {\n this.profileClick.emit();\n this.closeDropdown();\n }\n\n /**\n * Handle menu item click\n */\n onMenuItemClick(item: MenuItem): void {\n if (item.id === 'logout') {\n this.onLogoutClick();\n } else if (item.id === 'profile') {\n this.onProfileClick();\n }\n }\n}\n","<header\n class=\"lc-header\"\n [class.lc-header--dark]=\"theme() === 'dark'\"\n [class.lc-header--light]=\"theme() === 'light'\"\n [class.lc-header--size-sm]=\"size() === 'sm'\"\n [class.lc-header--size-md]=\"size() === 'md'\"\n [class.lc-header--size-lg]=\"size() === 'lg'\"\n [class.lc-header--size-xl]=\"size() === 'xl'\"\n [class.lc-header--has-nav]=\"navItems().length > 0\"\n [class.lc-header--static]=\"!sticky()\"\n [class.lc-header--transparent]=\"variant() === 'transparent'\"\n>\n <!-- Hamburger menu icon (mobile only) -->\n @if (showHamburger()) {\n <lc-button\n #hamburger\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"hamburgerAriaLabel()\"\n (clicked)=\"onHamburgerClick()\"\n class=\"lc-header__hamburger\"\n >\n <lc-icon name=\"bars-3\" size=\"sm\" />\n </lc-button>\n }\n\n <!-- Logo (clickable, navigates to home) -->\n <div class=\"lc-header__brand\">\n @if (showLogo()) {\n @if (homeHref()) {\n <!-- Plain link: works without the router and without JavaScript. -->\n <a [href]=\"homeHref()\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n } @else {\n <a routerLink=\"/\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n }\n }\n\n @if (title()) {\n <div class=\"lc-header__title-group\">\n @switch (titleTag()) {\n @case ('h1') {\n <h1 class=\"lc-header__title\">{{ title() }}</h1>\n }\n @case ('h2') {\n <h2 class=\"lc-header__title\">{{ title() }}</h2>\n }\n @case ('h3') {\n <h3 class=\"lc-header__title\">{{ title() }}</h3>\n }\n @case ('p') {\n <p class=\"lc-header__title\">{{ title() }}</p>\n }\n @case ('div') {\n <div class=\"lc-header__title\">{{ title() }}</div>\n }\n @default {\n <span class=\"lc-header__title\">{{ title() }}</span>\n }\n }\n @if (subtitle()) {\n <span class=\"lc-header__subtitle\" [attr.title]=\"subtitle()\">{{ subtitle() }}</span>\n }\n </div>\n }\n </div>\n\n <!-- Main navigation: inline from 1024 px, its own wrapping row below. -->\n @if (navItems().length > 0) {\n <nav class=\"lc-header__nav\" [attr.aria-label]=\"navAriaLabel()\">\n <ul class=\"lc-header__nav-list\">\n @for (item of navItems(); track $index) {\n <li class=\"lc-header__nav-item\">\n <a\n class=\"lc-header__nav-link\"\n [href]=\"item.href\"\n [attr.aria-current]=\"item.current ? 'page' : null\"\n >{{ item.label }}</a>\n </li>\n }\n </ul>\n </nav>\n }\n\n <div class=\"lc-header__spacer\"></div>\n\n <!-- End of the first row, e.g. a language link. -->\n <ng-content select=\"[slot='end']\" />\n\n <!-- Theme toggle button -->\n @if (showThemeButton()) {\n <lc-button\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"themeService.isDark() ? themeToLightAriaLabel() : themeToDarkAriaLabel()\"\n (clicked)=\"onThemeButtonClick()\"\n class=\"lc-header__theme-toggle\"\n >\n <lc-icon [name]=\"themeService.isDark() ? 'sun' : 'moon'\" size=\"sm\" />\n </lc-button>\n }\n\n <!-- Context info (e.g. tenant, organization, project) -->\n @if (contextName()) {\n <button\n type=\"button\"\n class=\"lc-header__context-info\"\n [attr.title]=\"contextName()\"\n [attr.aria-label]=\"contextAriaLabel()\"\n (click)=\"contextClick.emit()\"\n >\n @if (contextLabel()) {\n <span class=\"lc-header__context-label\">{{ contextLabel() }}</span>\n }\n <span class=\"lc-header__context-name\">{{ contextName() }}</span>\n </button>\n }\n\n <!-- User profile menu -->\n @if (showUserMenu()) {\n <lc-menu\n [items]=\"menuItems()\"\n [isOpen]=\"isDropdownOpen()\"\n position=\"bottom-right\"\n minWidth=\"min(220px, calc(100vw - 2rem))\"\n maxWidth=\"min(18rem, calc(100vw - 2rem))\"\n [size]=\"menuSize()\"\n (itemClick)=\"onMenuItemClick($event)\"\n (closed)=\"closeDropdown()\"\n >\n <!-- Menu header with avatar, name and email -->\n @if (userName() || userEmail()) {\n <div header class=\"lc-header__menu-header\">\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n size=\"md\"\n />\n <div class=\"lc-header__menu-user-info\">\n @if (userName()) {\n <div class=\"lc-header__menu-user-name\">{{ userName() }}</div>\n }\n @if (userEmail()) {\n <div class=\"lc-header__menu-user-email\">{{ userEmail() }}</div>\n }\n </div>\n </div>\n }\n\n @if (userMenuTrigger() === 'avatar') {\n <button\n trigger\n class=\"lc-header__profile-trigger lc-header__profile-trigger--avatar\"\n type=\"button\"\n [attr.aria-label]=\"userMenuAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n [decorative]=\"true\"\n size=\"md\"\n />\n </button>\n } @else {\n <button\n trigger\n class=\"lc-header__profile-trigger\"\n type=\"button\"\n [attr.aria-label]=\"userMenuAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-icon name=\"user\" size=\"sm\" />\n <lc-icon name=\"chevron-down\" size=\"xs\" />\n </button>\n }\n </lc-menu>\n }\n</header>\n\n<ng-template #brandLogo>\n <lc-logo\n [variant]=\"logo() ? 'full' : 'emblem'\"\n [size]=\"logoSize()\"\n [clickable]=\"false\"\n [colorMode]=\"theme() === 'dark' ? 'dark' : theme() === 'light' ? 'light' : 'auto'\"\n [src]=\"logoSrc()\"\n [emblemSrc]=\"logoEmblemSrc()\"\n [darkSrc]=\"logoDarkSrc()\"\n [darkEmblemSrc]=\"logoDarkEmblemSrc()\"\n [alt]=\"logoAlt() || title() || 'Logo'\"\n />\n</ng-template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-header.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/header/header.component.ts","../../../../libs/angular-ui-kit/src/lib/header/header.component.html"],"sourcesContent":["import {\n Component,\n ElementRef,\n Injector,\n input,\n output,\n signal,\n computed,\n inject,\n viewChild,\n afterRenderEffect,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { RouterModule } from '@angular/router';\nimport { ButtonComponent } from '@lifecorner/angular-ui-kit/button';\nimport { LogoComponent } from '@lifecorner/angular-ui-kit/logo';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_BARS_3, ICON_CHEVRON_DOWN, ICON_LOGOUT, ICON_MOON, ICON_SUN, ICON_USER } from '@lifecorner/angular-ui-kit/icons';\nimport { AvatarColor, AvatarComponent } from '@lifecorner/angular-ui-kit/avatar';\nimport { MenuComponent, MenuItem } from '@lifecorner/angular-ui-kit/menu';\nimport { ThemeService } from '@lifecorner/angular-ui-kit/theme';\n\n/** A link in the header's main navigation (`navItems`). */\nexport interface HeaderNavItem {\n /** Visible link text. */\n label: string;\n /** Plain URL — rendered as a native `href`, no router involved. */\n href: string;\n /** Marks the page the visitor is on (`aria-current=\"page\"` + underline). */\n current?: boolean;\n}\n\n/** Element used for the header title (`titleTag`). */\nexport type HeaderTitleTag = 'h1' | 'h2' | 'h3' | 'p' | 'span' | 'div';\n\n/**\n * Surface of the header: `default` is the bar on `--color-surface` with a\n * bottom border; `transparent` has no background and no border, for a header\n * that sits on the page (\"Weite\").\n */\nexport type HeaderVariant = 'default' | 'transparent';\n\n/**\n * What the account-menu button shows: `icon` (a user icon and a chevron) or\n * `avatar` (the person's initials avatar, `userName`, `userAvatarSrc`,\n * `userAvatarColor`, in a 48 px round button).\n */\nexport type HeaderUserMenuTrigger = 'icon' | 'avatar';\n\n/**\n * AppHeaderComponent - Global application header for the LifeCorner shell\n *\n * Features:\n * - Clickable logo for home navigation\n * - Optional title and subtitle display\n * - User profile dropdown with avatar, name, email, optional Profile link, and Logout\n * - Optional theme toggle button in header. By default the button toggles the\n * `ThemeService` itself and additionally emits `themeToggleClick`, so the\n * handler must NOT toggle again (that would undo the switch). To own the\n * toggling in the app, set `[autoToggleTheme]=\"false\"` and toggle in the\n * handler.\n * - Hamburger menu toggle for mobile sidebar; bind `sidenavOpen` (and\n * `sidenavId`) so the toggle exposes `aria-expanded` / `aria-controls`.\n * - OnPush change detection for performance\n *\n * Public, prerendered sites (no router, no JavaScript needed):\n * - `homeHref` makes the brand a plain link (instead of `routerLink=\"/\"`).\n * - `navItems` render a labelled main navigation (`<nav aria-label><ul>` with\n * `aria-current=\"page\"` on the current item); below 1024 px it moves to a\n * second row and wraps.\n * - `[slot='end']` takes content at the end of the first row (e.g. a language\n * link), `showUserMenu` hides the account menu, `titleTag` picks the title\n * element (the page keeps its own `<h1>`), `sticky` can be switched off.\n * App shell (\"Weite\", kit 3.3):\n * - `variant=\"transparent\"`: no background and no border, the header sits on\n * the page (pair it with `[sticky]=\"false\"`, a header without a surface\n * cannot stay over scrolling text).\n * - `userMenuTrigger=\"avatar\"`: the account button is the person's initials\n * avatar (`userAvatarColor` for the member colour, `userAvatarSrc` for a\n * photo) in a 48 px round button; the icon trigger is 44 px high in every\n * density.\n * - The subtitle (e.g. a household name) stays on one line and ends with \"…\";\n * the full text is its `title` and stays in the accessible text. It is shown\n * as typed (no uppercase).\n * - The account menu is at most `min(18rem, 100vw − 2rem)` wide; the name and\n * email in its header wrap instead of being cut.\n * - Every built-in label is an input (`homeAriaLabel`, `hamburgerAriaLabel`,\n * `userMenuAriaLabel`, `navAriaLabel`, `profileLabel`, `logoutLabel`,\n * `themeToDarkAriaLabel`, `themeToLightAriaLabel`, `contextAriaLabel`);\n * the defaults stay English.\n * - The `ThemeService` (which persists to localStorage) is only created when\n * the theme button is shown.\n *\n * @example\n * ```html\n * <lc-header\n * [logo]=\"'/assets/logo.svg'\"\n * [title]=\"'LifeCorner'\"\n * [subtitle]=\"'User Profile'\"\n * [userName]=\"'John Doe'\"\n * [userEmail]=\"'user@example.com'\"\n * [showHamburger]=\"true\"\n * [sidenavOpen]=\"sidenavOpen\"\n * sidenavId=\"app-sidenav\"\n * [showThemeButton]=\"true\"\n * [showProfileMenuItem]=\"true\"\n * (hamburgerClick)=\"toggleSidebar()\"\n * (themeToggleClick)=\"trackThemeToggle()\"\n * (profileClick)=\"navigateToProfile()\"\n * (logoutClick)=\"handleLogout()\"\n * />\n *\n * <!-- App-controlled theme: the header only reports the click -->\n * <lc-header\n * [showThemeButton]=\"true\"\n * [autoToggleTheme]=\"false\"\n * (themeToggleClick)=\"toggleTheme()\"\n * />\n *\n * <!-- Public site: plain links, labelled nav, language link at the end -->\n * <lc-header\n * size=\"sm\"\n * [sticky]=\"false\"\n * [showUserMenu]=\"false\"\n * homeHref=\"/de/\"\n * homeAriaLabel=\"Produkt – Startseite\"\n * navAriaLabel=\"Hauptnavigation\"\n * [navItems]=\"[\n * { label: 'Sicherheit', href: '/de/sicherheit', current: true },\n * { label: 'Roadmap', href: '/de/roadmap' }\n * ]\"\n * >\n * <a slot=\"end\" lcButton variant=\"ghost\" href=\"/en/security\" hreflang=\"en\" lang=\"en\">English</a>\n * </lc-header>\n * ```\n */\n@Component({\n selector: 'lc-header',\n standalone: true,\n imports: [\n NgTemplateOutlet,\n RouterModule,\n ButtonComponent,\n LogoComponent,\n IconComponent,\n AvatarComponent,\n MenuComponent,\n ],\n // Its own glyphs, and the profile menu's (lc-menu renders them in this view).\n viewProviders: [ɵprovideKitIcons([ICON_BARS_3, ICON_SUN, ICON_MOON, ICON_USER, ICON_CHEVRON_DOWN, ICON_LOGOUT])],\n templateUrl: './header.component.html',\n styleUrl: './header.component.scss',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'lc-header-host',\n },\n})\nexport class HeaderComponent {\n readonly theme = input<'light' | 'dark' | 'auto'>('auto');\n readonly logo = input('');\n /**\n * Render the brand block. On its own this shows the emblem; with `logo` set\n * it shows the full lockup. (It used to additionally require `logo` or\n * `title`, so `showLogo` alone rendered an empty 0px-wide brand area with no\n * error — an app could end up with no branding at all and no clue why.)\n */\n readonly showLogo = input(true);\n /** Custom URL for the full brand logo (forwarded to inner `<lc-logo>`). */\n readonly logoSrc = input('');\n /** Custom URL for the emblem-only brand logo. */\n readonly logoEmblemSrc = input('');\n /** Optional dark-theme URL for the full brand logo. */\n readonly logoDarkSrc = input('');\n /** Optional dark-theme URL for the emblem-only brand logo. */\n readonly logoDarkEmblemSrc = input('');\n /** Alt text for the brand logo (forwarded to inner `<lc-logo>`). */\n readonly logoAlt = input('');\n /** Size of the brand logo (forwarded to inner `<lc-logo>`). Defaults to `md`. */\n readonly logoSize = input<'xs' | 'sm' | 'md' | 'lg' | 'xl'>('md');\n /**\n * Overall header height. Useful to align the header with a sidebar brand block.\n * Maps to the same `min-height` scale the sidenav logo area uses:\n * `sm` 56px · `md` 64px (default) · `lg` 80px · `xl` 112px.\n */\n readonly size = input<'sm' | 'md' | 'lg' | 'xl'>('md');\n readonly title = input('');\n /**\n * Surface: `default` (the bar on `--color-surface` with a bottom border) or\n * `transparent` (no background, no border — the header sits on the page).\n */\n readonly variant = input<HeaderVariant>('default');\n /**\n * Element for the title. `h1` keeps the app-shell behaviour; on a site whose\n * pages carry their own `<h1>`, use `span` (or `p`/`div`).\n */\n readonly titleTag = input<HeaderTitleTag>('h1');\n /**\n * Second line under the title (e.g. the household name). One line, cut\n * with \"…\" when it does not fit; the full text is its `title` attribute.\n * Shown as typed.\n */\n readonly subtitle = input('');\n readonly userEmail = input('');\n readonly userName = input('');\n /**\n * What the account-menu button shows: `icon` (user icon and chevron) or\n * `avatar` (the initials of `userName` in a 48 px round button).\n */\n readonly userMenuTrigger = input<HeaderUserMenuTrigger>('icon');\n /** Photo for the account avatar (trigger and menu header); initials when empty or broken. */\n readonly userAvatarSrc = input('');\n /** Colour of the account avatar's initials: `default` or a member colour `member-1` … `member-6`. */\n readonly userAvatarColor = input<AvatarColor>('default');\n readonly showHamburger = input(false);\n /**\n * Open state of the sidenav the hamburger controls. When bound, the toggle\n * announces it via `aria-expanded`; leave `undefined` when the header does\n * not know (the attribute is then omitted rather than lying).\n */\n readonly sidenavOpen = input<boolean | undefined>(undefined);\n /** DOM id of the sidenav the hamburger controls (`aria-controls`). */\n readonly sidenavId = input('');\n readonly showThemeButton = input(false);\n /**\n * Whether the theme button toggles the `ThemeService` itself before emitting\n * `themeToggleClick`. Set to `false` when the app owns the theme switch and\n * toggles in the `(themeToggleClick)` handler — otherwise both would toggle\n * and the click would be a no-op.\n */\n readonly autoToggleTheme = input(true);\n readonly contextName = input('');\n readonly contextLabel = input('');\n readonly menuSize = input<'sm' | 'md' | 'lg'>('sm');\n readonly showProfileMenuItem = input(true);\n /** Render the account menu (avatar trigger with Profile/Logout). */\n readonly showUserMenu = input(true);\n /**\n * Plain URL for the brand link. When set, the brand is a native\n * `<a href>` — no router needed (static or prerendered sites). Empty keeps\n * `routerLink=\"/\"`.\n */\n readonly homeHref = input('');\n /**\n * Main navigation links, rendered as `<nav><ul><li><a href>` with\n * `aria-current=\"page\"` on the current one. On screens below 1024 px the\n * navigation takes a second row and wraps.\n */\n readonly navItems = input<readonly HeaderNavItem[]>([]);\n /** Keep the header at the top while scrolling (`position: sticky`). */\n readonly sticky = input(true);\n\n // Labels (defaults are English; translate them in the app).\n /** Accessible name of the brand link. */\n readonly homeAriaLabel = input('Go to home');\n /** Accessible name of the hamburger button. */\n readonly hamburgerAriaLabel = input('Toggle sidebar menu');\n /** Accessible name of the account menu trigger. */\n readonly userMenuAriaLabel = input('Open user menu');\n /** Accessible name of the `<nav>` around `navItems`. */\n readonly navAriaLabel = input('Main navigation');\n /** Label of the theme button while the light theme is active. */\n readonly themeToDarkAriaLabel = input('Switch to dark mode');\n /** Label of the theme button while the dark theme is active. */\n readonly themeToLightAriaLabel = input('Switch to light mode');\n /** Accessible name of the context button (`contextName`). */\n readonly contextAriaLabel = input('Context info');\n /** Label of the Profile entry in the account menu. */\n readonly profileLabel = input('Profile');\n /** Label of the Logout entry in the account menu. */\n readonly logoutLabel = input('Logout');\n\n readonly hamburgerClick = output<void>();\n readonly themeToggleClick = output<void>();\n readonly logoutClick = output<void>();\n readonly profileClick = output<void>();\n readonly contextClick = output<void>();\n\n private readonly injector = inject(Injector);\n private themeServiceInstance: ThemeService | null = null;\n\n /**\n * Resolved on first use, i.e. only when the theme button is shown: creating\n * the ThemeService reads and writes the theme class and localStorage, which a\n * site without a theme switch must not do.\n */\n protected get themeService(): ThemeService {\n return (this.themeServiceInstance ??= this.injector.get(ThemeService));\n }\n\n private readonly hamburger = viewChild('hamburger', { read: ElementRef<HTMLElement> });\n\n constructor() {\n // The hamburger is an <lc-button>; the ARIA state belongs on its native\n // <button> (the element that has the button role), not on the custom\n // element host — so it is reflected after render rather than bound in the\n // template.\n afterRenderEffect(() => {\n const button = this.hamburger()?.nativeElement.querySelector('button');\n if (!button) return;\n const open = this.sidenavOpen();\n const controls = this.sidenavId();\n if (open === undefined) {\n button.removeAttribute('aria-expanded');\n } else {\n button.setAttribute('aria-expanded', String(open));\n }\n if (controls) {\n button.setAttribute('aria-controls', controls);\n } else {\n button.removeAttribute('aria-controls');\n }\n });\n }\n\n /**\n * Get menu items for profile dropdown\n */\n protected readonly menuItems = computed<MenuItem[]>(() => {\n const items: MenuItem[] = [];\n\n // Add profile link if enabled\n if (this.showProfileMenuItem()) {\n items.push({\n id: 'profile',\n label: this.profileLabel(),\n icon: 'user',\n dividerAfter: true,\n });\n }\n\n // Add logout\n items.push({\n id: 'logout',\n label: this.logoutLabel(),\n icon: 'arrow-right-start-on-rectangle',\n variant: 'danger',\n });\n\n return items;\n });\n\n /**\n * Dropdown open state (using Angular signals)\n */\n private readonly dropdownOpen = signal<boolean>(false);\n\n /**\n * Get dropdown open state\n */\n isDropdownOpen(): boolean {\n return this.dropdownOpen();\n }\n\n /**\n * Toggle profile dropdown visibility\n */\n toggleDropdown(): void {\n this.dropdownOpen.set(!this.dropdownOpen());\n }\n\n /**\n * Close profile dropdown\n */\n closeDropdown(): void {\n this.dropdownOpen.set(false);\n }\n\n /**\n * Handle hamburger click\n */\n onHamburgerClick(): void {\n this.hamburgerClick.emit();\n }\n\n /**\n * Handle theme button click (separate button, not in menu). Toggles the\n * theme unless the app opted out via `autoToggleTheme`, then emits.\n */\n onThemeButtonClick(): void {\n if (this.autoToggleTheme()) {\n this.themeService.toggleTheme();\n }\n this.themeToggleClick.emit();\n }\n\n /**\n * Handle logout click\n */\n onLogoutClick(): void {\n this.logoutClick.emit();\n this.closeDropdown();\n }\n\n /**\n * Handle profile click\n */\n onProfileClick(): void {\n this.profileClick.emit();\n this.closeDropdown();\n }\n\n /**\n * Handle menu item click\n */\n onMenuItemClick(item: MenuItem): void {\n if (item.id === 'logout') {\n this.onLogoutClick();\n } else if (item.id === 'profile') {\n this.onProfileClick();\n }\n }\n}\n","<header\n class=\"lc-header\"\n [class.lc-header--dark]=\"theme() === 'dark'\"\n [class.lc-header--light]=\"theme() === 'light'\"\n [class.lc-header--size-sm]=\"size() === 'sm'\"\n [class.lc-header--size-md]=\"size() === 'md'\"\n [class.lc-header--size-lg]=\"size() === 'lg'\"\n [class.lc-header--size-xl]=\"size() === 'xl'\"\n [class.lc-header--has-nav]=\"navItems().length > 0\"\n [class.lc-header--static]=\"!sticky()\"\n [class.lc-header--transparent]=\"variant() === 'transparent'\"\n>\n <!-- Hamburger menu icon (mobile only) -->\n @if (showHamburger()) {\n <lc-button\n #hamburger\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"hamburgerAriaLabel()\"\n (clicked)=\"onHamburgerClick()\"\n class=\"lc-header__hamburger\"\n >\n <lc-icon name=\"bars-3\" size=\"sm\" />\n </lc-button>\n }\n\n <!-- Logo (clickable, navigates to home) -->\n <div class=\"lc-header__brand\">\n @if (showLogo()) {\n @if (homeHref()) {\n <!-- Plain link: works without the router and without JavaScript. -->\n <a [href]=\"homeHref()\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n } @else {\n <a routerLink=\"/\" class=\"lc-header__logo\" [attr.aria-label]=\"homeAriaLabel()\">\n <ng-container [ngTemplateOutlet]=\"brandLogo\" />\n </a>\n }\n }\n\n @if (title()) {\n <div class=\"lc-header__title-group\">\n @switch (titleTag()) {\n @case ('h1') {\n <h1 class=\"lc-header__title\">{{ title() }}</h1>\n }\n @case ('h2') {\n <h2 class=\"lc-header__title\">{{ title() }}</h2>\n }\n @case ('h3') {\n <h3 class=\"lc-header__title\">{{ title() }}</h3>\n }\n @case ('p') {\n <p class=\"lc-header__title\">{{ title() }}</p>\n }\n @case ('div') {\n <div class=\"lc-header__title\">{{ title() }}</div>\n }\n @default {\n <span class=\"lc-header__title\">{{ title() }}</span>\n }\n }\n @if (subtitle()) {\n <span class=\"lc-header__subtitle\" [attr.title]=\"subtitle()\">{{ subtitle() }}</span>\n }\n </div>\n }\n </div>\n\n <!-- Main navigation: inline from 1024 px, its own wrapping row below. -->\n @if (navItems().length > 0) {\n <nav class=\"lc-header__nav\" [attr.aria-label]=\"navAriaLabel()\">\n <ul class=\"lc-header__nav-list\">\n @for (item of navItems(); track $index) {\n <li class=\"lc-header__nav-item\">\n <a\n class=\"lc-header__nav-link\"\n [href]=\"item.href\"\n [attr.aria-current]=\"item.current ? 'page' : null\"\n >{{ item.label }}</a>\n </li>\n }\n </ul>\n </nav>\n }\n\n <div class=\"lc-header__spacer\"></div>\n\n <!-- End of the first row, e.g. a language link. -->\n <ng-content select=\"[slot='end']\" />\n\n <!-- Theme toggle button -->\n @if (showThemeButton()) {\n <lc-button\n variant=\"ghost\"\n size=\"sm\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"themeService.isDark() ? themeToLightAriaLabel() : themeToDarkAriaLabel()\"\n (clicked)=\"onThemeButtonClick()\"\n class=\"lc-header__theme-toggle\"\n >\n <lc-icon [name]=\"themeService.isDark() ? 'sun' : 'moon'\" size=\"sm\" />\n </lc-button>\n }\n\n <!-- Context info (e.g. tenant, organization, project) -->\n @if (contextName()) {\n <button\n type=\"button\"\n class=\"lc-header__context-info\"\n [attr.title]=\"contextName()\"\n [attr.aria-label]=\"contextAriaLabel()\"\n (click)=\"contextClick.emit()\"\n >\n @if (contextLabel()) {\n <span class=\"lc-header__context-label\">{{ contextLabel() }}</span>\n }\n <span class=\"lc-header__context-name\">{{ contextName() }}</span>\n </button>\n }\n\n <!-- User profile menu -->\n @if (showUserMenu()) {\n <lc-menu\n [items]=\"menuItems()\"\n [isOpen]=\"isDropdownOpen()\"\n position=\"bottom-right\"\n minWidth=\"min(220px, calc(100vw - 2rem))\"\n maxWidth=\"min(18rem, calc(100vw - 2rem))\"\n [size]=\"menuSize()\"\n (itemClick)=\"onMenuItemClick($event)\"\n (closed)=\"closeDropdown()\"\n >\n <!-- Menu header with avatar, name and email -->\n @if (userName() || userEmail()) {\n <div header class=\"lc-header__menu-header\">\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n size=\"md\"\n />\n <div class=\"lc-header__menu-user-info\">\n @if (userName()) {\n <div class=\"lc-header__menu-user-name\">{{ userName() }}</div>\n }\n @if (userEmail()) {\n <div class=\"lc-header__menu-user-email\">{{ userEmail() }}</div>\n }\n </div>\n </div>\n }\n\n @if (userMenuTrigger() === 'avatar') {\n <button\n trigger\n class=\"lc-header__profile-trigger lc-header__profile-trigger--avatar\"\n type=\"button\"\n [attr.aria-label]=\"userMenuAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-avatar\n [name]=\"userName()\"\n [src]=\"userAvatarSrc() || undefined\"\n [color]=\"userAvatarColor()\"\n [decorative]=\"true\"\n size=\"md\"\n />\n </button>\n } @else {\n <button\n trigger\n class=\"lc-header__profile-trigger\"\n type=\"button\"\n [attr.aria-label]=\"userMenuAriaLabel()\"\n [attr.aria-expanded]=\"isDropdownOpen()\"\n (click)=\"toggleDropdown()\"\n >\n <lc-icon name=\"user\" size=\"sm\" />\n <lc-icon name=\"chevron-down\" size=\"xs\" />\n </button>\n }\n </lc-menu>\n }\n</header>\n\n<ng-template #brandLogo>\n <lc-logo\n [variant]=\"logo() ? 'full' : 'emblem'\"\n [size]=\"logoSize()\"\n [clickable]=\"false\"\n [colorMode]=\"theme() === 'dark' ? 'dark' : theme() === 'light' ? 'light' : 'auto'\"\n [src]=\"logoSrc()\"\n [emblemSrc]=\"logoEmblemSrc()\"\n [darkSrc]=\"logoDarkSrc()\"\n [darkEmblemSrc]=\"logoDarkEmblemSrc()\"\n [alt]=\"logoAlt() || title() || 'Logo'\"\n />\n</ng-template>\n"],"mappings":"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"}
@@ -214,7 +214,8 @@ var ListComponent = class ListComponent {
214
214
  "type",
215
215
  "title",
216
216
  "disabledReason",
217
- "inline"
217
+ "inline",
218
+ "flush"
218
219
  ],
219
220
  outputs: [
220
221
  "clicked",
@@ -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 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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"}
@@ -215,7 +215,8 @@ var NextStepCardComponent = class NextStepCardComponent {
215
215
  "type",
216
216
  "title",
217
217
  "disabledReason",
218
- "inline"
218
+ "inline",
219
+ "flush"
219
220
  ],
220
221
  outputs: [
221
222
  "clicked",