@tekus/design-system 5.35.0 → 5.36.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.
@@ -1 +1 @@
1
- {"version":3,"file":"tekus-design-system-components-modal.mjs","sources":["../../../projects/design-system/components/modal/src/modal.component.ts","../../../projects/design-system/components/modal/src/modal.component.html","../../../projects/design-system/components/modal/src/services/modal.service.ts","../../../projects/design-system/components/modal/tekus-design-system-components-modal.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n input,\n output,\n Type,\n ElementRef,\n model,\n viewChild,\n ViewContainerRef,\n ComponentRef,\n effect,\n OnDestroy,\n untracked,\n afterEveryRender,\n inject,\n Injector,\n} from '@angular/core';\nimport { ButtonComponent } from '@tekus/design-system/components/button';\nimport { DialogModule } from 'primeng/dialog';\nimport { ModalFooterButton, ModalSizeType } from './modal.types';\nimport {\n TkCanClose,\n TkCloseInterceptor,\n TkDialogRef,\n} from '@tekus/design-system/core/types';\nimport { Observable, isObservable } from 'rxjs';\nimport { take } from 'rxjs/operators';\n\n/**\n * @component ModalComponent\n * @description\n * A programmatically controlled modal dialog used for displaying dynamic content.\n * Modernized for Angular 19 with 100% synchronous Signal-based closing interception.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'tk-modal',\n imports: [DialogModule, ButtonComponent],\n templateUrl: './modal.component.html',\n styleUrl: './modal.component.scss',\n})\nexport class ModalComponent<T = unknown> implements OnDestroy {\n private readonly elementRef = inject(ElementRef);\n private readonly injector = inject(Injector);\n\n private readonly contentHost = viewChild('contentHost', {\n read: ViewContainerRef,\n });\n private componentRef?: ComponentRef<T>;\n\n /** The dialog ref associated with this modal */\n dialogRef = input<TkDialogRef<ModalComponent<T>, unknown> | null>(null);\n\n /** The title displayed at the top of the modal */\n title = input<string>('');\n\n /** The main content of the modal. Can be a string or a Component Type. */\n content = input<string | Type<T> | null>(null);\n\n /** Array of footer buttons with label, callback, and return value */\n footerButtons = model<ModalFooterButton[]>([]);\n\n /** Modal size: 'small', 'large', 'medium' or 'full' */\n size = input<ModalSizeType>('small');\n\n /** Whether the modal can be closed by the user via close button */\n closable = input<boolean>(true);\n\n /** Whether clicking outside the modal mask closes the modal */\n closeOnOutsideClick = input<boolean>(false);\n\n /**\n * Optional data to be passed as inputs to the dynamic component.\n */\n data = input<Partial<T>>({});\n\n /**\n * Optional interceptor called before the modal closes.\n * MUST be synchronous. Returns true to allow closing.\n */\n interceptor = input<TkCloseInterceptor | undefined>(undefined);\n\n /** Computed: whether the content is a simple string */\n isContentString = computed(() => typeof this.content() === 'string');\n\n /** Computed: whether the modal has footer buttons to display */\n hasFooter = computed(() => (this.footerButtons() ?? []).length > 0);\n\n /** Whether the modal should be responsive on mobile screens */\n responsive = input<boolean>(true);\n\n /** Visibility flag as Model Signal (allows two-way binding) */\n isOpened = model<boolean>(false);\n\n /** Whether the modal content has a scrollbar */\n hasScroll = false;\n\n // --- Internals ---\n /** Emits when the modal closes, passing the return value from footer buttons or null */\n readonly closed = output<unknown>();\n private alreadyEmitted = false;\n private returnValueOnClose: unknown = null;\n\n constructor() {\n /**\n * @summary Orchestrates the reactive dynamic lifecycle.\n */\n\n effect(() => {\n const opened = this.isOpened();\n const host = this.contentHost();\n this.dialogRef(); // Track it to re-run if it's set later\n\n untracked(() => {\n if (opened && host) {\n this.attachDynamicContent();\n } else if (!opened) {\n this.detachDynamicContent();\n }\n });\n });\n\n effect(() => {\n const currentData = this.data();\n untracked(() => this.syncDynamicInputs(currentData));\n });\n\n afterEveryRender(() => {\n this.checkScroll();\n });\n }\n\n /** Computed: calculates modal max-width based on `size` */\n modalMaxWidth = computed(() => {\n switch (this.size()) {\n case 'large':\n return '67.5rem';\n case 'medium':\n return '35rem';\n case 'full':\n return '98vw';\n default:\n return '28.125rem';\n }\n });\n\n ngOnDestroy(): void {\n this.detachDynamicContent();\n }\n\n /**\n * @summary Orchestrates dynamic rendering and destruction based on visibility.\n * @private\n */\n private attachDynamicContent(): void {\n const type = this.content();\n const host = this.contentHost();\n\n if (!type || typeof type === 'string' || !host) return;\n this.detachDynamicContent();\n\n const customInjector = Injector.create({\n providers: [{ provide: TkDialogRef, useValue: this.dialogRef() }],\n parent: this.injector,\n });\n\n this.componentRef = host.createComponent(type, {\n injector: customInjector,\n });\n this.syncDynamicInputs(this.data());\n }\n\n /**\n * @summary Synchronizes incoming data record with the dynamic instance @Inputs.\n * @private\n */\n private syncDynamicInputs(data: Partial<T>): void {\n if (!this.componentRef) return;\n Object.entries(data).forEach(([key, value]) => {\n this.componentRef?.setInput(key, value);\n });\n }\n\n /**\n * @summary Safely destroys the dynamic component and clears references.\n * @private\n */\n private detachDynamicContent(): void {\n if (this.componentRef) {\n this.componentRef.destroy();\n this.componentRef = undefined;\n }\n }\n\n /**\n * Checks if the modal content has a scrollbar and updates `hasScroll` state.\n */\n checkScroll(): void {\n const contentEl =\n this.elementRef.nativeElement.querySelector('.p-dialog-content');\n if (contentEl) {\n this.hasScroll = contentEl.scrollHeight > contentEl.clientHeight;\n }\n }\n\n private wasOpened = false;\n\n /**\n * Opens the modal dialog.\n */\n open(): void {\n this.wasOpened = true;\n this.isOpened.set(true);\n this.resetClosureState();\n }\n\n /**\n * @summary Main entry point for closure requests.\n * Supports synchronous and asynchronous (Promise/Observable) evaluations.\n * @param returnValue (Optional) Value to emit on close.\n */\n tryClose(returnValue: unknown = null): void {\n const hasReturnValue = arguments.length > 0;\n const instance = this.componentRef?.instance as TkCanClose | undefined;\n const canCloseFn = instance?.canClose ? instance.canClose() : true;\n\n this.evaluateCanClose(canCloseFn, (canCloseInstance) => {\n if (!canCloseInstance) {\n instance?.onBlockedClose?.();\n return;\n }\n\n const configInterceptor = this.interceptor();\n if (configInterceptor) {\n const interceptorResult = configInterceptor();\n this.evaluateCanClose(interceptorResult, (canCloseInterceptor) => {\n if (canCloseInterceptor) {\n this.executeClosure(returnValue, hasReturnValue);\n } else {\n instance?.onBlockedClose?.();\n }\n });\n } else {\n this.executeClosure(returnValue, hasReturnValue);\n }\n });\n }\n\n /**\n * Evaluates a boolean, Promise or Observable to check if closing is allowed.\n */\n private evaluateCanClose(\n result: boolean | Promise<boolean> | Observable<boolean>,\n callback: (canClose: boolean) => void\n ): void {\n if (isObservable(result)) {\n result.pipe(take(1)).subscribe({\n next: (res) => callback(res),\n error: () => callback(false),\n });\n } else if (result instanceof Promise) {\n result.then(\n (res) => callback(res),\n () => callback(false)\n );\n } else {\n callback(result);\n }\n }\n\n /**\n * Resolves a static or functional property of a button.\n */\n resolveProperty<R>(prop: R | (() => R) | undefined): R | undefined {\n if (typeof prop === 'function') {\n return (prop as () => R)();\n }\n return prop;\n }\n\n /**\n * @summary Unified logic to execute the final closure state change.\n * @private\n */\n private executeClosure(returnValue: unknown, hasReturnValue: boolean): void {\n if (hasReturnValue) {\n this.alreadyEmitted = true;\n this.returnValueOnClose = returnValue;\n }\n this.isOpened.set(false);\n }\n\n /**\n * @summary Handles external visibility changes (from p-dialog 'X' or Escape).\n * Ensures the reactive guard is respected before allowing closure.\n */\n onVisibleChange(visible: boolean): void {\n if (!visible) {\n this.tryClose();\n }\n }\n\n /**\n * Handles the close event from the underlying dialog component.\n */\n handleClose(): void {\n if (!this.wasOpened || this.isOpened()) {\n return;\n }\n const valueToEmit = this.alreadyEmitted ? this.returnValueOnClose : null;\n this.closed.emit(valueToEmit);\n this.resetClosureState();\n this.wasOpened = false;\n }\n\n /**\n * @summary Handles actions triggered by footer buttons.\n */\n handleAction(\n action: (() => void) | undefined,\n returnValue: unknown,\n preventClose = false\n ): void {\n if (action) action();\n if (!preventClose) {\n this.tryClose(returnValue);\n }\n }\n\n /**\n * @summary Safely closes the modal, optionally passing a return value.\n * @param returnValue Value to emit when closing.\n */\n close(returnValue: unknown = null): void {\n this.tryClose(returnValue);\n }\n\n /**\n * @private\n * Encapsulates state cleanup to avoid repetitive assignments\n */\n private resetClosureState(): void {\n this.alreadyEmitted = false;\n this.returnValueOnClose = null;\n }\n}\n","<p-dialog\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"onVisibleChange($event)\"\n [closable]=\"closable()\"\n [dismissableMask]=\"closeOnOutsideClick()\"\n [draggable]=\"false\"\n [focusOnShow]=\"false\"\n [header]=\"title()\"\n [style]=\"{\n 'max-width': modalMaxWidth(),\n width: 'calc(100% - var(--tk-spacing-base-200))',\n }\"\n (onHide)=\"handleClose()\"\n (onShow)=\"checkScroll()\"\n [styleClass]=\"hasFooter() ? 'tk-modal--has-footer' : 'tk-modal--no-footer'\"\n class=\"tk-modal\">\n @if (title()) {\n <ng-template pTemplate=\"header\">\n <span class=\"p-dialog-title\">{{ title() }}</span>\n </ng-template>\n }\n <section class=\"tk-modal__content\">\n @if (content()) {\n @if (isContentString()) {\n <p [innerHTML]=\"content()\"></p>\n } @else {\n <ng-template #contentHost></ng-template>\n }\n }\n </section>\n\n <ng-template pTemplate=\"footer\">\n @if (hasFooter()) {\n <section\n class=\"tk-modal__footer\"\n [class.tk-modal__footer--with-content]=\"hasScroll\">\n @for (btn of footerButtons()!; track $index) {\n <tk-button\n [label]=\"resolveProperty(btn.label)!\"\n [severity]=\"btn.severity\"\n [variant]=\"btn.variant\"\n [disabled]=\"resolveProperty(btn.disabled) ?? false\"\n (clicked)=\"handleAction(btn.action, btn.returnValue, btn.preventClose)\"\n (keydown.enter)=\"handleAction(btn.action, btn.returnValue, btn.preventClose)\"\n (keydown.space)=\"handleAction(btn.action, btn.returnValue, btn.preventClose)\" />\n }\n </section>\n }\n </ng-template>\n</p-dialog>\n","import { Injectable, ApplicationRef, ComponentRef, createComponent, EmbeddedViewRef, inject } from '@angular/core';\nimport { ModalComponent } from '../modal.component';\nimport { ModalConfig } from '../modal.types';\nimport { TkDialogRef } from '@tekus/design-system/core/types';\n\n/**\n * @service ModalService\n * @description\n * Service responsible for programmatically opening and managing modal dialogs.\n * It handles component creation, attachment to the document body, and cleanup.\n */\n@Injectable({ providedIn: 'root' })\nexport class ModalService {\n private readonly appRef = inject(ApplicationRef);\n\n /** Reference to the currently open modal dialog ref */\n private dialogRef: TkDialogRef<ModalComponent> | null = null;\n\n /** Internal getter for testing purposes */\n get modalRefForTesting(): ComponentRef<ModalComponent> | null {\n return this.dialogRef?.componentRef || null;\n }\n /** Internal setter for testing purposes */\n set modalRefForTesting(ref: ComponentRef<ModalComponent> | null) {\n this.dialogRef = ref ? new TkDialogRef(ref) : null;\n }\n\n /**\n * Opens a modal dialog with the provided configuration.\n * Only one modal can be open at a time.\n * @param config Configuration object for the modal (title, content, buttons, etc.)\n * @returns A TkDialogRef for the opened modal.\n */\n open<T = unknown, R = unknown>(config: ModalConfig): TkDialogRef<ModalComponent<T>, R> {\n if (this.dialogRef) {\n return this.dialogRef as unknown as TkDialogRef<ModalComponent<T>, R>;\n }\n\n const componentRef = createComponent(ModalComponent, {\n environmentInjector: this.appRef.injector,\n }) as ComponentRef<ModalComponent<T>>;\n\n this.appRef.attachView(componentRef.hostView);\n\n const domElem = (componentRef.hostView as EmbeddedViewRef<unknown>).rootNodes[0] as HTMLElement;\n document.body.appendChild(domElem);\n\n const dialogRef = new TkDialogRef<ModalComponent<T>, R>(componentRef);\n this.dialogRef = dialogRef as unknown as TkDialogRef<ModalComponent>;\n\n componentRef.setInput('title', config.title);\n componentRef.setInput('content', config.content);\n componentRef.setInput('footerButtons', config.footerButtons || []);\n componentRef.setInput('size', config.size || 'small');\n componentRef.setInput('closable', config.closable ?? true);\n componentRef.setInput('closeOnOutsideClick', config.closeOnOutsideClick ?? false);\n componentRef.setInput('interceptor', config.interceptor);\n componentRef.setInput('data', config.data || {});\n componentRef.setInput('dialogRef', dialogRef);\n\n componentRef.instance.closed.subscribe((value: unknown) => {\n dialogRef.emitClose(value as R);\n this.appRef.detachView(componentRef.hostView);\n componentRef.destroy();\n this.dialogRef = null;\n });\n\n componentRef.instance.open();\n\n return dialogRef;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tekus-design-system-components-modal.mjs","sources":["../../../projects/design-system/components/modal/src/modal.component.ts","../../../projects/design-system/components/modal/src/modal.component.html","../../../projects/design-system/components/modal/src/services/modal.service.ts","../../../projects/design-system/components/modal/tekus-design-system-components-modal.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n input,\n output,\n Type,\n ElementRef,\n model,\n viewChild,\n ViewContainerRef,\n ComponentRef,\n effect,\n OnDestroy,\n untracked,\n afterEveryRender,\n inject,\n Injector,\n} from '@angular/core';\nimport { ButtonComponent } from '@tekus/design-system/components/button';\nimport { DialogModule } from 'primeng/dialog';\nimport { ModalFooterButton, ModalSizeType } from './modal.types';\nimport {\n TkCanClose,\n TkCloseInterceptor,\n TkDialogRef,\n} from '@tekus/design-system/core/types';\nimport { Observable, isObservable } from 'rxjs';\nimport { take } from 'rxjs/operators';\n\n/**\n * @component ModalComponent\n * @description\n * A programmatically controlled modal dialog used for displaying dynamic content.\n * Modernized for Angular 19 with 100% synchronous Signal-based closing interception.\n */\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'tk-modal',\n imports: [DialogModule, ButtonComponent],\n templateUrl: './modal.component.html',\n styleUrl: './modal.component.scss',\n})\nexport class ModalComponent<T = unknown> implements OnDestroy {\n private readonly elementRef = inject(ElementRef);\n private readonly injector = inject(Injector);\n\n private readonly contentHost = viewChild('contentHost', {\n read: ViewContainerRef,\n });\n private componentRef?: ComponentRef<T>;\n\n /** The dialog ref associated with this modal */\n readonly dialogRef = input<TkDialogRef<ModalComponent<T>, unknown> | null>(null);\n\n /** The title displayed at the top of the modal */\n readonly title = input<string>('');\n\n /** The main content of the modal. Can be a string or a Component Type. */\n readonly content = input<string | Type<T> | null>(null);\n\n /** Array of footer buttons with label, callback, and return value */\n readonly footerButtons = model<ModalFooterButton[]>([]);\n\n /** Modal size: 'small', 'large', 'medium' or 'full' */\n readonly size = input<ModalSizeType>('small');\n\n /** Whether the modal can be closed by the user via close button */\n readonly closable = input<boolean>(true);\n\n /** Whether clicking outside the modal mask closes the modal */\n readonly closeOnOutsideClick = input<boolean>(false);\n\n /**\n * Optional data to be passed as inputs to the dynamic component.\n */\n data = input<Partial<T>>({});\n\n /**\n * Optional interceptor called before the modal closes.\n * MUST be synchronous. Returns true to allow closing.\n */\n readonly interceptor = input<TkCloseInterceptor | undefined>(undefined);\n\n /** Computed: whether the content is a simple string */\n readonly isContentString = computed(() => typeof this.content() === 'string');\n\n /** Computed: whether the modal has footer buttons to display */\n readonly hasFooter = computed(() => (this.footerButtons() ?? []).length > 0);\n\n /** Whether the modal should be responsive on mobile screens */\n readonly responsive = input<boolean>(true);\n\n /** Visibility flag as Model Signal (allows two-way binding) */\n readonly isOpened = model<boolean>(false);\n\n /** Whether the modal content has a scrollbar */\n hasScroll = false;\n\n // --- Internals ---\n /** Emits when the modal closes, passing the return value from footer buttons or null */\n readonly closed = output<unknown>();\n private alreadyEmitted = false;\n private returnValueOnClose: unknown = null;\n\n constructor() {\n this.registerContentLifecycleEffect();\n this.registerDataSyncEffect();\n afterEveryRender(() => this.checkScroll());\n }\n\n /**\n * @summary Orchestrates the reactive dynamic lifecycle.\n * @private\n */\n private registerContentLifecycleEffect(): void {\n effect(() => {\n const opened = this.isOpened();\n const host = this.contentHost();\n this.dialogRef(); // Track it to re-run if it's set later\n\n untracked(() => {\n if (opened && host) {\n this.attachDynamicContent();\n } else if (!opened) {\n this.detachDynamicContent();\n }\n });\n });\n }\n\n /**\n * @private\n */\n private registerDataSyncEffect(): void {\n effect(() => {\n const currentData = this.data();\n untracked(() => this.syncDynamicInputs(currentData));\n });\n }\n\n /** Computed: calculates modal max-width based on `size` */\n modalMaxWidth = computed(() => {\n switch (this.size()) {\n case 'large':\n return '67.5rem';\n case 'medium':\n return '35rem';\n case 'full':\n return '98vw';\n default:\n return '28.125rem';\n }\n });\n\n ngOnDestroy(): void {\n this.detachDynamicContent();\n }\n\n /**\n * @summary Orchestrates dynamic rendering and destruction based on visibility.\n * @private\n */\n private attachDynamicContent(): void {\n const type = this.content();\n const host = this.contentHost();\n\n if (!type || typeof type === 'string' || !host) {\n return;\n }\n this.detachDynamicContent();\n\n this.componentRef = host.createComponent(type, {\n injector: this.createContentInjector(),\n });\n this.syncDynamicInputs(this.data());\n }\n\n /**\n * @private\n */\n private createContentInjector(): Injector {\n return Injector.create({\n providers: [{ provide: TkDialogRef, useValue: this.dialogRef() }],\n parent: this.injector,\n });\n }\n\n /**\n * @summary Synchronizes incoming data record with the dynamic instance @Inputs.\n * @private\n */\n private syncDynamicInputs(data: Partial<T>): void {\n if (!this.componentRef) {\n return;\n }\n Object.entries(data).forEach(([key, value]) => {\n this.componentRef?.setInput(key, value);\n });\n }\n\n /**\n * @summary Safely destroys the dynamic component and clears references.\n * @private\n */\n private detachDynamicContent(): void {\n if (this.componentRef) {\n this.componentRef.destroy();\n this.componentRef = undefined;\n }\n }\n\n /**\n * Checks if the modal content has a scrollbar and updates `hasScroll` state.\n */\n checkScroll(): void {\n const contentEl =\n this.elementRef.nativeElement.querySelector('.p-dialog-content');\n if (contentEl) {\n this.hasScroll = contentEl.scrollHeight > contentEl.clientHeight;\n }\n }\n\n private wasOpened = false;\n\n /**\n * Opens the modal dialog.\n */\n open(): void {\n this.wasOpened = true;\n this.isOpened.set(true);\n this.resetClosureState();\n }\n\n /**\n * @summary Main entry point for closure requests.\n * Supports synchronous and asynchronous (Promise/Observable) evaluations.\n * @param returnValue (Optional) Value to emit on close.\n */\n tryClose(returnValue: unknown = null): void {\n const hasReturnValue = arguments.length > 0;\n const instance = this.componentRef?.instance as TkCanClose | undefined;\n const canCloseFn = instance?.canClose ? instance.canClose() : true;\n\n this.evaluateCanClose(canCloseFn, (canCloseInstance) => {\n if (!canCloseInstance) {\n instance?.onBlockedClose?.();\n return;\n }\n this.resolveInterceptorAndClose(instance, returnValue, hasReturnValue);\n });\n }\n\n /**\n * @summary Evaluates the optional close interceptor, then executes closure.\n * @private\n */\n private resolveInterceptorAndClose(\n instance: TkCanClose | undefined,\n returnValue: unknown,\n hasReturnValue: boolean\n ): void {\n const configInterceptor = this.interceptor();\n if (!configInterceptor) {\n this.executeClosure(returnValue, hasReturnValue);\n return;\n }\n\n this.evaluateCanClose(configInterceptor(), (canCloseInterceptor) => {\n if (!canCloseInterceptor) {\n instance?.onBlockedClose?.();\n return;\n }\n this.executeClosure(returnValue, hasReturnValue);\n });\n }\n\n /**\n * Evaluates a boolean, Promise or Observable to check if closing is allowed.\n */\n private evaluateCanClose(\n result: boolean | Promise<boolean> | Observable<boolean>,\n callback: (canClose: boolean) => void\n ): void {\n if (isObservable(result)) {\n result.pipe(take(1)).subscribe({\n next: (res) => callback(res),\n error: () => callback(false),\n });\n } else if (result instanceof Promise) {\n result.then(\n (res) => callback(res),\n () => callback(false)\n );\n } else {\n callback(result);\n }\n }\n\n /**\n * Resolves a static or functional property of a button.\n */\n resolveProperty<R>(prop: R | (() => R) | undefined): R | undefined {\n if (typeof prop === 'function') {\n return (prop as () => R)();\n }\n return prop;\n }\n\n /**\n * @summary Unified logic to execute the final closure state change.\n * @private\n */\n private executeClosure(returnValue: unknown, hasReturnValue: boolean): void {\n if (hasReturnValue) {\n this.alreadyEmitted = true;\n this.returnValueOnClose = returnValue;\n }\n this.isOpened.set(false);\n }\n\n /**\n * @summary Handles external visibility changes (from p-dialog 'X' or Escape).\n * Ensures the reactive guard is respected before allowing closure.\n */\n onVisibleChange(visible: boolean): void {\n if (!visible) {\n this.tryClose();\n }\n }\n\n /**\n * Handles the close event from the underlying dialog component.\n */\n handleClose(): void {\n if (!this.wasOpened || this.isOpened()) {\n return;\n }\n const valueToEmit = this.alreadyEmitted ? this.returnValueOnClose : null;\n this.closed.emit(valueToEmit);\n this.resetClosureState();\n this.wasOpened = false;\n }\n\n /**\n * @summary Handles actions triggered by footer buttons.\n */\n handleAction(\n action: (() => void) | undefined,\n returnValue: unknown,\n preventClose = false\n ): void {\n if (action) {\n action();\n }\n if (!preventClose) {\n this.tryClose(returnValue);\n }\n }\n\n /**\n * @summary Safely closes the modal, optionally passing a return value.\n * @param returnValue Value to emit when closing.\n */\n close(returnValue: unknown = null): void {\n this.tryClose(returnValue);\n }\n\n /**\n * @private\n * Encapsulates state cleanup to avoid repetitive assignments\n */\n private resetClosureState(): void {\n this.alreadyEmitted = false;\n this.returnValueOnClose = null;\n }\n}\n","<p-dialog\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"onVisibleChange($event)\"\n [closable]=\"closable()\"\n [dismissableMask]=\"closeOnOutsideClick()\"\n [draggable]=\"false\"\n [focusOnShow]=\"false\"\n [header]=\"title()\"\n [style]=\"{\n 'max-width': modalMaxWidth(),\n width: 'calc(100% - var(--tk-spacing-base-200))',\n }\"\n (onHide)=\"handleClose()\"\n (onShow)=\"checkScroll()\"\n [styleClass]=\"hasFooter() ? 'tk-modal--has-footer' : 'tk-modal--no-footer'\"\n class=\"tk-modal\">\n @if (title()) {\n <ng-template pTemplate=\"header\">\n <span class=\"p-dialog-title\">{{ title() }}</span>\n </ng-template>\n }\n <section class=\"tk-modal__content\">\n @if (content()) {\n @if (isContentString()) {\n <p [innerHTML]=\"content()\"></p>\n } @else {\n <ng-template #contentHost></ng-template>\n }\n }\n </section>\n\n <ng-template pTemplate=\"footer\">\n @if (hasFooter()) {\n <section\n class=\"tk-modal__footer\"\n [class.tk-modal__footer--with-content]=\"hasScroll\">\n @for (btn of footerButtons()!; track $index) {\n <tk-button\n [label]=\"resolveProperty(btn.label)!\"\n [severity]=\"btn.severity\"\n [variant]=\"btn.variant\"\n [disabled]=\"resolveProperty(btn.disabled) ?? false\"\n (clicked)=\"handleAction(btn.action, btn.returnValue, btn.preventClose)\"\n (keydown.enter)=\"handleAction(btn.action, btn.returnValue, btn.preventClose)\"\n (keydown.space)=\"handleAction(btn.action, btn.returnValue, btn.preventClose)\" />\n }\n </section>\n }\n </ng-template>\n</p-dialog>\n","import { Injectable, ApplicationRef, ComponentRef, createComponent, EmbeddedViewRef, inject } from '@angular/core';\nimport { ModalComponent } from '../modal.component';\nimport { ModalConfig } from '../modal.types';\nimport { TkDialogRef } from '@tekus/design-system/core/types';\n\n/**\n * @service ModalService\n * @description\n * Service responsible for programmatically opening and managing modal dialogs.\n * It handles component creation, attachment to the document body, and cleanup.\n */\n@Injectable({ providedIn: 'root' })\nexport class ModalService {\n private readonly appRef = inject(ApplicationRef);\n\n /** Reference to the currently open modal dialog ref */\n private dialogRef: TkDialogRef<ModalComponent> | null = null;\n\n /** Internal getter for testing purposes */\n get modalRefForTesting(): ComponentRef<ModalComponent> | null {\n return this.dialogRef?.componentRef || null;\n }\n /** Internal setter for testing purposes */\n set modalRefForTesting(ref: ComponentRef<ModalComponent> | null) {\n this.dialogRef = ref ? new TkDialogRef(ref) : null;\n }\n\n /**\n * Opens a modal dialog with the provided configuration.\n * Only one modal can be open at a time.\n * @param config Configuration object for the modal (title, content, buttons, etc.)\n * @returns A TkDialogRef for the opened modal.\n */\n open<T = unknown, R = unknown>(config: ModalConfig): TkDialogRef<ModalComponent<T>, R> {\n if (this.dialogRef) {\n return this.dialogRef as unknown as TkDialogRef<ModalComponent<T>, R>;\n }\n\n const componentRef = createComponent(ModalComponent, {\n environmentInjector: this.appRef.injector,\n }) as ComponentRef<ModalComponent<T>>;\n\n this.appRef.attachView(componentRef.hostView);\n\n const domElem = (componentRef.hostView as EmbeddedViewRef<unknown>).rootNodes[0] as HTMLElement;\n document.body.appendChild(domElem);\n\n const dialogRef = new TkDialogRef<ModalComponent<T>, R>(componentRef);\n this.dialogRef = dialogRef as unknown as TkDialogRef<ModalComponent>;\n\n componentRef.setInput('title', config.title);\n componentRef.setInput('content', config.content);\n componentRef.setInput('footerButtons', config.footerButtons || []);\n componentRef.setInput('size', config.size || 'small');\n componentRef.setInput('closable', config.closable ?? true);\n componentRef.setInput('closeOnOutsideClick', config.closeOnOutsideClick ?? false);\n componentRef.setInput('interceptor', config.interceptor);\n componentRef.setInput('data', config.data || {});\n componentRef.setInput('dialogRef', dialogRef);\n\n componentRef.instance.closed.subscribe((value: unknown) => {\n dialogRef.emitClose(value as R);\n this.appRef.detachView(componentRef.hostView);\n componentRef.destroy();\n this.dialogRef = null;\n });\n\n componentRef.instance.open();\n\n return dialogRef;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -11,6 +11,17 @@ class ProcessStepsComponent {
11
11
  this.description = input(...(ngDevMode ? [undefined, { debugName: "description" }] : /* istanbul ignore next */ []));
12
12
  this.icon = input('gears', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
13
13
  this.status = input('progress', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
14
+ /** Whether to show the spinner + icon header while `status` is `progress`. */
15
+ this.showIcon = input(true, ...(ngDevMode ? [{ debugName: "showIcon" }] : /* istanbul ignore next */ []));
16
+ /**
17
+ * Strips the panel down to just the step list: no padding, and no
18
+ * `title`/`description` header while `status` is `progress` — for hosts
19
+ * that provide their own framing (e.g. a card) and already show the file
20
+ * name elsewhere. The final result view (`success`/`error`/`warning`)
21
+ * still shows its own title/message, since that's the only place the
22
+ * outcome text is surfaced.
23
+ */
24
+ this.compact = input(false, ...(ngDevMode ? [{ debugName: "compact" }] : /* istanbul ignore next */ []));
14
25
  /** Specific problems to list inside the result message box (ignored when `status` is `success`). */
15
26
  this.errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
16
27
  /** Seconds until the countdown finishes; omit to disable it. */
@@ -47,6 +58,16 @@ class ProcessStepsComponent {
47
58
  }, ...(ngDevMode ? [{ debugName: "resultColor" }] : /* istanbul ignore next */ []));
48
59
  /** Severity for the message box wrapping `description`/`errors` (success has no box). */
49
60
  this.resultMessageSeverity = computed(() => this.status() === 'error' ? 'error' : 'warn', ...(ngDevMode ? [{ debugName: "resultMessageSeverity" }] : /* istanbul ignore next */ []));
61
+ /** Severity for the compact terminal banner (`tk-message`) — unlike `resultMessageSeverity`, success gets its own box here. */
62
+ this.bannerSeverity = computed(() => {
63
+ if (this.status() === 'error') {
64
+ return 'error';
65
+ }
66
+ if (this.status() === 'warning') {
67
+ return 'warn';
68
+ }
69
+ return 'success';
70
+ }, ...(ngDevMode ? [{ debugName: "bannerSeverity" }] : /* istanbul ignore next */ []));
50
71
  /** `countdownLabel` with `{seconds}` filled in, or `undefined` while the countdown is disabled. */
51
72
  this.countdownText = computed(() => {
52
73
  const seconds = this.remainingSeconds();
@@ -96,12 +117,12 @@ class ProcessStepsComponent {
96
117
  }
97
118
  }
98
119
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ProcessStepsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
99
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ProcessStepsComponent, isStandalone: true, selector: "tk-process-steps", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, countdownSeconds: { classPropertyName: "countdownSeconds", publicName: "countdownSeconds", isSignal: true, isRequired: false, transformFunction: null }, countdownLabel: { classPropertyName: "countdownLabel", publicName: "countdownLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { countdownFinished: "countdownFinished" }, ngImport: i0, template: "<output class=\"tk-process-steps\">\n @if (status() === 'progress') {\n <div class=\"tk-process-steps__spinner-wrapper\" aria-hidden=\"true\">\n <p-progressSpinner\n class=\"tk-process-steps__spinner-progress\"\n strokeWidth=\"3\"\n animationDuration=\"1s\" />\n <tk-icon\n [icon]=\"icon()\"\n styleIcon=\"fal\"\n size=\"lg\"\n class=\"tk-process-steps__spinner-icon\" />\n </div>\n <h3 class=\"tk-process-steps__title\">{{ title() }}</h3>\n @if (description()) {\n <p class=\"tk-process-steps__description\">{{ description() }}</p>\n }\n <ul class=\"tk-process-steps__steps\">\n @for (step of steps(); track step.label) {\n <li\n class=\"tk-process-steps__step\"\n [class.tk-process-steps__step--active]=\"step.state === 'active'\"\n [class.tk-process-steps__step--done]=\"step.state === 'done'\"\n [class.tk-process-steps__step--error]=\"step.state === 'error'\"\n [class.tk-process-steps__step--warning]=\"step.state === 'warning'\"\n [attr.aria-current]=\"step.state === 'active' ? 'step' : null\">\n @switch (step.state) {\n @case ('done') {\n <tk-icon\n icon=\"circle-check\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"success\"\n class=\"tk-process-steps__step-icon--done\"\n aria-hidden=\"true\" />\n }\n @case ('error') {\n <tk-icon\n icon=\"circle-xmark\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"danger\"\n class=\"tk-process-steps__step-icon--error\"\n aria-hidden=\"true\" />\n }\n @case ('warning') {\n <tk-icon\n icon=\"triangle-exclamation\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"warning\"\n class=\"tk-process-steps__step-icon--warning\"\n aria-hidden=\"true\" />\n }\n @case ('active') {\n <span class=\"tk-process-steps__step-spinner\" aria-hidden=\"true\">\n <p-progressSpinner strokeWidth=\"5\" animationDuration=\"0.8s\" />\n </span>\n }\n @default {\n <span class=\"tk-process-steps__step-dot\" aria-hidden=\"true\"></span>\n }\n }\n <span class=\"tk-process-steps__step-label\">\n {{ step.label }}\n <span class=\"tk-process-steps__sr-only\">({{ stepStatusLabel(step.state) }})</span>\n </span>\n </li>\n }\n </ul>\n } @else {\n <div\n class=\"tk-process-steps__result-circle\"\n [class.tk-process-steps__result-circle--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-circle--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-circle--warning]=\"status() === 'warning'\">\n <tk-icon\n [icon]=\"resultIcon()\"\n styleIcon=\"fal\"\n size=\"2x\"\n [color]=\"resultColor()\"\n aria-hidden=\"true\" />\n </div>\n <h3\n class=\"tk-process-steps__result-title\"\n [class.tk-process-steps__result-title--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-title--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-title--warning]=\"status() === 'warning'\">\n {{ title() }}\n </h3>\n\n @if (status() === 'success') {\n @if (description()) {\n <p class=\"tk-process-steps__result-description\">{{ description() }}</p>\n }\n } @else if (errors().length || description()) {\n <tk-message [severity]=\"resultMessageSeverity()\" class=\"tk-process-steps__result-message\">\n @if (errors().length) {\n <ul class=\"tk-process-steps__result-errors\">\n @for (error of errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n } @else {\n {{ description() }}\n }\n </tk-message>\n }\n\n @if (countdownText(); as countdownText) {\n <p\n class=\"tk-process-steps__result-countdown\"\n [class.tk-process-steps__result-countdown--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-countdown--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-countdown--warning]=\"status() === 'warning'\">\n {{ countdownText }}\n </p>\n }\n }\n</output>\n", styles: [":host{display:block}.tk-process-steps{display:flex;flex-direction:column;align-items:center;padding:var(--tk-spacing-padding-xl);gap:var(--tk-spacing-gap-m);text-align:center}.tk-process-steps__spinner-wrapper{position:relative;display:inline-flex;align-items:center;justify-content:center}.tk-process-steps__spinner-progress{width:var(--tk-size-base-500);height:var(--tk-size-base-500)}.tk-process-steps__spinner-icon{position:absolute;pointer-events:none;color:var(--tk-color-primary-strong)}.tk-process-steps__title{font-size:var(--tk-font-size-base-125);font-weight:var(--tk-font-weight-600);color:var(--tk-color-text-default);margin:0}.tk-process-steps__description{font-size:var(--tk-font-size-base-88);color:var(--tk-color-text-subtle);max-width:28rem;margin:0;line-height:1.6}.tk-process-steps__steps{width:100%;max-width:28rem;margin:0 auto;display:flex;flex-direction:column;gap:var(--tk-spacing-gap-m, 1rem);text-align:left;list-style:none;padding:0}.tk-process-steps__step{display:flex;align-items:center;gap:var(--tk-spacing-gap-s);font-size:var(--tk-font-size-base-88)}.tk-process-steps__step-icon--done,.tk-process-steps__step-icon--error,.tk-process-steps__step-icon--warning{flex-shrink:0}.tk-process-steps__step-spinner{display:inline-flex;align-items:center;justify-content:center;width:1.1rem;height:1.1rem;flex-shrink:0}.tk-process-steps__step-spinner ::ng-deep .p-progressspinner{width:1.1rem;height:1.1rem;margin:0}.tk-process-steps__step-spinner ::ng-deep svg{width:1.1rem!important;height:1.1rem!important}.tk-process-steps__step-dot{width:var(--tk-size-base-50);height:var(--tk-size-base-50);border-radius:50%;background:var(--tk-color-text-subtle);flex-shrink:0;opacity:.4}.tk-process-steps__step-label{color:var(--tk-color-text-subtle)}.tk-process-steps__step--active .tk-process-steps__step-label{color:var(--tk-color-primary-default);font-weight:var(--tk-font-weight-600)}.tk-process-steps__step--done .tk-process-steps__step-label{color:var(--tk-color-feedback-success-strong)}.tk-process-steps__step--error .tk-process-steps__step-label{color:var(--tk-color-feedback-danger-strong)}.tk-process-steps__step--warning .tk-process-steps__step-label{color:var(--tk-color-feedback-warn-strong)}.tk-process-steps__result-circle{width:var(--tk-size-base-500);height:var(--tk-size-base-500);border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0}.tk-process-steps__result-circle--success{background:var(--tk-color-feedback-success-muted)}.tk-process-steps__result-circle--error{background:var(--tk-color-feedback-danger-muted)}.tk-process-steps__result-circle--warning{background:var(--tk-color-feedback-warn-muted)}.tk-process-steps__result-title{font-size:var(--tk-font-size-base-125);font-weight:var(--tk-font-weight-600);margin:0}.tk-process-steps__result-title--success{color:var(--tk-color-feedback-success-strong)}.tk-process-steps__result-title--error{color:var(--tk-color-feedback-danger-strong)}.tk-process-steps__result-title--warning{color:var(--tk-color-feedback-warn-strong)}.tk-process-steps__result-description{font-size:var(--tk-font-size-base-100);color:var(--tk-color-text-subtle);max-width:22rem;margin:0;line-height:1.6}.tk-process-steps__result-message{text-align:left}.tk-process-steps__result-errors{margin:0;padding-left:var(--tk-spacing-padding-l);display:flex;flex-direction:column;gap:var(--tk-spacing-gap-xs)}.tk-process-steps__result-countdown{font-size:var(--tk-font-size-base-88);color:var(--tk-color-text-subtle);margin:0}.tk-process-steps__result-countdown--success{color:var(--tk-color-feedback-success-strong)}.tk-process-steps__result-countdown--error{color:var(--tk-color-feedback-danger-strong)}.tk-process-steps__result-countdown--warning{color:var(--tk-color-feedback-warn-strong)}.tk-process-steps__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: IconComponent, selector: "tk-icon", inputs: ["icon", "styleIcon", "color", "size", "disabled"] }, { kind: "component", type: MessageComponent, selector: "tk-message", inputs: ["severity", "closable"], outputs: ["closed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
120
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ProcessStepsComponent, isStandalone: true, selector: "tk-process-steps", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, countdownSeconds: { classPropertyName: "countdownSeconds", publicName: "countdownSeconds", isSignal: true, isRequired: false, transformFunction: null }, countdownLabel: { classPropertyName: "countdownLabel", publicName: "countdownLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { countdownFinished: "countdownFinished" }, ngImport: i0, template: "<output class=\"tk-process-steps\" [class.tk-process-steps--compact]=\"compact()\">\n @if (status() === 'progress' && showIcon()) {\n <div class=\"tk-process-steps__spinner-wrapper\" aria-hidden=\"true\">\n <p-progressSpinner\n class=\"tk-process-steps__spinner-progress\"\n strokeWidth=\"3\"\n animationDuration=\"1s\" />\n <tk-icon\n [icon]=\"icon()\"\n styleIcon=\"fal\"\n size=\"lg\"\n class=\"tk-process-steps__spinner-icon\" />\n </div>\n }\n\n @if (status() === 'progress' && !compact()) {\n <h3 class=\"tk-process-steps__title\">{{ title() }}</h3>\n @if (description()) {\n <p class=\"tk-process-steps__description\">{{ description() }}</p>\n }\n }\n\n @if (status() === 'progress' || compact()) {\n <ul class=\"tk-process-steps__steps\">\n @for (step of steps(); track step.label) {\n <li\n class=\"tk-process-steps__step\"\n [class.tk-process-steps__step--active]=\"step.state === 'active'\"\n [class.tk-process-steps__step--done]=\"step.state === 'done'\"\n [class.tk-process-steps__step--error]=\"step.state === 'error'\"\n [class.tk-process-steps__step--warning]=\"step.state === 'warning'\"\n [attr.aria-current]=\"step.state === 'active' ? 'step' : null\">\n <span\n class=\"tk-process-steps__step-icon-wrapper\"\n [class.tk-process-steps__step-icon-wrapper--done]=\"step.state === 'done'\"\n [class.tk-process-steps__step-icon-wrapper--error]=\"step.state === 'error'\"\n [class.tk-process-steps__step-icon-wrapper--warning]=\"step.state === 'warning'\">\n @switch (step.state) {\n @case ('done') {\n <tk-icon\n icon=\"circle-check\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"success\"\n class=\"tk-process-steps__step-icon--done\"\n aria-hidden=\"true\" />\n }\n @case ('error') {\n <tk-icon\n icon=\"circle-xmark\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"danger\"\n class=\"tk-process-steps__step-icon--error\"\n aria-hidden=\"true\" />\n }\n @case ('warning') {\n <tk-icon\n icon=\"triangle-exclamation\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"warning\"\n class=\"tk-process-steps__step-icon--warning\"\n aria-hidden=\"true\" />\n }\n @case ('active') {\n <span class=\"tk-process-steps__step-spinner\" aria-hidden=\"true\">\n <p-progressSpinner strokeWidth=\"5\" animationDuration=\"0.8s\" />\n </span>\n }\n @default {\n <span class=\"tk-process-steps__step-dot\" aria-hidden=\"true\"></span>\n }\n }\n </span>\n <span class=\"tk-process-steps__step-content\">\n <span class=\"tk-process-steps__step-label\">\n {{ step.label }}\n <span class=\"tk-process-steps__sr-only\">({{ stepStatusLabel(step.state) }})</span>\n </span>\n @if (step.description) {\n <span class=\"tk-process-steps__step-description\">{{ step.description }}</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n\n @if (status() !== 'progress') {\n @if (compact()) {\n @if (errors().length || description()) {\n <tk-message [severity]=\"bannerSeverity()\" class=\"tk-process-steps__banner\">\n @if (errors().length) {\n <ul class=\"tk-process-steps__result-errors\">\n @for (error of errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n } @else {\n {{ description() }}\n }\n </tk-message>\n }\n } @else {\n <div\n class=\"tk-process-steps__result-circle\"\n [class.tk-process-steps__result-circle--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-circle--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-circle--warning]=\"status() === 'warning'\">\n <tk-icon\n [icon]=\"resultIcon()\"\n styleIcon=\"fal\"\n size=\"2x\"\n [color]=\"resultColor()\"\n aria-hidden=\"true\" />\n </div>\n <h3\n class=\"tk-process-steps__result-title\"\n [class.tk-process-steps__result-title--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-title--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-title--warning]=\"status() === 'warning'\">\n {{ title() }}\n </h3>\n\n @if (status() === 'success') {\n @if (description()) {\n <p class=\"tk-process-steps__result-description\">{{ description() }}</p>\n }\n } @else if (errors().length || description()) {\n <tk-message [severity]=\"resultMessageSeverity()\" class=\"tk-process-steps__result-message\">\n @if (errors().length) {\n <ul class=\"tk-process-steps__result-errors\">\n @for (error of errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n } @else {\n {{ description() }}\n }\n </tk-message>\n }\n }\n\n @if (countdownText(); as countdownText) {\n <p\n class=\"tk-process-steps__result-countdown\"\n [class.tk-process-steps__result-countdown--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-countdown--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-countdown--warning]=\"status() === 'warning'\">\n {{ countdownText }}\n </p>\n }\n }\n</output>\n", styles: [":host{display:block}.tk-process-steps{display:flex;flex-direction:column;align-items:center;padding:var(--tk-spacing-padding-xl);gap:var(--tk-spacing-gap-m);text-align:center}.tk-process-steps--compact{padding:0}.tk-process-steps__spinner-wrapper{position:relative;display:inline-flex;align-items:center;justify-content:center}.tk-process-steps__spinner-progress{width:var(--tk-size-base-500);height:var(--tk-size-base-500)}.tk-process-steps__spinner-icon{position:absolute;pointer-events:none;color:var(--tk-color-primary-strong)}.tk-process-steps__title{font-size:var(--tk-font-size-base-125);font-weight:var(--tk-font-weight-600);color:var(--tk-color-text-default);margin:0}.tk-process-steps__description{font-size:var(--tk-font-size-base-88);color:var(--tk-color-text-subtle);max-width:28rem;margin:0;line-height:1.6}.tk-process-steps__steps{width:100%;max-width:28rem;margin:0 auto;display:flex;flex-direction:column;gap:var(--tk-spacing-gap-m, 1rem);text-align:left;list-style:none;padding:0}.tk-process-steps--compact .tk-process-steps__steps{background:var(--tk-color-background-soft);border-radius:var(--tk-borderRadius-m);padding:var(--tk-spacing-base-100);max-width:none}.tk-process-steps__step{display:flex;align-items:flex-start;gap:var(--tk-spacing-gap-s);font-size:var(--tk-font-size-base-88)}.tk-process-steps__step-icon-wrapper{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:50%;flex-shrink:0}.tk-process-steps__step-icon-wrapper--done{background:var(--tk-color-feedback-success-muted)}.tk-process-steps__step-icon-wrapper--error{background:var(--tk-color-feedback-danger-muted)}.tk-process-steps__step-icon-wrapper--warning{background:var(--tk-color-feedback-warn-muted)}.tk-process-steps__step-content{display:flex;flex-direction:column;gap:var(--tk-spacing-gap-xs);padding-top:.15rem}.tk-process-steps__step-spinner{display:inline-flex;align-items:center;justify-content:center;width:1.1rem;height:1.1rem;flex-shrink:0}.tk-process-steps__step-spinner ::ng-deep .p-progressspinner{width:1.1rem;height:1.1rem;margin:0}.tk-process-steps__step-spinner ::ng-deep svg{width:1.1rem!important;height:1.1rem!important}.tk-process-steps__step-dot{width:var(--tk-size-base-50);height:var(--tk-size-base-50);border-radius:50%;background:var(--tk-color-text-subtle);flex-shrink:0;opacity:.4}.tk-process-steps__step-label{color:var(--tk-color-text-subtle)}.tk-process-steps__step-description{font-size:var(--tk-font-size-base-75);font-weight:var(--tk-font-weight-400);color:var(--tk-color-text-subtle)}.tk-process-steps__step--active .tk-process-steps__step-label{color:var(--tk-color-primary-default);font-weight:var(--tk-font-weight-600)}.tk-process-steps__step--done .tk-process-steps__step-label{color:var(--tk-color-feedback-success-strong);font-weight:var(--tk-font-weight-600)}.tk-process-steps__step--error .tk-process-steps__step-label{color:var(--tk-color-feedback-danger-strong);font-weight:var(--tk-font-weight-600)}.tk-process-steps__step--warning .tk-process-steps__step-label{color:var(--tk-color-feedback-warn-strong);font-weight:var(--tk-font-weight-600)}.tk-process-steps__banner{text-align:left}.tk-process-steps__result-circle{width:var(--tk-size-base-500);height:var(--tk-size-base-500);border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0}.tk-process-steps__result-circle--success{background:var(--tk-color-feedback-success-muted)}.tk-process-steps__result-circle--error{background:var(--tk-color-feedback-danger-muted)}.tk-process-steps__result-circle--warning{background:var(--tk-color-feedback-warn-muted)}.tk-process-steps__result-title{font-size:var(--tk-font-size-base-125);font-weight:var(--tk-font-weight-600);margin:0}.tk-process-steps__result-title--success{color:var(--tk-color-feedback-success-strong)}.tk-process-steps__result-title--error{color:var(--tk-color-feedback-danger-strong)}.tk-process-steps__result-title--warning{color:var(--tk-color-feedback-warn-strong)}.tk-process-steps__result-description{font-size:var(--tk-font-size-base-100);color:var(--tk-color-text-subtle);max-width:22rem;margin:0;line-height:1.6}.tk-process-steps__result-message{text-align:left}.tk-process-steps__result-errors{margin:0;padding-left:var(--tk-spacing-padding-l);display:flex;flex-direction:column;gap:var(--tk-spacing-gap-xs)}.tk-process-steps__result-countdown{font-size:var(--tk-font-size-base-88);color:var(--tk-color-text-subtle);margin:0}.tk-process-steps__result-countdown--success{color:var(--tk-color-feedback-success-strong)}.tk-process-steps__result-countdown--error{color:var(--tk-color-feedback-danger-strong)}.tk-process-steps__result-countdown--warning{color:var(--tk-color-feedback-warn-strong)}.tk-process-steps__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: IconComponent, selector: "tk-icon", inputs: ["icon", "styleIcon", "color", "size", "disabled"] }, { kind: "component", type: MessageComponent, selector: "tk-message", inputs: ["severity", "closable"], outputs: ["closed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
100
121
  }
101
122
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ProcessStepsComponent, decorators: [{
102
123
  type: Component,
103
- args: [{ selector: 'tk-process-steps', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ProgressSpinner, IconComponent, MessageComponent], template: "<output class=\"tk-process-steps\">\n @if (status() === 'progress') {\n <div class=\"tk-process-steps__spinner-wrapper\" aria-hidden=\"true\">\n <p-progressSpinner\n class=\"tk-process-steps__spinner-progress\"\n strokeWidth=\"3\"\n animationDuration=\"1s\" />\n <tk-icon\n [icon]=\"icon()\"\n styleIcon=\"fal\"\n size=\"lg\"\n class=\"tk-process-steps__spinner-icon\" />\n </div>\n <h3 class=\"tk-process-steps__title\">{{ title() }}</h3>\n @if (description()) {\n <p class=\"tk-process-steps__description\">{{ description() }}</p>\n }\n <ul class=\"tk-process-steps__steps\">\n @for (step of steps(); track step.label) {\n <li\n class=\"tk-process-steps__step\"\n [class.tk-process-steps__step--active]=\"step.state === 'active'\"\n [class.tk-process-steps__step--done]=\"step.state === 'done'\"\n [class.tk-process-steps__step--error]=\"step.state === 'error'\"\n [class.tk-process-steps__step--warning]=\"step.state === 'warning'\"\n [attr.aria-current]=\"step.state === 'active' ? 'step' : null\">\n @switch (step.state) {\n @case ('done') {\n <tk-icon\n icon=\"circle-check\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"success\"\n class=\"tk-process-steps__step-icon--done\"\n aria-hidden=\"true\" />\n }\n @case ('error') {\n <tk-icon\n icon=\"circle-xmark\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"danger\"\n class=\"tk-process-steps__step-icon--error\"\n aria-hidden=\"true\" />\n }\n @case ('warning') {\n <tk-icon\n icon=\"triangle-exclamation\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"warning\"\n class=\"tk-process-steps__step-icon--warning\"\n aria-hidden=\"true\" />\n }\n @case ('active') {\n <span class=\"tk-process-steps__step-spinner\" aria-hidden=\"true\">\n <p-progressSpinner strokeWidth=\"5\" animationDuration=\"0.8s\" />\n </span>\n }\n @default {\n <span class=\"tk-process-steps__step-dot\" aria-hidden=\"true\"></span>\n }\n }\n <span class=\"tk-process-steps__step-label\">\n {{ step.label }}\n <span class=\"tk-process-steps__sr-only\">({{ stepStatusLabel(step.state) }})</span>\n </span>\n </li>\n }\n </ul>\n } @else {\n <div\n class=\"tk-process-steps__result-circle\"\n [class.tk-process-steps__result-circle--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-circle--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-circle--warning]=\"status() === 'warning'\">\n <tk-icon\n [icon]=\"resultIcon()\"\n styleIcon=\"fal\"\n size=\"2x\"\n [color]=\"resultColor()\"\n aria-hidden=\"true\" />\n </div>\n <h3\n class=\"tk-process-steps__result-title\"\n [class.tk-process-steps__result-title--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-title--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-title--warning]=\"status() === 'warning'\">\n {{ title() }}\n </h3>\n\n @if (status() === 'success') {\n @if (description()) {\n <p class=\"tk-process-steps__result-description\">{{ description() }}</p>\n }\n } @else if (errors().length || description()) {\n <tk-message [severity]=\"resultMessageSeverity()\" class=\"tk-process-steps__result-message\">\n @if (errors().length) {\n <ul class=\"tk-process-steps__result-errors\">\n @for (error of errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n } @else {\n {{ description() }}\n }\n </tk-message>\n }\n\n @if (countdownText(); as countdownText) {\n <p\n class=\"tk-process-steps__result-countdown\"\n [class.tk-process-steps__result-countdown--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-countdown--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-countdown--warning]=\"status() === 'warning'\">\n {{ countdownText }}\n </p>\n }\n }\n</output>\n", styles: [":host{display:block}.tk-process-steps{display:flex;flex-direction:column;align-items:center;padding:var(--tk-spacing-padding-xl);gap:var(--tk-spacing-gap-m);text-align:center}.tk-process-steps__spinner-wrapper{position:relative;display:inline-flex;align-items:center;justify-content:center}.tk-process-steps__spinner-progress{width:var(--tk-size-base-500);height:var(--tk-size-base-500)}.tk-process-steps__spinner-icon{position:absolute;pointer-events:none;color:var(--tk-color-primary-strong)}.tk-process-steps__title{font-size:var(--tk-font-size-base-125);font-weight:var(--tk-font-weight-600);color:var(--tk-color-text-default);margin:0}.tk-process-steps__description{font-size:var(--tk-font-size-base-88);color:var(--tk-color-text-subtle);max-width:28rem;margin:0;line-height:1.6}.tk-process-steps__steps{width:100%;max-width:28rem;margin:0 auto;display:flex;flex-direction:column;gap:var(--tk-spacing-gap-m, 1rem);text-align:left;list-style:none;padding:0}.tk-process-steps__step{display:flex;align-items:center;gap:var(--tk-spacing-gap-s);font-size:var(--tk-font-size-base-88)}.tk-process-steps__step-icon--done,.tk-process-steps__step-icon--error,.tk-process-steps__step-icon--warning{flex-shrink:0}.tk-process-steps__step-spinner{display:inline-flex;align-items:center;justify-content:center;width:1.1rem;height:1.1rem;flex-shrink:0}.tk-process-steps__step-spinner ::ng-deep .p-progressspinner{width:1.1rem;height:1.1rem;margin:0}.tk-process-steps__step-spinner ::ng-deep svg{width:1.1rem!important;height:1.1rem!important}.tk-process-steps__step-dot{width:var(--tk-size-base-50);height:var(--tk-size-base-50);border-radius:50%;background:var(--tk-color-text-subtle);flex-shrink:0;opacity:.4}.tk-process-steps__step-label{color:var(--tk-color-text-subtle)}.tk-process-steps__step--active .tk-process-steps__step-label{color:var(--tk-color-primary-default);font-weight:var(--tk-font-weight-600)}.tk-process-steps__step--done .tk-process-steps__step-label{color:var(--tk-color-feedback-success-strong)}.tk-process-steps__step--error .tk-process-steps__step-label{color:var(--tk-color-feedback-danger-strong)}.tk-process-steps__step--warning .tk-process-steps__step-label{color:var(--tk-color-feedback-warn-strong)}.tk-process-steps__result-circle{width:var(--tk-size-base-500);height:var(--tk-size-base-500);border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0}.tk-process-steps__result-circle--success{background:var(--tk-color-feedback-success-muted)}.tk-process-steps__result-circle--error{background:var(--tk-color-feedback-danger-muted)}.tk-process-steps__result-circle--warning{background:var(--tk-color-feedback-warn-muted)}.tk-process-steps__result-title{font-size:var(--tk-font-size-base-125);font-weight:var(--tk-font-weight-600);margin:0}.tk-process-steps__result-title--success{color:var(--tk-color-feedback-success-strong)}.tk-process-steps__result-title--error{color:var(--tk-color-feedback-danger-strong)}.tk-process-steps__result-title--warning{color:var(--tk-color-feedback-warn-strong)}.tk-process-steps__result-description{font-size:var(--tk-font-size-base-100);color:var(--tk-color-text-subtle);max-width:22rem;margin:0;line-height:1.6}.tk-process-steps__result-message{text-align:left}.tk-process-steps__result-errors{margin:0;padding-left:var(--tk-spacing-padding-l);display:flex;flex-direction:column;gap:var(--tk-spacing-gap-xs)}.tk-process-steps__result-countdown{font-size:var(--tk-font-size-base-88);color:var(--tk-color-text-subtle);margin:0}.tk-process-steps__result-countdown--success{color:var(--tk-color-feedback-success-strong)}.tk-process-steps__result-countdown--error{color:var(--tk-color-feedback-danger-strong)}.tk-process-steps__result-countdown--warning{color:var(--tk-color-feedback-warn-strong)}.tk-process-steps__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
104
- }], ctorParameters: () => [], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], countdownSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "countdownSeconds", required: false }] }], countdownLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "countdownLabel", required: false }] }], countdownFinished: [{ type: i0.Output, args: ["countdownFinished"] }] } });
124
+ args: [{ selector: 'tk-process-steps', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ProgressSpinner, IconComponent, MessageComponent], template: "<output class=\"tk-process-steps\" [class.tk-process-steps--compact]=\"compact()\">\n @if (status() === 'progress' && showIcon()) {\n <div class=\"tk-process-steps__spinner-wrapper\" aria-hidden=\"true\">\n <p-progressSpinner\n class=\"tk-process-steps__spinner-progress\"\n strokeWidth=\"3\"\n animationDuration=\"1s\" />\n <tk-icon\n [icon]=\"icon()\"\n styleIcon=\"fal\"\n size=\"lg\"\n class=\"tk-process-steps__spinner-icon\" />\n </div>\n }\n\n @if (status() === 'progress' && !compact()) {\n <h3 class=\"tk-process-steps__title\">{{ title() }}</h3>\n @if (description()) {\n <p class=\"tk-process-steps__description\">{{ description() }}</p>\n }\n }\n\n @if (status() === 'progress' || compact()) {\n <ul class=\"tk-process-steps__steps\">\n @for (step of steps(); track step.label) {\n <li\n class=\"tk-process-steps__step\"\n [class.tk-process-steps__step--active]=\"step.state === 'active'\"\n [class.tk-process-steps__step--done]=\"step.state === 'done'\"\n [class.tk-process-steps__step--error]=\"step.state === 'error'\"\n [class.tk-process-steps__step--warning]=\"step.state === 'warning'\"\n [attr.aria-current]=\"step.state === 'active' ? 'step' : null\">\n <span\n class=\"tk-process-steps__step-icon-wrapper\"\n [class.tk-process-steps__step-icon-wrapper--done]=\"step.state === 'done'\"\n [class.tk-process-steps__step-icon-wrapper--error]=\"step.state === 'error'\"\n [class.tk-process-steps__step-icon-wrapper--warning]=\"step.state === 'warning'\">\n @switch (step.state) {\n @case ('done') {\n <tk-icon\n icon=\"circle-check\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"success\"\n class=\"tk-process-steps__step-icon--done\"\n aria-hidden=\"true\" />\n }\n @case ('error') {\n <tk-icon\n icon=\"circle-xmark\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"danger\"\n class=\"tk-process-steps__step-icon--error\"\n aria-hidden=\"true\" />\n }\n @case ('warning') {\n <tk-icon\n icon=\"triangle-exclamation\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"warning\"\n class=\"tk-process-steps__step-icon--warning\"\n aria-hidden=\"true\" />\n }\n @case ('active') {\n <span class=\"tk-process-steps__step-spinner\" aria-hidden=\"true\">\n <p-progressSpinner strokeWidth=\"5\" animationDuration=\"0.8s\" />\n </span>\n }\n @default {\n <span class=\"tk-process-steps__step-dot\" aria-hidden=\"true\"></span>\n }\n }\n </span>\n <span class=\"tk-process-steps__step-content\">\n <span class=\"tk-process-steps__step-label\">\n {{ step.label }}\n <span class=\"tk-process-steps__sr-only\">({{ stepStatusLabel(step.state) }})</span>\n </span>\n @if (step.description) {\n <span class=\"tk-process-steps__step-description\">{{ step.description }}</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n\n @if (status() !== 'progress') {\n @if (compact()) {\n @if (errors().length || description()) {\n <tk-message [severity]=\"bannerSeverity()\" class=\"tk-process-steps__banner\">\n @if (errors().length) {\n <ul class=\"tk-process-steps__result-errors\">\n @for (error of errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n } @else {\n {{ description() }}\n }\n </tk-message>\n }\n } @else {\n <div\n class=\"tk-process-steps__result-circle\"\n [class.tk-process-steps__result-circle--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-circle--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-circle--warning]=\"status() === 'warning'\">\n <tk-icon\n [icon]=\"resultIcon()\"\n styleIcon=\"fal\"\n size=\"2x\"\n [color]=\"resultColor()\"\n aria-hidden=\"true\" />\n </div>\n <h3\n class=\"tk-process-steps__result-title\"\n [class.tk-process-steps__result-title--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-title--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-title--warning]=\"status() === 'warning'\">\n {{ title() }}\n </h3>\n\n @if (status() === 'success') {\n @if (description()) {\n <p class=\"tk-process-steps__result-description\">{{ description() }}</p>\n }\n } @else if (errors().length || description()) {\n <tk-message [severity]=\"resultMessageSeverity()\" class=\"tk-process-steps__result-message\">\n @if (errors().length) {\n <ul class=\"tk-process-steps__result-errors\">\n @for (error of errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n } @else {\n {{ description() }}\n }\n </tk-message>\n }\n }\n\n @if (countdownText(); as countdownText) {\n <p\n class=\"tk-process-steps__result-countdown\"\n [class.tk-process-steps__result-countdown--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-countdown--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-countdown--warning]=\"status() === 'warning'\">\n {{ countdownText }}\n </p>\n }\n }\n</output>\n", styles: [":host{display:block}.tk-process-steps{display:flex;flex-direction:column;align-items:center;padding:var(--tk-spacing-padding-xl);gap:var(--tk-spacing-gap-m);text-align:center}.tk-process-steps--compact{padding:0}.tk-process-steps__spinner-wrapper{position:relative;display:inline-flex;align-items:center;justify-content:center}.tk-process-steps__spinner-progress{width:var(--tk-size-base-500);height:var(--tk-size-base-500)}.tk-process-steps__spinner-icon{position:absolute;pointer-events:none;color:var(--tk-color-primary-strong)}.tk-process-steps__title{font-size:var(--tk-font-size-base-125);font-weight:var(--tk-font-weight-600);color:var(--tk-color-text-default);margin:0}.tk-process-steps__description{font-size:var(--tk-font-size-base-88);color:var(--tk-color-text-subtle);max-width:28rem;margin:0;line-height:1.6}.tk-process-steps__steps{width:100%;max-width:28rem;margin:0 auto;display:flex;flex-direction:column;gap:var(--tk-spacing-gap-m, 1rem);text-align:left;list-style:none;padding:0}.tk-process-steps--compact .tk-process-steps__steps{background:var(--tk-color-background-soft);border-radius:var(--tk-borderRadius-m);padding:var(--tk-spacing-base-100);max-width:none}.tk-process-steps__step{display:flex;align-items:flex-start;gap:var(--tk-spacing-gap-s);font-size:var(--tk-font-size-base-88)}.tk-process-steps__step-icon-wrapper{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:50%;flex-shrink:0}.tk-process-steps__step-icon-wrapper--done{background:var(--tk-color-feedback-success-muted)}.tk-process-steps__step-icon-wrapper--error{background:var(--tk-color-feedback-danger-muted)}.tk-process-steps__step-icon-wrapper--warning{background:var(--tk-color-feedback-warn-muted)}.tk-process-steps__step-content{display:flex;flex-direction:column;gap:var(--tk-spacing-gap-xs);padding-top:.15rem}.tk-process-steps__step-spinner{display:inline-flex;align-items:center;justify-content:center;width:1.1rem;height:1.1rem;flex-shrink:0}.tk-process-steps__step-spinner ::ng-deep .p-progressspinner{width:1.1rem;height:1.1rem;margin:0}.tk-process-steps__step-spinner ::ng-deep svg{width:1.1rem!important;height:1.1rem!important}.tk-process-steps__step-dot{width:var(--tk-size-base-50);height:var(--tk-size-base-50);border-radius:50%;background:var(--tk-color-text-subtle);flex-shrink:0;opacity:.4}.tk-process-steps__step-label{color:var(--tk-color-text-subtle)}.tk-process-steps__step-description{font-size:var(--tk-font-size-base-75);font-weight:var(--tk-font-weight-400);color:var(--tk-color-text-subtle)}.tk-process-steps__step--active .tk-process-steps__step-label{color:var(--tk-color-primary-default);font-weight:var(--tk-font-weight-600)}.tk-process-steps__step--done .tk-process-steps__step-label{color:var(--tk-color-feedback-success-strong);font-weight:var(--tk-font-weight-600)}.tk-process-steps__step--error .tk-process-steps__step-label{color:var(--tk-color-feedback-danger-strong);font-weight:var(--tk-font-weight-600)}.tk-process-steps__step--warning .tk-process-steps__step-label{color:var(--tk-color-feedback-warn-strong);font-weight:var(--tk-font-weight-600)}.tk-process-steps__banner{text-align:left}.tk-process-steps__result-circle{width:var(--tk-size-base-500);height:var(--tk-size-base-500);border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0}.tk-process-steps__result-circle--success{background:var(--tk-color-feedback-success-muted)}.tk-process-steps__result-circle--error{background:var(--tk-color-feedback-danger-muted)}.tk-process-steps__result-circle--warning{background:var(--tk-color-feedback-warn-muted)}.tk-process-steps__result-title{font-size:var(--tk-font-size-base-125);font-weight:var(--tk-font-weight-600);margin:0}.tk-process-steps__result-title--success{color:var(--tk-color-feedback-success-strong)}.tk-process-steps__result-title--error{color:var(--tk-color-feedback-danger-strong)}.tk-process-steps__result-title--warning{color:var(--tk-color-feedback-warn-strong)}.tk-process-steps__result-description{font-size:var(--tk-font-size-base-100);color:var(--tk-color-text-subtle);max-width:22rem;margin:0;line-height:1.6}.tk-process-steps__result-message{text-align:left}.tk-process-steps__result-errors{margin:0;padding-left:var(--tk-spacing-padding-l);display:flex;flex-direction:column;gap:var(--tk-spacing-gap-xs)}.tk-process-steps__result-countdown{font-size:var(--tk-font-size-base-88);color:var(--tk-color-text-subtle);margin:0}.tk-process-steps__result-countdown--success{color:var(--tk-color-feedback-success-strong)}.tk-process-steps__result-countdown--error{color:var(--tk-color-feedback-danger-strong)}.tk-process-steps__result-countdown--warning{color:var(--tk-color-feedback-warn-strong)}.tk-process-steps__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
125
+ }], ctorParameters: () => [], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], countdownSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "countdownSeconds", required: false }] }], countdownLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "countdownLabel", required: false }] }], countdownFinished: [{ type: i0.Output, args: ["countdownFinished"] }] } });
105
126
 
106
127
  /**
107
128
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"tekus-design-system-components-process-steps.mjs","sources":["../../../projects/design-system/components/process-steps/src/process-steps.component.ts","../../../projects/design-system/components/process-steps/src/process-steps.component.html","../../../projects/design-system/components/process-steps/tekus-design-system-components-process-steps.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n EffectCleanupRegisterFn,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { ProgressSpinner } from 'primeng/progressspinner';\nimport { IconComponent } from '@tekus/design-system/components/icon';\nimport { MessageComponent } from '@tekus/design-system/components/message';\nimport { ProcessStep, ProcessStepsStatus, StepState } from './process-steps.types';\n\n@Component({\n selector: 'tk-process-steps',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [ProgressSpinner, IconComponent, MessageComponent],\n templateUrl: './process-steps.component.html',\n styleUrl: './process-steps.component.scss'\n})\nexport class ProcessStepsComponent {\n readonly steps = input<ProcessStep[]>([]);\n readonly title = input.required<string>();\n readonly description = input<string>();\n readonly icon = input<string>('gears');\n readonly status = input<ProcessStepsStatus>('progress');\n\n /** Specific problems to list inside the result message box (ignored when `status` is `success`). */\n readonly errors = input<string[]>([]);\n\n /** Seconds until the countdown finishes; omit to disable it. */\n readonly countdownSeconds = input<number>();\n\n /**\n * Countdown text; `{seconds}` is replaced with the seconds left. Defaults to a \"closing\"\n * message, but the countdown isn't only for closing — override it to match what\n * `(countdownFinished)` actually does.\n */\n readonly countdownLabel = input<string>('Closing in {seconds}s…');\n\n /** Emitted once when the countdown reaches zero — the consumer decides what happens next (close a modal, show a toast, etc.). */\n readonly countdownFinished = output<void>();\n\n /** Seconds left in the countdown, or `undefined` while it's disabled. */\n readonly remainingSeconds = signal<number | undefined>(undefined);\n\n constructor() {\n effect(onCleanup => this.runCountdown(onCleanup));\n }\n\n /** Starts (or disables) the countdown whenever `status`/`countdownSeconds` change. */\n private runCountdown(onCleanup: EffectCleanupRegisterFn): void {\n const total = this.countdownSeconds();\n if (this.status() === 'progress' || !total) {\n this.remainingSeconds.set(undefined);\n return;\n }\n\n this.remainingSeconds.set(total);\n const intervalId = setInterval(() => this.tickCountdown(intervalId), 1000);\n onCleanup(() => clearInterval(intervalId));\n }\n\n /** Decrements `remainingSeconds` by one and emits `countdownFinished` once it bottoms out. */\n private tickCountdown(intervalId: ReturnType<typeof setInterval>): void {\n const next = (this.remainingSeconds() ?? 1) - 1;\n this.remainingSeconds.set(Math.max(next, 0));\n if (next <= 0) {\n clearInterval(intervalId);\n this.countdownFinished.emit();\n }\n }\n\n /**\n * Accessible suffix announced per step since state is otherwise\n * conveyed only through color/icon.\n */\n stepStatusLabel(state: StepState): string {\n switch (state) {\n case 'done':\n return 'completed';\n case 'active':\n return 'in progress';\n case 'error':\n return 'failed';\n case 'warning':\n return 'needs attention';\n default:\n return 'pending';\n }\n }\n\n readonly resultIcon = computed<string>(() => {\n switch (this.status()) {\n case 'error':\n return 'xmark';\n case 'warning':\n return 'triangle-exclamation';\n default:\n return 'check';\n }\n });\n\n readonly resultColor = computed<'success' | 'danger' | 'warning'>(() => {\n switch (this.status()) {\n case 'error':\n return 'danger';\n case 'warning':\n return 'warning';\n default:\n return 'success';\n }\n });\n\n /** Severity for the message box wrapping `description`/`errors` (success has no box). */\n readonly resultMessageSeverity = computed<'error' | 'warn'>(() =>\n this.status() === 'error' ? 'error' : 'warn'\n );\n\n /** `countdownLabel` with `{seconds}` filled in, or `undefined` while the countdown is disabled. */\n readonly countdownText = computed<string | undefined>(() => {\n const seconds = this.remainingSeconds();\n if (seconds === undefined) {\n return undefined;\n }\n return this.countdownLabel().replace('{seconds}', String(seconds));\n });\n}\n","<output class=\"tk-process-steps\">\n @if (status() === 'progress') {\n <div class=\"tk-process-steps__spinner-wrapper\" aria-hidden=\"true\">\n <p-progressSpinner\n class=\"tk-process-steps__spinner-progress\"\n strokeWidth=\"3\"\n animationDuration=\"1s\" />\n <tk-icon\n [icon]=\"icon()\"\n styleIcon=\"fal\"\n size=\"lg\"\n class=\"tk-process-steps__spinner-icon\" />\n </div>\n <h3 class=\"tk-process-steps__title\">{{ title() }}</h3>\n @if (description()) {\n <p class=\"tk-process-steps__description\">{{ description() }}</p>\n }\n <ul class=\"tk-process-steps__steps\">\n @for (step of steps(); track step.label) {\n <li\n class=\"tk-process-steps__step\"\n [class.tk-process-steps__step--active]=\"step.state === 'active'\"\n [class.tk-process-steps__step--done]=\"step.state === 'done'\"\n [class.tk-process-steps__step--error]=\"step.state === 'error'\"\n [class.tk-process-steps__step--warning]=\"step.state === 'warning'\"\n [attr.aria-current]=\"step.state === 'active' ? 'step' : null\">\n @switch (step.state) {\n @case ('done') {\n <tk-icon\n icon=\"circle-check\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"success\"\n class=\"tk-process-steps__step-icon--done\"\n aria-hidden=\"true\" />\n }\n @case ('error') {\n <tk-icon\n icon=\"circle-xmark\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"danger\"\n class=\"tk-process-steps__step-icon--error\"\n aria-hidden=\"true\" />\n }\n @case ('warning') {\n <tk-icon\n icon=\"triangle-exclamation\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"warning\"\n class=\"tk-process-steps__step-icon--warning\"\n aria-hidden=\"true\" />\n }\n @case ('active') {\n <span class=\"tk-process-steps__step-spinner\" aria-hidden=\"true\">\n <p-progressSpinner strokeWidth=\"5\" animationDuration=\"0.8s\" />\n </span>\n }\n @default {\n <span class=\"tk-process-steps__step-dot\" aria-hidden=\"true\"></span>\n }\n }\n <span class=\"tk-process-steps__step-label\">\n {{ step.label }}\n <span class=\"tk-process-steps__sr-only\">({{ stepStatusLabel(step.state) }})</span>\n </span>\n </li>\n }\n </ul>\n } @else {\n <div\n class=\"tk-process-steps__result-circle\"\n [class.tk-process-steps__result-circle--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-circle--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-circle--warning]=\"status() === 'warning'\">\n <tk-icon\n [icon]=\"resultIcon()\"\n styleIcon=\"fal\"\n size=\"2x\"\n [color]=\"resultColor()\"\n aria-hidden=\"true\" />\n </div>\n <h3\n class=\"tk-process-steps__result-title\"\n [class.tk-process-steps__result-title--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-title--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-title--warning]=\"status() === 'warning'\">\n {{ title() }}\n </h3>\n\n @if (status() === 'success') {\n @if (description()) {\n <p class=\"tk-process-steps__result-description\">{{ description() }}</p>\n }\n } @else if (errors().length || description()) {\n <tk-message [severity]=\"resultMessageSeverity()\" class=\"tk-process-steps__result-message\">\n @if (errors().length) {\n <ul class=\"tk-process-steps__result-errors\">\n @for (error of errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n } @else {\n {{ description() }}\n }\n </tk-message>\n }\n\n @if (countdownText(); as countdownText) {\n <p\n class=\"tk-process-steps__result-countdown\"\n [class.tk-process-steps__result-countdown--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-countdown--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-countdown--warning]=\"status() === 'warning'\">\n {{ countdownText }}\n </p>\n }\n }\n</output>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tekus-design-system-components-process-steps.mjs","sources":["../../../projects/design-system/components/process-steps/src/process-steps.component.ts","../../../projects/design-system/components/process-steps/src/process-steps.component.html","../../../projects/design-system/components/process-steps/tekus-design-system-components-process-steps.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n EffectCleanupRegisterFn,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { ProgressSpinner } from 'primeng/progressspinner';\nimport { IconComponent } from '@tekus/design-system/components/icon';\nimport { MessageComponent } from '@tekus/design-system/components/message';\nimport { ProcessStep, ProcessStepsStatus, StepState } from './process-steps.types';\n\n@Component({\n selector: 'tk-process-steps',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [ProgressSpinner, IconComponent, MessageComponent],\n templateUrl: './process-steps.component.html',\n styleUrl: './process-steps.component.scss'\n})\nexport class ProcessStepsComponent {\n readonly steps = input<ProcessStep[]>([]);\n readonly title = input.required<string>();\n readonly description = input<string>();\n readonly icon = input<string>('gears');\n readonly status = input<ProcessStepsStatus>('progress');\n\n /** Whether to show the spinner + icon header while `status` is `progress`. */\n readonly showIcon = input<boolean>(true);\n\n /**\n * Strips the panel down to just the step list: no padding, and no\n * `title`/`description` header while `status` is `progress` — for hosts\n * that provide their own framing (e.g. a card) and already show the file\n * name elsewhere. The final result view (`success`/`error`/`warning`)\n * still shows its own title/message, since that's the only place the\n * outcome text is surfaced.\n */\n readonly compact = input<boolean>(false);\n\n /** Specific problems to list inside the result message box (ignored when `status` is `success`). */\n readonly errors = input<string[]>([]);\n\n /** Seconds until the countdown finishes; omit to disable it. */\n readonly countdownSeconds = input<number>();\n\n /**\n * Countdown text; `{seconds}` is replaced with the seconds left. Defaults to a \"closing\"\n * message, but the countdown isn't only for closing — override it to match what\n * `(countdownFinished)` actually does.\n */\n readonly countdownLabel = input<string>('Closing in {seconds}s…');\n\n /** Emitted once when the countdown reaches zero — the consumer decides what happens next (close a modal, show a toast, etc.). */\n readonly countdownFinished = output<void>();\n\n /** Seconds left in the countdown, or `undefined` while it's disabled. */\n readonly remainingSeconds = signal<number | undefined>(undefined);\n\n constructor() {\n effect(onCleanup => this.runCountdown(onCleanup));\n }\n\n /** Starts (or disables) the countdown whenever `status`/`countdownSeconds` change. */\n private runCountdown(onCleanup: EffectCleanupRegisterFn): void {\n const total = this.countdownSeconds();\n if (this.status() === 'progress' || !total) {\n this.remainingSeconds.set(undefined);\n return;\n }\n\n this.remainingSeconds.set(total);\n const intervalId = setInterval(() => this.tickCountdown(intervalId), 1000);\n onCleanup(() => clearInterval(intervalId));\n }\n\n /** Decrements `remainingSeconds` by one and emits `countdownFinished` once it bottoms out. */\n private tickCountdown(intervalId: ReturnType<typeof setInterval>): void {\n const next = (this.remainingSeconds() ?? 1) - 1;\n this.remainingSeconds.set(Math.max(next, 0));\n if (next <= 0) {\n clearInterval(intervalId);\n this.countdownFinished.emit();\n }\n }\n\n /**\n * Accessible suffix announced per step since state is otherwise\n * conveyed only through color/icon.\n */\n stepStatusLabel(state: StepState): string {\n switch (state) {\n case 'done':\n return 'completed';\n case 'active':\n return 'in progress';\n case 'error':\n return 'failed';\n case 'warning':\n return 'needs attention';\n default:\n return 'pending';\n }\n }\n\n readonly resultIcon = computed<string>(() => {\n switch (this.status()) {\n case 'error':\n return 'xmark';\n case 'warning':\n return 'triangle-exclamation';\n default:\n return 'check';\n }\n });\n\n readonly resultColor = computed<'success' | 'danger' | 'warning'>(() => {\n switch (this.status()) {\n case 'error':\n return 'danger';\n case 'warning':\n return 'warning';\n default:\n return 'success';\n }\n });\n\n /** Severity for the message box wrapping `description`/`errors` (success has no box). */\n readonly resultMessageSeverity = computed<'error' | 'warn'>(() =>\n this.status() === 'error' ? 'error' : 'warn'\n );\n\n /** Severity for the compact terminal banner (`tk-message`) — unlike `resultMessageSeverity`, success gets its own box here. */\n readonly bannerSeverity = computed<'success' | 'error' | 'warn'>(() => {\n if (this.status() === 'error') {\n return 'error';\n }\n if (this.status() === 'warning') {\n return 'warn';\n }\n return 'success';\n });\n\n /** `countdownLabel` with `{seconds}` filled in, or `undefined` while the countdown is disabled. */\n readonly countdownText = computed<string | undefined>(() => {\n const seconds = this.remainingSeconds();\n if (seconds === undefined) {\n return undefined;\n }\n return this.countdownLabel().replace('{seconds}', String(seconds));\n });\n}\n","<output class=\"tk-process-steps\" [class.tk-process-steps--compact]=\"compact()\">\n @if (status() === 'progress' && showIcon()) {\n <div class=\"tk-process-steps__spinner-wrapper\" aria-hidden=\"true\">\n <p-progressSpinner\n class=\"tk-process-steps__spinner-progress\"\n strokeWidth=\"3\"\n animationDuration=\"1s\" />\n <tk-icon\n [icon]=\"icon()\"\n styleIcon=\"fal\"\n size=\"lg\"\n class=\"tk-process-steps__spinner-icon\" />\n </div>\n }\n\n @if (status() === 'progress' && !compact()) {\n <h3 class=\"tk-process-steps__title\">{{ title() }}</h3>\n @if (description()) {\n <p class=\"tk-process-steps__description\">{{ description() }}</p>\n }\n }\n\n @if (status() === 'progress' || compact()) {\n <ul class=\"tk-process-steps__steps\">\n @for (step of steps(); track step.label) {\n <li\n class=\"tk-process-steps__step\"\n [class.tk-process-steps__step--active]=\"step.state === 'active'\"\n [class.tk-process-steps__step--done]=\"step.state === 'done'\"\n [class.tk-process-steps__step--error]=\"step.state === 'error'\"\n [class.tk-process-steps__step--warning]=\"step.state === 'warning'\"\n [attr.aria-current]=\"step.state === 'active' ? 'step' : null\">\n <span\n class=\"tk-process-steps__step-icon-wrapper\"\n [class.tk-process-steps__step-icon-wrapper--done]=\"step.state === 'done'\"\n [class.tk-process-steps__step-icon-wrapper--error]=\"step.state === 'error'\"\n [class.tk-process-steps__step-icon-wrapper--warning]=\"step.state === 'warning'\">\n @switch (step.state) {\n @case ('done') {\n <tk-icon\n icon=\"circle-check\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"success\"\n class=\"tk-process-steps__step-icon--done\"\n aria-hidden=\"true\" />\n }\n @case ('error') {\n <tk-icon\n icon=\"circle-xmark\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"danger\"\n class=\"tk-process-steps__step-icon--error\"\n aria-hidden=\"true\" />\n }\n @case ('warning') {\n <tk-icon\n icon=\"triangle-exclamation\"\n styleIcon=\"fal\"\n size=\"1x\"\n color=\"warning\"\n class=\"tk-process-steps__step-icon--warning\"\n aria-hidden=\"true\" />\n }\n @case ('active') {\n <span class=\"tk-process-steps__step-spinner\" aria-hidden=\"true\">\n <p-progressSpinner strokeWidth=\"5\" animationDuration=\"0.8s\" />\n </span>\n }\n @default {\n <span class=\"tk-process-steps__step-dot\" aria-hidden=\"true\"></span>\n }\n }\n </span>\n <span class=\"tk-process-steps__step-content\">\n <span class=\"tk-process-steps__step-label\">\n {{ step.label }}\n <span class=\"tk-process-steps__sr-only\">({{ stepStatusLabel(step.state) }})</span>\n </span>\n @if (step.description) {\n <span class=\"tk-process-steps__step-description\">{{ step.description }}</span>\n }\n </span>\n </li>\n }\n </ul>\n }\n\n @if (status() !== 'progress') {\n @if (compact()) {\n @if (errors().length || description()) {\n <tk-message [severity]=\"bannerSeverity()\" class=\"tk-process-steps__banner\">\n @if (errors().length) {\n <ul class=\"tk-process-steps__result-errors\">\n @for (error of errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n } @else {\n {{ description() }}\n }\n </tk-message>\n }\n } @else {\n <div\n class=\"tk-process-steps__result-circle\"\n [class.tk-process-steps__result-circle--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-circle--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-circle--warning]=\"status() === 'warning'\">\n <tk-icon\n [icon]=\"resultIcon()\"\n styleIcon=\"fal\"\n size=\"2x\"\n [color]=\"resultColor()\"\n aria-hidden=\"true\" />\n </div>\n <h3\n class=\"tk-process-steps__result-title\"\n [class.tk-process-steps__result-title--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-title--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-title--warning]=\"status() === 'warning'\">\n {{ title() }}\n </h3>\n\n @if (status() === 'success') {\n @if (description()) {\n <p class=\"tk-process-steps__result-description\">{{ description() }}</p>\n }\n } @else if (errors().length || description()) {\n <tk-message [severity]=\"resultMessageSeverity()\" class=\"tk-process-steps__result-message\">\n @if (errors().length) {\n <ul class=\"tk-process-steps__result-errors\">\n @for (error of errors(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n } @else {\n {{ description() }}\n }\n </tk-message>\n }\n }\n\n @if (countdownText(); as countdownText) {\n <p\n class=\"tk-process-steps__result-countdown\"\n [class.tk-process-steps__result-countdown--success]=\"status() === 'success'\"\n [class.tk-process-steps__result-countdown--error]=\"status() === 'error'\"\n [class.tk-process-steps__result-countdown--warning]=\"status() === 'warning'\">\n {{ countdownText }}\n </p>\n }\n }\n</output>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, inject, ChangeDetectorRef, input, output, HostListener, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { CommonModule } from '@angular/common';
4
3
  import { BehaviorSubject, Subscription } from 'rxjs';
5
4
  import { BreakpointObserver } from '@angular/cdk/layout';
6
5
  import { ButtonComponent } from '@tekus/design-system/components/button';
6
+ import { HeaderComponent } from '@tekus/design-system/components/header';
7
7
 
8
8
  class SidebarService {
9
9
  constructor() {
@@ -58,6 +58,10 @@ class SidebarLayoutComponent {
58
58
  * If provided, it overrides the service state.
59
59
  */
60
60
  this.isCollapsed = input(undefined, ...(ngDevMode ? [{ debugName: "isCollapsed" }] : /* istanbul ignore next */ []));
61
+ /**
62
+ * Actions rendered in the right zone of the header via tk-header.
63
+ */
64
+ this.headerActions = input([], ...(ngDevMode ? [{ debugName: "headerActions" }] : /* istanbul ignore next */ []));
61
65
  /**
62
66
  * Emitted when the collapsed state changes.
63
67
  */
@@ -108,6 +112,16 @@ class SidebarLayoutComponent {
108
112
  get displayCollapsed() {
109
113
  return this.isCollapsed() === undefined ? this.collapsed : this.isCollapsed();
110
114
  }
115
+ /**
116
+ * Returns the left actions for tk-header: includes the toggle button
117
+ * only when the sidebar is collapsed or in tablet/mobile mode.
118
+ */
119
+ get headerLeftActions() {
120
+ if (this.displayCollapsed || this.isTablet) {
121
+ return [{ icon: 'bars', label: 'Toggle sidebar', action: () => this.toggleSidebar() }];
122
+ }
123
+ return [];
124
+ }
111
125
  /**
112
126
  * Toggles the sidebar state.
113
127
  */
@@ -158,15 +172,15 @@ class SidebarLayoutComponent {
158
172
  this.closeSidebar();
159
173
  }
160
174
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SidebarLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
161
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SidebarLayoutComponent, isStandalone: true, selector: "tk-sidebar-layout", inputs: { isCollapsed: { classPropertyName: "isCollapsed", publicName: "isCollapsed", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsedChange: "collapsedChange" }, host: { listeners: { "click": "handleSidebarContentClick($event)" } }, ngImport: i0, template: "<div\n class=\"tk-sidebar-layout\"\n [class.collapsed]=\"displayCollapsed\"\n [class.is-tablet]=\"isTablet\"\n [class.is-mobile]=\"isMobile\"\n>\n <!-- Backdrop for overlay mode -->\n @if (!displayCollapsed && isTablet) {\n <tk-button\n class=\"tk-sidebar-backdrop\"\n (clicked)=\"handleBackdropClick()\"\n aria-label=\"Close sidebar\"\n ></tk-button>\n }\n\n <!-- Sidebar -->\n <aside class=\"tk-sidebar\">\n @if (!displayCollapsed) {\n <div class=\"tk-sidebar-header\">\n <img\n src=\"assets/img/tk-logo-normal-light.svg\"\n alt=\"Tekus Logo\"\n class=\"tk-logo-expanded\"\n />\n <tk-button\n class=\"tk-sidebar-toggle is-sidebar\"\n (clicked)=\"toggleSidebar()\"\n severity=\"secondary\"\n variant=\"text\"\n icon=\"arrow-left\"\n ></tk-button>\n </div>\n }\n\n <ng-content select=\"[sidebar-content]\"></ng-content>\n </aside>\n\n <!-- Main Content -->\n <div class=\"tk-main-container\">\n <header class=\"tk-nav-header\">\n <div class=\"tk-nav-left\">\n @if (displayCollapsed || isTablet) {\n <tk-button\n class=\"tk-sidebar-toggle\"\n (clicked)=\"toggleSidebar()\"\n severity=\"secondary\"\n variant=\"text\"\n icon=\"bars\"\n ></tk-button>\n <img\n src=\"assets/img/tk-logo-normal-dark.svg\"\n alt=\"Tekus Logo\"\n class=\"tk-logo-header\"\n />\n }\n </div>\n\n <div class=\"tk-nav-right\">\n <div class=\"tk-header-actions\">\n <ng-content select=\"[header-actions]\"></ng-content>\n </div>\n </div>\n </header>\n\n <main class=\"tk-content\">\n <ng-content></ng-content>\n </main>\n </div>\n</div>\n", styles: [":host{display:block;height:100vh;width:100%}.tk-sidebar-layout{display:flex;height:100%;width:100%;overflow:hidden;position:relative}.tk-sidebar-layout .tk-sidebar-backdrop{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:999;cursor:pointer;animation:fadeIn .3s ease-in-out;display:block}.tk-sidebar-layout .tk-sidebar-backdrop::ng-deep .p-button{width:100%!important;height:100%!important;background-color:#00000080!important;border:none!important;padding:0!important;border-radius:0!important;box-shadow:none!important}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.tk-sidebar-layout .tk-sidebar{background-color:var(--tk-color-background-inverse, #191a1b);color:var(--tk-color-text-inverse, #ffffff);width:var(--tk-sidebar-width, 17.5rem);height:100%;display:flex;flex-direction:column;transition:width .3s ease-in-out,transform .3s ease-in-out;flex-shrink:0;overflow-y:auto;overflow-x:hidden}.tk-sidebar-layout .tk-sidebar::-webkit-scrollbar{width:.25rem}.tk-sidebar-layout .tk-sidebar::-webkit-scrollbar-thumb{background:var(--tk-color-base-surface-700, #424243);border-radius:.125rem}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header{padding:0 var(--tk-spacing-padding-m, 1rem);display:flex;align-items:center;justify-content:space-between;height:3.5rem;flex-shrink:0}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header .tk-logo-expanded{height:1.5rem;width:auto}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header .tk-logo-collapsed{height:2.5rem;width:auto}.tk-sidebar-layout .tk-sidebar .tk-sidebar-menu{flex:1;padding:var(--tk-spacing-padding-m, 1rem)}.tk-sidebar-layout .tk-main-container{flex:1;display:flex;flex-direction:column;min-width:0;background-color:var(--tk-color-background-default, #ffffff)}.tk-sidebar-layout .tk-sidebar-toggle{appearance:none;background:none;border:none;box-shadow:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;color:var(--tk-color-text-default, #191a1b);border-radius:var(--tk-borderRadius-s, .5rem);transition:all .2s;min-width:unset}.tk-sidebar-layout .tk-sidebar-toggle::ng-deep .p-button{background:none!important;border:none!important;padding:var(--tk-spacing-padding-xs, .25rem)!important;min-width:unset!important;height:auto!important;color:inherit!important;box-shadow:none!important}.tk-sidebar-layout .tk-sidebar-toggle::ng-deep .p-button:hover{background-color:var(--tk-color-background-soft, #f2f1f1)!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar{color:#fff!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button{color:#fff!important;background:transparent!important;padding:0!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button:hover{background-color:transparent!important;opacity:.7}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button ::ng-deep svg,.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button ::ng-deep path{fill:currentColor!important;stroke:currentColor!important}.tk-sidebar-layout .tk-nav-header{height:3.5rem;background-color:var(--tk-color-background-default, #ffffff);display:flex;align-items:center;justify-content:space-between;padding:0 var(--tk-spacing-padding-m, 1rem);border-bottom:1px solid var(--tk-color-border-subtle, #e4e4e4);flex-shrink:0}.tk-sidebar-layout .tk-nav-header .tk-nav-left{display:flex;align-items:center;gap:var(--tk-spacing-gap-m, 1rem)}.tk-sidebar-layout .tk-nav-header .tk-logo-header{height:1.75rem;width:auto;margin-left:var(--tk-spacing-padding-s, .5rem)}.tk-sidebar-layout .tk-nav-header .tk-nav-right{display:flex;align-items:center}.tk-sidebar-layout .tk-nav-header .tk-header-actions{display:flex;align-items:center;gap:var(--tk-spacing-gap-s, .5rem)}.tk-sidebar-layout .tk-nav-header ::ng-deep .tk-header-action-btn{background:transparent;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:var(--tk-spacing-padding-s, .5rem);color:var(--tk-color-primary-default, #16006f);border-radius:50%;transition:background-color .2s}.tk-sidebar-layout .tk-nav-header ::ng-deep .tk-header-action-btn:hover{background-color:var(--tk-color-background-soft, #f2f1f1)}.tk-sidebar-layout .tk-content{flex:1;overflow-y:auto;padding:var(--tk-spacing-padding-l, 1.25rem)}.tk-sidebar-layout.collapsed:not(.is-tablet) .tk-sidebar{width:0;border-right:none}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-label,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-panelmenu-header-label,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-chevron,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-icon{display:none!important}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-link,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-panelmenu-header{justify-content:center;padding-left:0!important;padding-right:0!important}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-content{justify-content:center}.tk-sidebar-layout.is-tablet .tk-sidebar{position:fixed;left:0;top:0;bottom:0;z-index:1000;width:var(--tk-sidebar-width, 17.5rem)!important;transform:translate(0);box-shadow:4px 0 10px #0000001a}.tk-sidebar-layout.is-tablet.collapsed .tk-sidebar{transform:translate(-100%)}.tk-sidebar-layout.is-tablet .tk-main-container{width:100%;flex:1}.tk-sidebar-layout.is-mobile .tk-sidebar{width:100%!important;max-width:none!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ButtonComponent, selector: "tk-button", inputs: ["label", "disabled", "type", "severity", "variant", "link", "icon", "iconPosition", "tooltipText", "full", "ariaLabel", "size"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
175
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SidebarLayoutComponent, isStandalone: true, selector: "tk-sidebar-layout", inputs: { isCollapsed: { classPropertyName: "isCollapsed", publicName: "isCollapsed", isSignal: true, isRequired: false, transformFunction: null }, headerActions: { classPropertyName: "headerActions", publicName: "headerActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsedChange: "collapsedChange" }, host: { listeners: { "click": "handleSidebarContentClick($event)" } }, ngImport: i0, template: "<div\n class=\"tk-sidebar-layout\"\n [class.collapsed]=\"displayCollapsed\"\n [class.is-tablet]=\"isTablet\"\n [class.is-mobile]=\"isMobile\"\n>\n <!-- Backdrop for overlay mode -->\n @if (!displayCollapsed && isTablet) {\n <tk-button\n class=\"tk-sidebar-backdrop\"\n (clicked)=\"handleBackdropClick()\"\n aria-label=\"Close sidebar\"\n ></tk-button>\n }\n\n <!-- Sidebar -->\n <aside class=\"tk-sidebar\">\n @if (!displayCollapsed) {\n <div class=\"tk-sidebar-header\">\n <img\n src=\"assets/img/tk-logo-normal-light.svg\"\n alt=\"Tekus Logo\"\n class=\"tk-logo-expanded\"\n />\n <tk-button\n class=\"tk-sidebar-toggle is-sidebar\"\n (clicked)=\"toggleSidebar()\"\n severity=\"secondary\"\n variant=\"text\"\n icon=\"arrow-left\"\n ></tk-button>\n </div>\n }\n\n <ng-content select=\"[sidebar-content]\"></ng-content>\n </aside>\n\n <!-- Main Content -->\n <div class=\"tk-main-container\">\n <tk-header\n [logoSrc]=\"(displayCollapsed || isTablet) ? 'assets/img/tk-logo-normal-dark.svg' : undefined\"\n logoAlt=\"Tekus Logo\"\n [leftActions]=\"headerLeftActions\"\n [rightActions]=\"headerActions()\">\n </tk-header>\n\n <main class=\"tk-content\">\n <ng-content></ng-content>\n </main>\n </div>\n</div>\n", styles: [":host{display:block;height:100vh;width:100%}.tk-sidebar-layout{display:flex;height:100%;width:100%;overflow:hidden;position:relative}.tk-sidebar-layout .tk-sidebar-backdrop{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:999;cursor:pointer;animation:fadeIn .3s ease-in-out;display:block}.tk-sidebar-layout .tk-sidebar-backdrop::ng-deep .p-button{width:100%!important;height:100%!important;background-color:#00000080!important;border:none!important;padding:0!important;border-radius:0!important;box-shadow:none!important}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.tk-sidebar-layout .tk-sidebar{background-color:var(--tk-color-background-inverse, #191a1b);color:var(--tk-color-text-inverse, #ffffff);width:var(--tk-sidebar-width, 17.5rem);height:100%;display:flex;flex-direction:column;transition:width .3s ease-in-out,transform .3s ease-in-out;flex-shrink:0;overflow-y:auto;overflow-x:hidden}.tk-sidebar-layout .tk-sidebar::-webkit-scrollbar{width:.25rem}.tk-sidebar-layout .tk-sidebar::-webkit-scrollbar-thumb{background:var(--tk-color-base-surface-700, #424243);border-radius:.125rem}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header{padding:0 var(--tk-spacing-padding-m, 1rem);display:flex;align-items:center;justify-content:space-between;height:3.5rem;flex-shrink:0}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header .tk-logo-expanded{height:1.5rem;width:auto}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header .tk-logo-collapsed{height:2.5rem;width:auto}.tk-sidebar-layout .tk-sidebar .tk-sidebar-menu{flex:1;padding:var(--tk-spacing-padding-m, 1rem)}.tk-sidebar-layout .tk-main-container{flex:1;display:flex;flex-direction:column;min-width:0;background-color:var(--tk-color-background-default, #ffffff)}.tk-sidebar-layout .tk-main-container tk-header{border-bottom:1px solid var(--tk-color-border-subtle, #e4e4e4);flex-shrink:0}.tk-sidebar-layout .tk-sidebar-toggle{appearance:none;background:none;border:none;box-shadow:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;color:var(--tk-color-text-default, #191a1b);border-radius:var(--tk-borderRadius-s, .5rem);transition:all .2s;min-width:unset}.tk-sidebar-layout .tk-sidebar-toggle::ng-deep .p-button{background:none!important;border:none!important;padding:var(--tk-spacing-padding-xs, .25rem)!important;min-width:unset!important;height:auto!important;color:inherit!important;box-shadow:none!important}.tk-sidebar-layout .tk-sidebar-toggle::ng-deep .p-button:hover{background-color:var(--tk-color-background-soft, #f2f1f1)!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar{color:#fff!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button{color:#fff!important;background:transparent!important;padding:0!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button:hover{background-color:transparent!important;opacity:.7}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button ::ng-deep svg,.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button ::ng-deep path{fill:currentColor!important;stroke:currentColor!important}.tk-sidebar-layout .tk-content{flex:1;overflow-y:auto;padding:var(--tk-spacing-padding-l, 1.25rem)}.tk-sidebar-layout.collapsed:not(.is-tablet) .tk-sidebar{width:0;border-right:none}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-label,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-panelmenu-header-label,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-chevron,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-icon{display:none!important}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-link,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-panelmenu-header{justify-content:center;padding-left:0!important;padding-right:0!important}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-content{justify-content:center}.tk-sidebar-layout.is-tablet .tk-sidebar{position:fixed;left:0;top:0;bottom:0;z-index:1000;width:var(--tk-sidebar-width, 17.5rem)!important;transform:translate(0);box-shadow:4px 0 10px #0000001a}.tk-sidebar-layout.is-tablet.collapsed .tk-sidebar{transform:translate(-100%)}.tk-sidebar-layout.is-tablet .tk-main-container{width:100%;flex:1}.tk-sidebar-layout.is-mobile .tk-sidebar{width:100%!important;max-width:none!important}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "tk-button", inputs: ["label", "disabled", "type", "severity", "variant", "link", "icon", "iconPosition", "tooltipText", "full", "ariaLabel", "size"], outputs: ["clicked"] }, { kind: "component", type: HeaderComponent, selector: "tk-header", inputs: ["logoSrc", "logoAlt", "leftActions", "rightActions"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
162
176
  }
163
177
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SidebarLayoutComponent, decorators: [{
164
178
  type: Component,
165
179
  args: [{ selector: 'tk-sidebar-layout', imports: [
166
- CommonModule,
167
- ButtonComponent
168
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"tk-sidebar-layout\"\n [class.collapsed]=\"displayCollapsed\"\n [class.is-tablet]=\"isTablet\"\n [class.is-mobile]=\"isMobile\"\n>\n <!-- Backdrop for overlay mode -->\n @if (!displayCollapsed && isTablet) {\n <tk-button\n class=\"tk-sidebar-backdrop\"\n (clicked)=\"handleBackdropClick()\"\n aria-label=\"Close sidebar\"\n ></tk-button>\n }\n\n <!-- Sidebar -->\n <aside class=\"tk-sidebar\">\n @if (!displayCollapsed) {\n <div class=\"tk-sidebar-header\">\n <img\n src=\"assets/img/tk-logo-normal-light.svg\"\n alt=\"Tekus Logo\"\n class=\"tk-logo-expanded\"\n />\n <tk-button\n class=\"tk-sidebar-toggle is-sidebar\"\n (clicked)=\"toggleSidebar()\"\n severity=\"secondary\"\n variant=\"text\"\n icon=\"arrow-left\"\n ></tk-button>\n </div>\n }\n\n <ng-content select=\"[sidebar-content]\"></ng-content>\n </aside>\n\n <!-- Main Content -->\n <div class=\"tk-main-container\">\n <header class=\"tk-nav-header\">\n <div class=\"tk-nav-left\">\n @if (displayCollapsed || isTablet) {\n <tk-button\n class=\"tk-sidebar-toggle\"\n (clicked)=\"toggleSidebar()\"\n severity=\"secondary\"\n variant=\"text\"\n icon=\"bars\"\n ></tk-button>\n <img\n src=\"assets/img/tk-logo-normal-dark.svg\"\n alt=\"Tekus Logo\"\n class=\"tk-logo-header\"\n />\n }\n </div>\n\n <div class=\"tk-nav-right\">\n <div class=\"tk-header-actions\">\n <ng-content select=\"[header-actions]\"></ng-content>\n </div>\n </div>\n </header>\n\n <main class=\"tk-content\">\n <ng-content></ng-content>\n </main>\n </div>\n</div>\n", styles: [":host{display:block;height:100vh;width:100%}.tk-sidebar-layout{display:flex;height:100%;width:100%;overflow:hidden;position:relative}.tk-sidebar-layout .tk-sidebar-backdrop{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:999;cursor:pointer;animation:fadeIn .3s ease-in-out;display:block}.tk-sidebar-layout .tk-sidebar-backdrop::ng-deep .p-button{width:100%!important;height:100%!important;background-color:#00000080!important;border:none!important;padding:0!important;border-radius:0!important;box-shadow:none!important}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.tk-sidebar-layout .tk-sidebar{background-color:var(--tk-color-background-inverse, #191a1b);color:var(--tk-color-text-inverse, #ffffff);width:var(--tk-sidebar-width, 17.5rem);height:100%;display:flex;flex-direction:column;transition:width .3s ease-in-out,transform .3s ease-in-out;flex-shrink:0;overflow-y:auto;overflow-x:hidden}.tk-sidebar-layout .tk-sidebar::-webkit-scrollbar{width:.25rem}.tk-sidebar-layout .tk-sidebar::-webkit-scrollbar-thumb{background:var(--tk-color-base-surface-700, #424243);border-radius:.125rem}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header{padding:0 var(--tk-spacing-padding-m, 1rem);display:flex;align-items:center;justify-content:space-between;height:3.5rem;flex-shrink:0}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header .tk-logo-expanded{height:1.5rem;width:auto}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header .tk-logo-collapsed{height:2.5rem;width:auto}.tk-sidebar-layout .tk-sidebar .tk-sidebar-menu{flex:1;padding:var(--tk-spacing-padding-m, 1rem)}.tk-sidebar-layout .tk-main-container{flex:1;display:flex;flex-direction:column;min-width:0;background-color:var(--tk-color-background-default, #ffffff)}.tk-sidebar-layout .tk-sidebar-toggle{appearance:none;background:none;border:none;box-shadow:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;color:var(--tk-color-text-default, #191a1b);border-radius:var(--tk-borderRadius-s, .5rem);transition:all .2s;min-width:unset}.tk-sidebar-layout .tk-sidebar-toggle::ng-deep .p-button{background:none!important;border:none!important;padding:var(--tk-spacing-padding-xs, .25rem)!important;min-width:unset!important;height:auto!important;color:inherit!important;box-shadow:none!important}.tk-sidebar-layout .tk-sidebar-toggle::ng-deep .p-button:hover{background-color:var(--tk-color-background-soft, #f2f1f1)!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar{color:#fff!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button{color:#fff!important;background:transparent!important;padding:0!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button:hover{background-color:transparent!important;opacity:.7}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button ::ng-deep svg,.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button ::ng-deep path{fill:currentColor!important;stroke:currentColor!important}.tk-sidebar-layout .tk-nav-header{height:3.5rem;background-color:var(--tk-color-background-default, #ffffff);display:flex;align-items:center;justify-content:space-between;padding:0 var(--tk-spacing-padding-m, 1rem);border-bottom:1px solid var(--tk-color-border-subtle, #e4e4e4);flex-shrink:0}.tk-sidebar-layout .tk-nav-header .tk-nav-left{display:flex;align-items:center;gap:var(--tk-spacing-gap-m, 1rem)}.tk-sidebar-layout .tk-nav-header .tk-logo-header{height:1.75rem;width:auto;margin-left:var(--tk-spacing-padding-s, .5rem)}.tk-sidebar-layout .tk-nav-header .tk-nav-right{display:flex;align-items:center}.tk-sidebar-layout .tk-nav-header .tk-header-actions{display:flex;align-items:center;gap:var(--tk-spacing-gap-s, .5rem)}.tk-sidebar-layout .tk-nav-header ::ng-deep .tk-header-action-btn{background:transparent;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:var(--tk-spacing-padding-s, .5rem);color:var(--tk-color-primary-default, #16006f);border-radius:50%;transition:background-color .2s}.tk-sidebar-layout .tk-nav-header ::ng-deep .tk-header-action-btn:hover{background-color:var(--tk-color-background-soft, #f2f1f1)}.tk-sidebar-layout .tk-content{flex:1;overflow-y:auto;padding:var(--tk-spacing-padding-l, 1.25rem)}.tk-sidebar-layout.collapsed:not(.is-tablet) .tk-sidebar{width:0;border-right:none}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-label,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-panelmenu-header-label,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-chevron,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-icon{display:none!important}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-link,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-panelmenu-header{justify-content:center;padding-left:0!important;padding-right:0!important}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-content{justify-content:center}.tk-sidebar-layout.is-tablet .tk-sidebar{position:fixed;left:0;top:0;bottom:0;z-index:1000;width:var(--tk-sidebar-width, 17.5rem)!important;transform:translate(0);box-shadow:4px 0 10px #0000001a}.tk-sidebar-layout.is-tablet.collapsed .tk-sidebar{transform:translate(-100%)}.tk-sidebar-layout.is-tablet .tk-main-container{width:100%;flex:1}.tk-sidebar-layout.is-mobile .tk-sidebar{width:100%!important;max-width:none!important}\n"] }]
169
- }], propDecorators: { isCollapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCollapsed", required: false }] }], collapsedChange: [{ type: i0.Output, args: ["collapsedChange"] }], handleSidebarContentClick: [{
180
+ ButtonComponent,
181
+ HeaderComponent,
182
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"tk-sidebar-layout\"\n [class.collapsed]=\"displayCollapsed\"\n [class.is-tablet]=\"isTablet\"\n [class.is-mobile]=\"isMobile\"\n>\n <!-- Backdrop for overlay mode -->\n @if (!displayCollapsed && isTablet) {\n <tk-button\n class=\"tk-sidebar-backdrop\"\n (clicked)=\"handleBackdropClick()\"\n aria-label=\"Close sidebar\"\n ></tk-button>\n }\n\n <!-- Sidebar -->\n <aside class=\"tk-sidebar\">\n @if (!displayCollapsed) {\n <div class=\"tk-sidebar-header\">\n <img\n src=\"assets/img/tk-logo-normal-light.svg\"\n alt=\"Tekus Logo\"\n class=\"tk-logo-expanded\"\n />\n <tk-button\n class=\"tk-sidebar-toggle is-sidebar\"\n (clicked)=\"toggleSidebar()\"\n severity=\"secondary\"\n variant=\"text\"\n icon=\"arrow-left\"\n ></tk-button>\n </div>\n }\n\n <ng-content select=\"[sidebar-content]\"></ng-content>\n </aside>\n\n <!-- Main Content -->\n <div class=\"tk-main-container\">\n <tk-header\n [logoSrc]=\"(displayCollapsed || isTablet) ? 'assets/img/tk-logo-normal-dark.svg' : undefined\"\n logoAlt=\"Tekus Logo\"\n [leftActions]=\"headerLeftActions\"\n [rightActions]=\"headerActions()\">\n </tk-header>\n\n <main class=\"tk-content\">\n <ng-content></ng-content>\n </main>\n </div>\n</div>\n", styles: [":host{display:block;height:100vh;width:100%}.tk-sidebar-layout{display:flex;height:100%;width:100%;overflow:hidden;position:relative}.tk-sidebar-layout .tk-sidebar-backdrop{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:999;cursor:pointer;animation:fadeIn .3s ease-in-out;display:block}.tk-sidebar-layout .tk-sidebar-backdrop::ng-deep .p-button{width:100%!important;height:100%!important;background-color:#00000080!important;border:none!important;padding:0!important;border-radius:0!important;box-shadow:none!important}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.tk-sidebar-layout .tk-sidebar{background-color:var(--tk-color-background-inverse, #191a1b);color:var(--tk-color-text-inverse, #ffffff);width:var(--tk-sidebar-width, 17.5rem);height:100%;display:flex;flex-direction:column;transition:width .3s ease-in-out,transform .3s ease-in-out;flex-shrink:0;overflow-y:auto;overflow-x:hidden}.tk-sidebar-layout .tk-sidebar::-webkit-scrollbar{width:.25rem}.tk-sidebar-layout .tk-sidebar::-webkit-scrollbar-thumb{background:var(--tk-color-base-surface-700, #424243);border-radius:.125rem}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header{padding:0 var(--tk-spacing-padding-m, 1rem);display:flex;align-items:center;justify-content:space-between;height:3.5rem;flex-shrink:0}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header .tk-logo-expanded{height:1.5rem;width:auto}.tk-sidebar-layout .tk-sidebar .tk-sidebar-header .tk-logo-collapsed{height:2.5rem;width:auto}.tk-sidebar-layout .tk-sidebar .tk-sidebar-menu{flex:1;padding:var(--tk-spacing-padding-m, 1rem)}.tk-sidebar-layout .tk-main-container{flex:1;display:flex;flex-direction:column;min-width:0;background-color:var(--tk-color-background-default, #ffffff)}.tk-sidebar-layout .tk-main-container tk-header{border-bottom:1px solid var(--tk-color-border-subtle, #e4e4e4);flex-shrink:0}.tk-sidebar-layout .tk-sidebar-toggle{appearance:none;background:none;border:none;box-shadow:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;color:var(--tk-color-text-default, #191a1b);border-radius:var(--tk-borderRadius-s, .5rem);transition:all .2s;min-width:unset}.tk-sidebar-layout .tk-sidebar-toggle::ng-deep .p-button{background:none!important;border:none!important;padding:var(--tk-spacing-padding-xs, .25rem)!important;min-width:unset!important;height:auto!important;color:inherit!important;box-shadow:none!important}.tk-sidebar-layout .tk-sidebar-toggle::ng-deep .p-button:hover{background-color:var(--tk-color-background-soft, #f2f1f1)!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar{color:#fff!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button{color:#fff!important;background:transparent!important;padding:0!important}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button:hover{background-color:transparent!important;opacity:.7}.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button ::ng-deep svg,.tk-sidebar-layout .tk-sidebar-toggle.is-sidebar::ng-deep .p-button ::ng-deep path{fill:currentColor!important;stroke:currentColor!important}.tk-sidebar-layout .tk-content{flex:1;overflow-y:auto;padding:var(--tk-spacing-padding-l, 1.25rem)}.tk-sidebar-layout.collapsed:not(.is-tablet) .tk-sidebar{width:0;border-right:none}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-label,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-panelmenu-header-label,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-chevron,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-icon{display:none!important}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-link,.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .p-panelmenu-header{justify-content:center;padding-left:0!important;padding-right:0!important}.tk-sidebar-layout.collapsed:not(.is-tablet) ::ng-deep .tk-sidebar .tk-panel-menu .tk-pm-item-content{justify-content:center}.tk-sidebar-layout.is-tablet .tk-sidebar{position:fixed;left:0;top:0;bottom:0;z-index:1000;width:var(--tk-sidebar-width, 17.5rem)!important;transform:translate(0);box-shadow:4px 0 10px #0000001a}.tk-sidebar-layout.is-tablet.collapsed .tk-sidebar{transform:translate(-100%)}.tk-sidebar-layout.is-tablet .tk-main-container{width:100%;flex:1}.tk-sidebar-layout.is-mobile .tk-sidebar{width:100%!important;max-width:none!important}\n"] }]
183
+ }], propDecorators: { isCollapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCollapsed", required: false }] }], headerActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerActions", required: false }] }], collapsedChange: [{ type: i0.Output, args: ["collapsedChange"] }], handleSidebarContentClick: [{
170
184
  type: HostListener,
171
185
  args: ['click', ['$event']]
172
186
  }] } });
@@ -1 +1 @@
1
- {"version":3,"file":"tekus-design-system-components-sidebar-layout.mjs","sources":["../../../projects/design-system/components/sidebar-layout/src/sidebar.service.ts","../../../projects/design-system/components/sidebar-layout/src/sidebar-layout.component.ts","../../../projects/design-system/components/sidebar-layout/src/sidebar-layout.component.html","../../../projects/design-system/components/sidebar-layout/tekus-design-system-components-sidebar-layout.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SidebarService {\n private readonly collapsedSubject = new BehaviorSubject<boolean>(false);\n \n /**\n * Observable to track the collapsed state of the sidebar.\n */\n isCollapsed$ = this.collapsedSubject.asObservable();\n\n /**\n * Toggles the collapsed state of the sidebar.\n */\n toggle(): void {\n this.collapsedSubject.next(!this.collapsedSubject.value);\n }\n\n /**\n * Explicitly sets the collapsed state of the sidebar.\n * @param value True to collapse, false to expand.\n */\n setCollapsed(value: boolean): void {\n this.collapsedSubject.next(value);\n }\n\n /**\n * Gets the current collapsed state.\n */\n get isCollapsed(): boolean {\n return this.collapsedSubject.value;\n }\n}\n","import { ChangeDetectionStrategy, Component, inject, input, output, OnInit, OnDestroy, ChangeDetectorRef, HostListener } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport { BreakpointObserver } from '@angular/cdk/layout';\nimport { SidebarService } from './sidebar.service';\nimport { ButtonComponent } from '@tekus/design-system/components/button';\n\n@Component({\n selector: 'tk-sidebar-layout',\n imports: [\n CommonModule,\n ButtonComponent\n ],\n templateUrl: './sidebar-layout.component.html',\n styleUrl: './sidebar-layout.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SidebarLayoutComponent implements OnInit, OnDestroy {\n private readonly sidebarService = inject(SidebarService);\n private readonly breakpointObserver = inject(BreakpointObserver);\n private readonly cdr = inject(ChangeDetectorRef);\n private readonly subscription = new Subscription();\n\n /**\n * Breakpoint constants\n */\n private readonly TABLET_BREAKPOINT = '(max-width: 1023px)';\n private readonly MOBILE_BREAKPOINT = '(max-width: 479px)';\n\n /**\n * Optional manual control of the collapsed state.\n * If provided, it overrides the service state.\n */\n isCollapsed = input<boolean | undefined>(undefined);\n\n\n /**\n * Emitted when the collapsed state changes.\n */\n collapsedChange = output<boolean>();\n\n /**\n * Internal state of the sidebar.\n */\n collapsed = false;\n\n /**\n * Responsive states\n */\n isTablet = false;\n isMobile = false;\n\n ngOnInit(): void {\n // Sync with service\n this.subscription.add(\n this.sidebarService.isCollapsed$.subscribe((state) => {\n if (this.isCollapsed() === undefined) {\n this.collapsed = state;\n this.collapsedChange.emit(state);\n this.cdr.markForCheck();\n }\n })\n );\n\n // Responsive breakpoints\n this.subscription.add(\n this.breakpointObserver\n .observe([this.TABLET_BREAKPOINT, this.MOBILE_BREAKPOINT])\n .subscribe((result) => {\n const wasTablet = this.isTablet;\n this.isTablet = result.breakpoints[this.TABLET_BREAKPOINT];\n this.isMobile = result.breakpoints[this.MOBILE_BREAKPOINT];\n\n // Auto-collapse when entering tablet/mobile mode (< 1024px)\n if (this.isTablet && !wasTablet) {\n this.sidebarService.setCollapsed(true);\n }\n\n // Auto-expand when returning to desktop mode (> 1024px)\n if (!this.isTablet && wasTablet) {\n this.sidebarService.setCollapsed(false);\n }\n\n this.cdr.markForCheck();\n })\n );\n }\n\n ngOnDestroy(): void {\n this.subscription.unsubscribe();\n }\n\n /**\n * Determines if the sidebar is currently collapsed.\n */\n get displayCollapsed(): boolean {\n return this.isCollapsed() === undefined ? this.collapsed : this.isCollapsed()!;\n }\n\n /**\n * Toggles the sidebar state.\n */\n toggleSidebar(): void {\n if (this.isCollapsed() === undefined) {\n this.sidebarService.toggle();\n } else {\n this.collapsedChange.emit(!this.isCollapsed());\n }\n }\n\n /**\n * Closes the sidebar explicitly.\n */\n closeSidebar(): void {\n if (this.isCollapsed() === undefined) {\n this.sidebarService.setCollapsed(true);\n } else {\n this.collapsedChange.emit(true);\n }\n }\n\n /**\n * Handles clicks in the sidebar content to auto-close on mobile.\n * Using HostListener to avoid template accessibility linting on non-interactive aside.\n */\n @HostListener('click', ['$event'])\n handleSidebarContentClick(event: MouseEvent): void {\n if (!this.isMobile) return;\n\n // Check if the click is inside the sidebar\n const sidebar = (event.target as HTMLElement).closest('.tk-sidebar');\n if (!sidebar) return;\n\n const target = event.target as HTMLElement;\n const navItem = target.closest('.tk-menu-item-link, .tk-pm-item-link, a, button');\n\n if (navItem) {\n // Check if it's a toggle for a sub-menu (has children)\n const hasChildren = navItem.querySelector('.tk-menu-item-chevron, .tk-pm-item-chevron');\n if (!hasChildren) {\n this.closeSidebar();\n }\n }\n }\n\n /**\n * Handles backdrop clicks to close the drawer.\n */\n handleBackdropClick(): void {\n this.closeSidebar();\n }\n}\n","<div\n class=\"tk-sidebar-layout\"\n [class.collapsed]=\"displayCollapsed\"\n [class.is-tablet]=\"isTablet\"\n [class.is-mobile]=\"isMobile\"\n>\n <!-- Backdrop for overlay mode -->\n @if (!displayCollapsed && isTablet) {\n <tk-button\n class=\"tk-sidebar-backdrop\"\n (clicked)=\"handleBackdropClick()\"\n aria-label=\"Close sidebar\"\n ></tk-button>\n }\n\n <!-- Sidebar -->\n <aside class=\"tk-sidebar\">\n @if (!displayCollapsed) {\n <div class=\"tk-sidebar-header\">\n <img\n src=\"assets/img/tk-logo-normal-light.svg\"\n alt=\"Tekus Logo\"\n class=\"tk-logo-expanded\"\n />\n <tk-button\n class=\"tk-sidebar-toggle is-sidebar\"\n (clicked)=\"toggleSidebar()\"\n severity=\"secondary\"\n variant=\"text\"\n icon=\"arrow-left\"\n ></tk-button>\n </div>\n }\n\n <ng-content select=\"[sidebar-content]\"></ng-content>\n </aside>\n\n <!-- Main Content -->\n <div class=\"tk-main-container\">\n <header class=\"tk-nav-header\">\n <div class=\"tk-nav-left\">\n @if (displayCollapsed || isTablet) {\n <tk-button\n class=\"tk-sidebar-toggle\"\n (clicked)=\"toggleSidebar()\"\n severity=\"secondary\"\n variant=\"text\"\n icon=\"bars\"\n ></tk-button>\n <img\n src=\"assets/img/tk-logo-normal-dark.svg\"\n alt=\"Tekus Logo\"\n class=\"tk-logo-header\"\n />\n }\n </div>\n\n <div class=\"tk-nav-right\">\n <div class=\"tk-header-actions\">\n <ng-content select=\"[header-actions]\"></ng-content>\n </div>\n </div>\n </header>\n\n <main class=\"tk-content\">\n <ng-content></ng-content>\n </main>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tekus-design-system-components-sidebar-layout.mjs","sources":["../../../projects/design-system/components/sidebar-layout/src/sidebar.service.ts","../../../projects/design-system/components/sidebar-layout/src/sidebar-layout.component.ts","../../../projects/design-system/components/sidebar-layout/src/sidebar-layout.component.html","../../../projects/design-system/components/sidebar-layout/tekus-design-system-components-sidebar-layout.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\nimport { BehaviorSubject } from 'rxjs';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SidebarService {\n private readonly collapsedSubject = new BehaviorSubject<boolean>(false);\n \n /**\n * Observable to track the collapsed state of the sidebar.\n */\n isCollapsed$ = this.collapsedSubject.asObservable();\n\n /**\n * Toggles the collapsed state of the sidebar.\n */\n toggle(): void {\n this.collapsedSubject.next(!this.collapsedSubject.value);\n }\n\n /**\n * Explicitly sets the collapsed state of the sidebar.\n * @param value True to collapse, false to expand.\n */\n setCollapsed(value: boolean): void {\n this.collapsedSubject.next(value);\n }\n\n /**\n * Gets the current collapsed state.\n */\n get isCollapsed(): boolean {\n return this.collapsedSubject.value;\n }\n}\n","import { ChangeDetectionStrategy, Component, inject, input, output, OnInit, OnDestroy, ChangeDetectorRef, HostListener } from '@angular/core';\nimport { Subscription } from 'rxjs';\nimport { BreakpointObserver } from '@angular/cdk/layout';\nimport { SidebarService } from './sidebar.service';\nimport { ButtonComponent } from '@tekus/design-system/components/button';\nimport { HeaderComponent, TkHeaderAction } from '@tekus/design-system/components/header';\n\n@Component({\n selector: 'tk-sidebar-layout',\n imports: [\n ButtonComponent,\n HeaderComponent,\n ],\n templateUrl: './sidebar-layout.component.html',\n styleUrl: './sidebar-layout.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SidebarLayoutComponent implements OnInit, OnDestroy {\n private readonly sidebarService = inject(SidebarService);\n private readonly breakpointObserver = inject(BreakpointObserver);\n private readonly cdr = inject(ChangeDetectorRef);\n private readonly subscription = new Subscription();\n\n /**\n * Breakpoint constants\n */\n private readonly TABLET_BREAKPOINT = '(max-width: 1023px)';\n private readonly MOBILE_BREAKPOINT = '(max-width: 479px)';\n\n /**\n * Optional manual control of the collapsed state.\n * If provided, it overrides the service state.\n */\n isCollapsed = input<boolean | undefined>(undefined);\n\n /**\n * Actions rendered in the right zone of the header via tk-header.\n */\n headerActions = input<TkHeaderAction[]>([]);\n\n /**\n * Emitted when the collapsed state changes.\n */\n collapsedChange = output<boolean>();\n\n /**\n * Internal state of the sidebar.\n */\n collapsed = false;\n\n /**\n * Responsive states\n */\n isTablet = false;\n isMobile = false;\n\n ngOnInit(): void {\n // Sync with service\n this.subscription.add(\n this.sidebarService.isCollapsed$.subscribe((state) => {\n if (this.isCollapsed() === undefined) {\n this.collapsed = state;\n this.collapsedChange.emit(state);\n this.cdr.markForCheck();\n }\n })\n );\n\n // Responsive breakpoints\n this.subscription.add(\n this.breakpointObserver\n .observe([this.TABLET_BREAKPOINT, this.MOBILE_BREAKPOINT])\n .subscribe((result) => {\n const wasTablet = this.isTablet;\n this.isTablet = result.breakpoints[this.TABLET_BREAKPOINT];\n this.isMobile = result.breakpoints[this.MOBILE_BREAKPOINT];\n\n // Auto-collapse when entering tablet/mobile mode (< 1024px)\n if (this.isTablet && !wasTablet) {\n this.sidebarService.setCollapsed(true);\n }\n\n // Auto-expand when returning to desktop mode (> 1024px)\n if (!this.isTablet && wasTablet) {\n this.sidebarService.setCollapsed(false);\n }\n\n this.cdr.markForCheck();\n })\n );\n }\n\n ngOnDestroy(): void {\n this.subscription.unsubscribe();\n }\n\n /**\n * Determines if the sidebar is currently collapsed.\n */\n get displayCollapsed(): boolean {\n return this.isCollapsed() === undefined ? this.collapsed : this.isCollapsed()!;\n }\n\n /**\n * Returns the left actions for tk-header: includes the toggle button\n * only when the sidebar is collapsed or in tablet/mobile mode.\n */\n get headerLeftActions(): TkHeaderAction[] {\n if (this.displayCollapsed || this.isTablet) {\n return [{ icon: 'bars', label: 'Toggle sidebar', action: () => this.toggleSidebar() }];\n }\n return [];\n }\n\n /**\n * Toggles the sidebar state.\n */\n toggleSidebar(): void {\n if (this.isCollapsed() === undefined) {\n this.sidebarService.toggle();\n } else {\n this.collapsedChange.emit(!this.isCollapsed());\n }\n }\n\n /**\n * Closes the sidebar explicitly.\n */\n closeSidebar(): void {\n if (this.isCollapsed() === undefined) {\n this.sidebarService.setCollapsed(true);\n } else {\n this.collapsedChange.emit(true);\n }\n }\n\n /**\n * Handles clicks in the sidebar content to auto-close on mobile.\n * Using HostListener to avoid template accessibility linting on non-interactive aside.\n */\n @HostListener('click', ['$event'])\n handleSidebarContentClick(event: MouseEvent): void {\n if (!this.isMobile) return;\n\n // Check if the click is inside the sidebar\n const sidebar = (event.target as HTMLElement).closest('.tk-sidebar');\n if (!sidebar) return;\n\n const target = event.target as HTMLElement;\n const navItem = target.closest('.tk-menu-item-link, .tk-pm-item-link, a, button');\n\n if (navItem) {\n // Check if it's a toggle for a sub-menu (has children)\n const hasChildren = navItem.querySelector('.tk-menu-item-chevron, .tk-pm-item-chevron');\n if (!hasChildren) {\n this.closeSidebar();\n }\n }\n }\n\n /**\n * Handles backdrop clicks to close the drawer.\n */\n handleBackdropClick(): void {\n this.closeSidebar();\n }\n}\n","<div\n class=\"tk-sidebar-layout\"\n [class.collapsed]=\"displayCollapsed\"\n [class.is-tablet]=\"isTablet\"\n [class.is-mobile]=\"isMobile\"\n>\n <!-- Backdrop for overlay mode -->\n @if (!displayCollapsed && isTablet) {\n <tk-button\n class=\"tk-sidebar-backdrop\"\n (clicked)=\"handleBackdropClick()\"\n aria-label=\"Close sidebar\"\n ></tk-button>\n }\n\n <!-- Sidebar -->\n <aside class=\"tk-sidebar\">\n @if (!displayCollapsed) {\n <div class=\"tk-sidebar-header\">\n <img\n src=\"assets/img/tk-logo-normal-light.svg\"\n alt=\"Tekus Logo\"\n class=\"tk-logo-expanded\"\n />\n <tk-button\n class=\"tk-sidebar-toggle is-sidebar\"\n (clicked)=\"toggleSidebar()\"\n severity=\"secondary\"\n variant=\"text\"\n icon=\"arrow-left\"\n ></tk-button>\n </div>\n }\n\n <ng-content select=\"[sidebar-content]\"></ng-content>\n </aside>\n\n <!-- Main Content -->\n <div class=\"tk-main-container\">\n <tk-header\n [logoSrc]=\"(displayCollapsed || isTablet) ? 'assets/img/tk-logo-normal-dark.svg' : undefined\"\n logoAlt=\"Tekus Logo\"\n [leftActions]=\"headerLeftActions\"\n [rightActions]=\"headerActions()\">\n </tk-header>\n\n <main class=\"tk-content\">\n <ng-content></ng-content>\n </main>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}