{"version":3,"file":"mayvio-ui-angular-src-multiselect.mjs","sources":["../../src/multiselect/multiselect.component.ts","../../src/multiselect/mayvio-ui-angular-src-multiselect.ts"],"sourcesContent":["import {\n  Component,\n  Input,\n  Output,\n  EventEmitter,\n  ChangeDetectionStrategy,\n  ChangeDetectorRef,\n  HostListener,\n  ElementRef,\n  inject,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport 'mayvio-ui/multiselect/css';\n\nexport interface MultiSelectOption {\n  value: string | number;\n  label: string;\n  disabled?: boolean;\n}\n\n@Component({\n  selector: 'mv-multiselect',\n  standalone: true,\n  imports: [CommonModule],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  template: `\n    <div class=\"mv-multiselect\" [class.mv-multiselect--open]=\"isOpen\" [class]=\"className\">\n      <div\n        class=\"mv-multiselect-trigger\"\n        [class.mv-multiselect-trigger--disabled]=\"disabled\"\n        (click)=\"toggleMenu()\"\n        [attr.tabindex]=\"disabled ? -1 : 0\"\n        (keydown.enter)=\"toggleMenu()\"\n        (keydown.space)=\"toggleMenu(); $event.preventDefault()\"\n      >\n        <ng-container *ngIf=\"selectedOptions.length === 0\">\n          <span class=\"mv-multiselect-placeholder\">{{ placeholder }}</span>\n        </ng-container>\n\n        <ng-container *ngIf=\"selectedOptions.length > 0\">\n          <span\n            *ngFor=\"let opt of selectedOptions\"\n            class=\"mv-badge mv-badge--md mv-badge--default\"\n            style=\"gap: 0.25rem\"\n          >\n            {{ opt.label }}\n            <button\n              type=\"button\"\n              [attr.aria-label]=\"'Remove ' + opt.label\"\n              (click)=\"removeTag($event, opt.value)\"\n              style=\"background: none; border: none; cursor: pointer; padding: 0; display: flex\"\n            >\n              <svg\n                width=\"12\"\n                height=\"12\"\n                viewBox=\"0 0 24 24\"\n                fill=\"none\"\n                stroke=\"currentColor\"\n                stroke-width=\"2\"\n                stroke-linecap=\"round\"\n                stroke-linejoin=\"round\"\n              >\n                <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n                <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n              </svg>\n            </button>\n          </span>\n        </ng-container>\n      </div>\n\n      <div class=\"mv-multiselect-menu\" role=\"listbox\" *ngIf=\"isOpen\">\n        <div class=\"mv-multiselect-search\" *ngIf=\"searchable\" (click)=\"$event.stopPropagation()\">\n          <input\n            type=\"text\"\n            class=\"mv-multiselect-search-input\"\n            placeholder=\"Search...\"\n            [value]=\"searchQuery\"\n            (input)=\"onSearch($event)\"\n          />\n        </div>\n\n        <div class=\"mv-multiselect-empty\" *ngIf=\"filteredOptions.length === 0\">\n          {{ emptyText }}\n        </div>\n\n        <div\n          *ngFor=\"let opt of filteredOptions\"\n          class=\"mv-multiselect-option\"\n          [class.mv-multiselect-option--selected]=\"isSelected(opt.value)\"\n          [class.mv-multiselect-option--disabled]=\"opt.disabled\"\n          role=\"option\"\n          [attr.aria-selected]=\"isSelected(opt.value)\"\n          (click)=\"onOptionClick($event, opt)\"\n        >\n          <svg\n            [style.visibility]=\"isSelected(opt.value) ? 'visible' : 'hidden'\"\n            width=\"16\"\n            height=\"16\"\n            viewBox=\"0 0 24 24\"\n            fill=\"none\"\n            stroke=\"currentColor\"\n            stroke-width=\"2\"\n            stroke-linecap=\"round\"\n            stroke-linejoin=\"round\"\n          >\n            <polyline points=\"20 6 9 17 4 12\"></polyline>\n          </svg>\n          {{ opt.label }}\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class MultiSelectComponent {\n  @Input() options: MultiSelectOption[] = [];\n  @Input() value: (string | number)[] = [];\n  @Input() disabled = false;\n  @Input() searchable = false;\n  @Input() placeholder = 'Select options...';\n  @Input() emptyText = 'No options found.';\n  @Input() className = '';\n\n  @Output() selectionChange = new EventEmitter<(string | number)[]>();\n\n  isOpen = false;\n  searchQuery = '';\n\n  private el = inject(ElementRef);\n  private cdr = inject(ChangeDetectorRef);\n\n  get selectedOptions(): MultiSelectOption[] {\n    return this.options.filter((opt) => this.value.includes(opt.value));\n  }\n\n  get filteredOptions(): MultiSelectOption[] {\n    if (!this.searchable || !this.searchQuery) {\n      return this.options;\n    }\n    const q = this.searchQuery.toLowerCase();\n    return this.options.filter((opt) => opt.label.toLowerCase().includes(q));\n  }\n\n  isSelected(val: string | number): boolean {\n    return this.value.includes(val);\n  }\n\n  toggleMenu() {\n    if (this.disabled) return;\n    this.isOpen = !this.isOpen;\n    if (!this.isOpen) {\n      this.searchQuery = '';\n    }\n    this.cdr.markForCheck();\n  }\n\n  toggleOption(val: string | number) {\n    const newVal = this.value.includes(val)\n      ? this.value.filter((v) => v !== val)\n      : [...this.value, val];\n\n    this.value = newVal;\n    this.selectionChange.emit(this.value);\n    this.cdr.markForCheck();\n  }\n\n  onOptionClick(event: Event, opt: MultiSelectOption) {\n    event.stopPropagation();\n    if (!opt.disabled) {\n      this.toggleOption(opt.value);\n    }\n  }\n\n  removeTag(event: Event, val: string | number) {\n    event.stopPropagation();\n    this.toggleOption(val);\n  }\n\n  onSearch(event: Event) {\n    const input = event.target as HTMLInputElement;\n    this.searchQuery = input.value;\n    this.cdr.markForCheck();\n  }\n\n  @HostListener('document:mousedown', ['$event.target'])\n  onClickOutside(target: EventTarget | null) {\n    if (this.isOpen && !this.el.nativeElement.contains(target as Node)) {\n      this.isOpen = false;\n      this.searchQuery = '';\n      this.cdr.markForCheck();\n    }\n  }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}