{"version":3,"file":"seniorsistemas-angular-components-workspace-switch.mjs","sources":["../../projects/angular-components/workspace-switch/src/lib/workspace-switch/workspace-switch.component.ts","../../projects/angular-components/workspace-switch/src/lib/workspace-switch/workspace-switch.component.html","../../projects/angular-components/workspace-switch/src/lib/workspace-switch/workspace-switch.module.ts","../../projects/angular-components/workspace-switch/src/seniorsistemas-angular-components-workspace-switch.ts"],"sourcesContent":["import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, HostListener, Input, OnInit, Output, QueryList, ViewChildren, inject } from '@angular/core';\n\nimport { Workspace } from './models/workspace';\n\n/**\n * @description Componente de seleção de workspace exibe um dropdown com a lista de espaços de trabalho\n * disponíveis, permitindo ao usuário alternar entre eles. Suporta navegação por teclado\n * (setas, Enter, Escape), estado desabilitado e um botão de ação customizável no rodapé.\n *\n * @example\n * ```html\n * <s-workspace-switch\n *   [workspaces]=\"workspaces\"\n *   footerButtonLabel=\"Criar workspace\"\n *   (selected)=\"onWorkspaceSelect($event)\"\n *   (footerButtonClicked)=\"onCreate()\"\n * />\n * ```\n *\n * @category Navegação\n */\n@Component({\n    selector: 's-workspace-switch',\n    templateUrl: './workspace-switch.component.html',\n    styleUrls: ['./workspace-switch.component.scss'],\n})\nexport class WorkspaceSwitchComponent implements OnInit {\n    private readonly eRef = inject(ElementRef);\n    private readonly changeDetectorRef = inject(ChangeDetectorRef);\n\n    /**\n     * @description Lista de workspaces disponíveis para seleção. Campo obrigatório.\n     * Cada item deve implementar a interface `Workspace`.\n     * Lança um erro em runtime se a lista estiver vazia.\n     */\n    @Input({ required: true })\n    public workspaces: Workspace[] = [];\n\n    /**\n     * @description Rótulo exibido no botão de ação localizado no rodapé do dropdown.\n     *\n     * @default 'Adicionar'\n     */\n    @Input()\n    public footerButtonLabel = 'Adicionar';\n\n    /**\n     * @description Controla a visibilidade do botão de ação no rodapé do dropdown.\n     * Quando `false`, o botão não é renderizado.\n     *\n     * @default true\n     */\n    @Input()\n    public showFooterButton = true;\n\n    /**\n     * @description Quando `true`, o componente fica desabilitado: não abre o dropdown,\n     * não emite eventos e fica inacessível via teclado (`tabindex = -1`).\n     *\n     * @default false\n     */\n    @Input()\n    public disabled = false;\n\n    /**\n     * @description Emitido quando o usuário clica no botão de ação do rodapé do dropdown.\n     */\n    @Output()\n    public footerButtonClicked = new EventEmitter();\n\n    /**\n     * @description Emitido quando o usuário seleciona um workspace da lista.\n     * Retorna o objeto `Workspace` selecionado.\n     */\n    @Output()\n    public selected: EventEmitter<Workspace> = new EventEmitter();\n\n    @ViewChildren('listItem')\n    public listItems: QueryList<ElementRef> | null = null;\n\n    public get open() {\n        return this._open;\n    }\n\n    public set open(open: boolean) {\n        this._open = open;\n        this.changeDetectorRef.detectChanges();\n\n        if (open) {\n            this._calculateListMaxHeight();\n        }\n    }\n\n    public height = 0;\n    public selectedItemIndex = 0;\n    public currentItemIndex = 0;\n\n    private _open = false;\n\n    @HostBinding('attr.tabindex')\n    public tabindex = 0;\n\n    @HostListener('document:click', ['$event'])\n    public onClickout(event: MouseEvent): void {\n        if (!this.eRef.nativeElement.contains(event.target)) {\n            this.open = false;\n        }\n    }\n\n    @HostListener('keydown', ['$event'])\n    public onKeydown(event: KeyboardEvent): void {\n        if (event.key === 'Enter' || event.key === ' ') {\n            if (this.open) {\n                const workspace = this.workspaces[this.selectedItemIndex];\n\n                if (workspace.disabled) {\n                    return;\n                }\n\n                this.selectedItemIndex = this.currentItemIndex;\n                this.selected.emit(this.workspaces[this.selectedItemIndex]);\n            }\n            this.open = !this.open;\n        } else if (event.key === 'Escape') {\n            this.open = false;\n        } else if (event.key === 'ArrowDown') {\n            if (this.currentItemIndex < this.workspaces.length - 1) {\n                this.currentItemIndex++;\n                this._scrollToCurrentItem();\n            }\n        } else if (event.key === 'ArrowUp') {\n            if (this.currentItemIndex > 0) {\n                this.currentItemIndex--;\n                this._scrollToCurrentItem();\n            }\n        }\n    }\n\n    public ngOnInit(): void {\n        if (this.disabled) {\n            this.tabindex = -1;\n        }\n    }\n\n    public validations(): void {\n        if (!this.workspaces.length) {\n            throw new Error('Workspaces list is empty.');\n        }\n    }\n\n    public buttonOnBlur(): void {\n        this.open = false;\n        this.currentItemIndex = this.selectedItemIndex;\n    }\n\n    public onSelectItem(workspace: Workspace): void {\n        if (workspace.disabled) {\n            return;\n        }\n\n        this.open = false;\n        this.selectedItemIndex = this.workspaces.indexOf(workspace);\n        this.currentItemIndex = this.selectedItemIndex;\n        this.selected.emit(workspace);\n    }\n\n    public onFooterButtonClick(): void {\n        this.open = false;\n        this.footerButtonClicked.emit();\n    }\n\n    private _calculateListMaxHeight(): void {\n        const workspaceListRef = this.eRef.nativeElement.querySelector('#workspace-list');\n        const { top } = workspaceListRef.getBoundingClientRect();\n\n        this.height = window.innerHeight - top - 20 - (this.showFooterButton ? 64 : 0);\n        this.changeDetectorRef.detectChanges();\n    }\n\n    private _scrollToCurrentItem(): void {\n        const currentItem = this.listItems?.toArray()[this.currentItemIndex];\n        if (currentItem) {\n            currentItem.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n        }\n    }\n}\n\n","<div\n    class=\"workspace-switch\"\n    [ngClass]=\"{ 'workspace-switch--disabled': disabled }\"\n    (blur)=\"buttonOnBlur()\"\n>\n    <div\n        class=\"button\"\n        (click)=\"open = !open\"\n    >\n        <div class=\"item\">\n            <span class=\"title\">{{ workspaces[selectedItemIndex].title }}</span>\n            <span class=\"subtitle\">{{ workspaces[selectedItemIndex].subtitle }}</span>\n        </div>\n        <div class=\"icons\">\n            <span class=\"fas fa-chevron-up\"></span>\n            <span class=\"fas fa-chevron-down\"></span>\n        </div>\n    </div>\n    <div\n        *ngIf=\"!disabled && open\"\n        class=\"drop-panel\"\n    >\n        <ul\n            id=\"workspace-list\"\n            class=\"workspace-list\"\n            [ngStyle]=\"{ 'max-height': height + 'px' }\"\n        >\n\n            @for(workspace of workspaces; track workspace.id; let i = $index) {\n               <li\n                   #listItem\n                   class=\"workspace\"\n                   [ngClass]=\"{\n                       'workspace--focused': i === currentItemIndex && !workspace.disabled,\n                       'workspace--disabled': workspace.disabled,\n                   }\"\n                   (click)=\"onSelectItem(workspace)\"\n               >\n                   <div class=\"item\">\n                       <span class=\"title\">{{ workspace.title }}</span>\n                       <span class=\"subtitle\">{{ workspace.subtitle }}</span>\n                   </div>\n\n                   @if (i === selectedItemIndex) {\n                      <span class=\"active-icon fas fa-check\"></span>\n                   }\n               </li>\n            }\n\n        </ul>\n        <div\n            *ngIf=\"showFooterButton\"\n            class=\"footer\"\n        >\n            <div\n                class=\"footer__button\"\n                (click)=\"onFooterButtonClick()\"\n            >\n                <span class=\"footer__button__icon fas fa-plus\"></span>\n                <span class=\"footer__button__title\">{{ footerButtonLabel }}</span>\n            </div>\n        </div>\n    </div>\n</div>\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nimport { WorkspaceSwitchComponent } from './workspace-switch.component';\n\n@NgModule({\n    imports: [CommonModule],\n    declarations: [WorkspaceSwitchComponent],\n    exports: [WorkspaceSwitchComponent],\n})\nexport class WorkspaceSwitchModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}