@neural-ui/core 1.7.0 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/bottom-sheet/package.json +4 -0
  2. package/confirm-popup/package.json +4 -0
  3. package/data-view/package.json +4 -0
  4. package/fesm2022/neural-ui-core-alert.mjs +48 -21
  5. package/fesm2022/neural-ui-core-alert.mjs.map +1 -1
  6. package/fesm2022/neural-ui-core-autocomplete.mjs +141 -68
  7. package/fesm2022/neural-ui-core-autocomplete.mjs.map +1 -1
  8. package/fesm2022/neural-ui-core-block-ui.mjs +2 -2
  9. package/fesm2022/neural-ui-core-block-ui.mjs.map +1 -1
  10. package/fesm2022/neural-ui-core-bottom-sheet.mjs +121 -0
  11. package/fesm2022/neural-ui-core-bottom-sheet.mjs.map +1 -0
  12. package/fesm2022/neural-ui-core-breadcrumb.mjs +2 -2
  13. package/fesm2022/neural-ui-core-breadcrumb.mjs.map +1 -1
  14. package/fesm2022/neural-ui-core-button.mjs +2 -2
  15. package/fesm2022/neural-ui-core-button.mjs.map +1 -1
  16. package/fesm2022/neural-ui-core-calendar.mjs +2 -2
  17. package/fesm2022/neural-ui-core-calendar.mjs.map +1 -1
  18. package/fesm2022/neural-ui-core-checkbox.mjs +69 -39
  19. package/fesm2022/neural-ui-core-checkbox.mjs.map +1 -1
  20. package/fesm2022/neural-ui-core-chip.mjs +2 -2
  21. package/fesm2022/neural-ui-core-chip.mjs.map +1 -1
  22. package/fesm2022/neural-ui-core-code-block.mjs +2 -2
  23. package/fesm2022/neural-ui-core-code-block.mjs.map +1 -1
  24. package/fesm2022/neural-ui-core-confirm-popup.mjs +105 -0
  25. package/fesm2022/neural-ui-core-confirm-popup.mjs.map +1 -0
  26. package/fesm2022/neural-ui-core-data-view.mjs +386 -0
  27. package/fesm2022/neural-ui-core-data-view.mjs.map +1 -0
  28. package/fesm2022/neural-ui-core-date-input.mjs +185 -10
  29. package/fesm2022/neural-ui-core-date-input.mjs.map +1 -1
  30. package/fesm2022/neural-ui-core-empty-state.mjs +19 -5
  31. package/fesm2022/neural-ui-core-empty-state.mjs.map +1 -1
  32. package/fesm2022/neural-ui-core-form-field.mjs +81 -0
  33. package/fesm2022/neural-ui-core-form-field.mjs.map +1 -0
  34. package/fesm2022/neural-ui-core-inline-editor.mjs +428 -0
  35. package/fesm2022/neural-ui-core-inline-editor.mjs.map +1 -0
  36. package/fesm2022/neural-ui-core-input-mask.mjs +110 -0
  37. package/fesm2022/neural-ui-core-input-mask.mjs.map +1 -0
  38. package/fesm2022/neural-ui-core-input.mjs +2 -2
  39. package/fesm2022/neural-ui-core-input.mjs.map +1 -1
  40. package/fesm2022/neural-ui-core-listbox.mjs +219 -0
  41. package/fesm2022/neural-ui-core-listbox.mjs.map +1 -0
  42. package/fesm2022/neural-ui-core-menu.mjs +229 -0
  43. package/fesm2022/neural-ui-core-menu.mjs.map +1 -0
  44. package/fesm2022/neural-ui-core-modal.mjs +34 -10
  45. package/fesm2022/neural-ui-core-modal.mjs.map +1 -1
  46. package/fesm2022/neural-ui-core-multiselect.mjs +159 -174
  47. package/fesm2022/neural-ui-core-multiselect.mjs.map +1 -1
  48. package/fesm2022/neural-ui-core-nav.mjs +2 -2
  49. package/fesm2022/neural-ui-core-nav.mjs.map +1 -1
  50. package/fesm2022/neural-ui-core-number-input.mjs +2 -2
  51. package/fesm2022/neural-ui-core-number-input.mjs.map +1 -1
  52. package/fesm2022/neural-ui-core-panel.mjs +92 -0
  53. package/fesm2022/neural-ui-core-panel.mjs.map +1 -0
  54. package/fesm2022/neural-ui-core-password.mjs +106 -0
  55. package/fesm2022/neural-ui-core-password.mjs.map +1 -0
  56. package/fesm2022/neural-ui-core-pick-list.mjs +133 -0
  57. package/fesm2022/neural-ui-core-pick-list.mjs.map +1 -0
  58. package/fesm2022/neural-ui-core-select.mjs +118 -162
  59. package/fesm2022/neural-ui-core-select.mjs.map +1 -1
  60. package/fesm2022/neural-ui-core-sidebar.mjs +14 -3
  61. package/fesm2022/neural-ui-core-sidebar.mjs.map +1 -1
  62. package/fesm2022/neural-ui-core-slider.mjs +2 -2
  63. package/fesm2022/neural-ui-core-slider.mjs.map +1 -1
  64. package/fesm2022/neural-ui-core-spinner.mjs +19 -9
  65. package/fesm2022/neural-ui-core-spinner.mjs.map +1 -1
  66. package/fesm2022/neural-ui-core-split-button.mjs +2 -2
  67. package/fesm2022/neural-ui-core-split-button.mjs.map +1 -1
  68. package/fesm2022/neural-ui-core-table.mjs +501 -62
  69. package/fesm2022/neural-ui-core-table.mjs.map +1 -1
  70. package/fesm2022/neural-ui-core-tags.mjs +134 -0
  71. package/fesm2022/neural-ui-core-tags.mjs.map +1 -0
  72. package/fesm2022/neural-ui-core-textarea.mjs +2 -2
  73. package/fesm2022/neural-ui-core-textarea.mjs.map +1 -1
  74. package/fesm2022/neural-ui-core-toggle-button-group.mjs +2 -2
  75. package/fesm2022/neural-ui-core-toggle-button-group.mjs.map +1 -1
  76. package/fesm2022/neural-ui-core-toolbar.mjs +16 -4
  77. package/fesm2022/neural-ui-core-toolbar.mjs.map +1 -1
  78. package/fesm2022/neural-ui-core-tree-select.mjs +259 -0
  79. package/fesm2022/neural-ui-core-tree-select.mjs.map +1 -0
  80. package/fesm2022/neural-ui-core-tree-table.mjs +267 -8
  81. package/fesm2022/neural-ui-core-tree-table.mjs.map +1 -1
  82. package/fesm2022/neural-ui-core-tree.mjs +15 -14
  83. package/fesm2022/neural-ui-core-tree.mjs.map +1 -1
  84. package/fesm2022/neural-ui-core-uploader.mjs +103 -12
  85. package/fesm2022/neural-ui-core-uploader.mjs.map +1 -1
  86. package/form-field/package.json +4 -0
  87. package/inline-editor/package.json +4 -0
  88. package/input-mask/package.json +4 -0
  89. package/listbox/package.json +4 -0
  90. package/menu/package.json +4 -0
  91. package/package.json +53 -1
  92. package/panel/package.json +4 -0
  93. package/password/package.json +4 -0
  94. package/pick-list/package.json +4 -0
  95. package/styles/_tokens.scss +30 -15
  96. package/tags/package.json +4 -0
  97. package/tree-select/package.json +4 -0
  98. package/types/neural-ui-core-alert.d.ts +2 -1
  99. package/types/neural-ui-core-autocomplete.d.ts +20 -2
  100. package/types/neural-ui-core-bottom-sheet.d.ts +20 -0
  101. package/types/neural-ui-core-checkbox.d.ts +6 -1
  102. package/types/neural-ui-core-confirm-popup.d.ts +38 -0
  103. package/types/neural-ui-core-data-view.d.ts +95 -0
  104. package/types/neural-ui-core-date-input.d.ts +35 -5
  105. package/types/neural-ui-core-empty-state.d.ts +11 -1
  106. package/types/neural-ui-core-form-field.d.ts +33 -0
  107. package/types/neural-ui-core-inline-editor.d.ts +66 -0
  108. package/types/neural-ui-core-input-mask.d.ts +26 -0
  109. package/types/neural-ui-core-listbox.d.ts +54 -0
  110. package/types/neural-ui-core-menu.d.ts +49 -0
  111. package/types/neural-ui-core-modal.d.ts +10 -2
  112. package/types/neural-ui-core-multiselect.d.ts +8 -1
  113. package/types/neural-ui-core-panel.d.ts +25 -0
  114. package/types/neural-ui-core-password.d.ts +29 -0
  115. package/types/neural-ui-core-pick-list.d.ts +40 -0
  116. package/types/neural-ui-core-select.d.ts +5 -1
  117. package/types/neural-ui-core-sidebar.d.ts +5 -1
  118. package/types/neural-ui-core-spinner.d.ts +4 -2
  119. package/types/neural-ui-core-table.d.ts +89 -5
  120. package/types/neural-ui-core-tags.d.ts +32 -0
  121. package/types/neural-ui-core-toolbar.d.ts +8 -2
  122. package/types/neural-ui-core-tree-select.d.ts +57 -0
  123. package/types/neural-ui-core-tree-table.d.ts +111 -4
  124. package/types/neural-ui-core-tree.d.ts +1 -1
  125. package/types/neural-ui-core-uploader.d.ts +26 -3
@@ -102,6 +102,11 @@ class NeuMultiselectComponent {
102
102
  searchable = input(false, ...(ngDevMode ? [{ debugName: "searchable" }] : /* istanbul ignore next */ []));
103
103
  /** Placeholder del input de búsqueda / Search input placeholder */
104
104
  searchPlaceholder = input('Buscar...', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
105
+ loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
106
+ loadingLabel = input('Loading...', ...(ngDevMode ? [{ debugName: "loadingLabel" }] : /* istanbul ignore next */ []));
107
+ selectAll = input(false, ...(ngDevMode ? [{ debugName: "selectAll" }] : /* istanbul ignore next */ []));
108
+ selectAllLabel = input('Select all', ...(ngDevMode ? [{ debugName: "selectAllLabel" }] : /* istanbul ignore next */ []));
109
+ unselectAllLabel = input('Unselect all', ...(ngDevMode ? [{ debugName: "unselectAllLabel" }] : /* istanbul ignore next */ []));
105
110
  /** Texto cuando no hay opciones tras filtrar / Text when no options remain after filtering */
106
111
  noResultsMessage = input('Sin resultados', ...(ngDevMode ? [{ debugName: "noResultsMessage" }] : /* istanbul ignore next */ []));
107
112
  /** Texto del botón de limpiar todas las selecciones / Button text to clear all selections */
@@ -186,6 +191,10 @@ class NeuMultiselectComponent {
186
191
  return this.options();
187
192
  return this.options().filter((o) => o.label.toLowerCase().includes(q));
188
193
  }, ...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
194
+ allFilteredSelected = computed(() => {
195
+ const enabled = this.filteredOptions().filter((option) => !option.disabled);
196
+ return enabled.length > 0 && enabled.every((option) => this._values().includes(option.value));
197
+ }, ...(ngDevMode ? [{ debugName: "allFilteredSelected" }] : /* istanbul ignore next */ []));
189
198
  resultsAnnouncement = computed(() => {
190
199
  if (!this.isOpen()) {
191
200
  return '';
@@ -337,6 +346,26 @@ class NeuMultiselectComponent {
337
346
  this._urlState.setParam(param, null);
338
347
  this.refreshVirtualViewport();
339
348
  }
349
+ toggleAllFiltered(event) {
350
+ event.stopPropagation();
351
+ const enabled = this.filteredOptions().filter((option) => !option.disabled);
352
+ const current = new Set(this._values());
353
+ if (this.allFilteredSelected()) {
354
+ enabled.forEach((option) => current.delete(option.value));
355
+ }
356
+ else {
357
+ enabled.forEach((option) => current.add(option.value));
358
+ }
359
+ const next = [...current];
360
+ this._values.set(next);
361
+ this._onChange(next);
362
+ this._onTouched();
363
+ this.selectionChange.emit(this.options().filter((option) => next.includes(option.value)));
364
+ const param = this.urlParam();
365
+ if (param)
366
+ this._urlState.setParam(param, next.length ? next.join(',') : null);
367
+ this.refreshVirtualViewport();
368
+ }
340
369
  toggleChipMode(event) {
341
370
  event.stopPropagation();
342
371
  this._chipMode.set(this._chipMode() === 'chips' ? 'count' : 'chips');
@@ -424,7 +453,7 @@ class NeuMultiselectComponent {
424
453
  });
425
454
  }
426
455
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuMultiselectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
427
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuMultiselectComponent, isStandalone: true, selector: "neu-multiselect", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, floatingLabel: { classPropertyName: "floatingLabel", publicName: "floatingLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null }, clearAllLabel: { classPropertyName: "clearAllLabel", publicName: "clearAllLabel", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollVisibleItems: { classPropertyName: "virtualScrollVisibleItems", publicName: "virtualScrollVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, clearAriaLabel: { classPropertyName: "clearAriaLabel", publicName: "clearAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, urlParam: { classPropertyName: "urlParam", publicName: "urlParam", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "keydown.escape": "close()", "window:resize": "onWindowResize()" } }, providers: [
456
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuMultiselectComponent, isStandalone: true, selector: "neu-multiselect", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, floatingLabel: { classPropertyName: "floatingLabel", publicName: "floatingLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingLabel: { classPropertyName: "loadingLabel", publicName: "loadingLabel", isSignal: true, isRequired: false, transformFunction: null }, selectAll: { classPropertyName: "selectAll", publicName: "selectAll", isSignal: true, isRequired: false, transformFunction: null }, selectAllLabel: { classPropertyName: "selectAllLabel", publicName: "selectAllLabel", isSignal: true, isRequired: false, transformFunction: null }, unselectAllLabel: { classPropertyName: "unselectAllLabel", publicName: "unselectAllLabel", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null }, clearAllLabel: { classPropertyName: "clearAllLabel", publicName: "clearAllLabel", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollVisibleItems: { classPropertyName: "virtualScrollVisibleItems", publicName: "virtualScrollVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, clearAriaLabel: { classPropertyName: "clearAriaLabel", publicName: "clearAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, urlParam: { classPropertyName: "urlParam", publicName: "urlParam", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "keydown.escape": "close()", "window:resize": "onWindowResize()" } }, providers: [
428
457
  {
429
458
  provide: NG_VALUE_ACCESSOR,
430
459
  useExisting: forwardRef(() => NeuMultiselectComponent),
@@ -585,105 +614,83 @@ class NeuMultiselectComponent {
585
614
  />
586
615
  </div>
587
616
  }
617
+ @if (selectAll()) {
618
+ <button type="button" class="neu-multiselect__select-all" (click)="toggleAllFiltered($event)">
619
+ {{ allFilteredSelected() ? unselectAllLabel() : selectAllLabel() }}
620
+ </button>
621
+ }
588
622
 
589
623
  <!-- Opciones -->
590
624
  <div class="neu-multiselect__options">
591
- @if (virtualScroll()) {
625
+ <ng-template #multiselectOptionTpl let-option>
626
+ <div
627
+ class="neu-multiselect__option"
628
+ [class.neu-multiselect__option--selected]="isSelected(option.value)"
629
+ [class.neu-multiselect__option--disabled]="option.disabled"
630
+ role="option"
631
+ [id]="'neu-ms-opt-' + option.value"
632
+ [attr.aria-selected]="isSelected(option.value)"
633
+ [attr.aria-disabled]="option.disabled"
634
+ [attr.tabindex]="option.disabled ? null : '-1'"
635
+ (click)="toggleOption(option)"
636
+ (keydown.enter)="toggleOption(option)"
637
+ (keydown.space)="toggleOption(option)"
638
+ (keydown.arrowDown)="focusOptionByIndex($any($event), option, 1)"
639
+ (keydown.arrowUp)="focusOptionByIndex($any($event), option, -1)"
640
+ >
641
+ <span
642
+ class="neu-multiselect__checkbox"
643
+ [class.neu-multiselect__checkbox--checked]="isSelected(option.value)"
644
+ >
645
+ <svg
646
+ class="neu-multiselect__checkbox-check"
647
+ viewBox="0 0 12 10"
648
+ fill="none"
649
+ stroke="currentColor"
650
+ stroke-width="2"
651
+ stroke-linecap="round"
652
+ stroke-linejoin="round"
653
+ aria-hidden="true"
654
+ >
655
+ <polyline points="1 5 4.5 9 11 1" />
656
+ </svg>
657
+ </span>
658
+ @if (itemTpl()) {
659
+ <ng-container
660
+ [ngTemplateOutlet]="itemTpl()!.templateRef"
661
+ [ngTemplateOutletContext]="{ $implicit: option }"
662
+ />
663
+ } @else {
664
+ {{ option.label }}
665
+ }
666
+ </div>
667
+ </ng-template>
668
+
669
+ @if (loading()) {
670
+ <div class="neu-multiselect__empty" role="status">{{ loadingLabel() }}</div>
671
+ } @else if (virtualScroll()) {
592
672
  <cdk-virtual-scroll-viewport
593
673
  class="neu-multiselect__viewport"
594
674
  [itemSize]="virtualScrollItemSize()"
595
675
  [style.height]="virtualViewportHeight()"
596
676
  >
597
- <div
598
- *cdkVirtualFor="let option of filteredOptions(); trackBy: trackByOptionValue"
599
- class="neu-multiselect__option"
600
- [class.neu-multiselect__option--selected]="isSelected(option.value)"
601
- [class.neu-multiselect__option--disabled]="option.disabled"
602
- role="option"
603
- [id]="'neu-ms-opt-' + option.value"
604
- [attr.aria-selected]="isSelected(option.value)"
605
- [attr.aria-disabled]="option.disabled"
606
- [attr.tabindex]="option.disabled ? null : '-1'"
607
- (click)="toggleOption(option)"
608
- (keydown.enter)="toggleOption(option)"
609
- (keydown.space)="toggleOption(option)"
610
- (keydown.arrowDown)="focusOptionByIndex($any($event), option, 1)"
611
- (keydown.arrowUp)="focusOptionByIndex($any($event), option, -1)"
612
- >
613
- <span
614
- class="neu-multiselect__checkbox"
615
- [class.neu-multiselect__checkbox--checked]="isSelected(option.value)"
616
- >
617
- <svg
618
- class="neu-multiselect__checkbox-check"
619
- viewBox="0 0 12 10"
620
- fill="none"
621
- stroke="currentColor"
622
- stroke-width="2"
623
- stroke-linecap="round"
624
- stroke-linejoin="round"
625
- aria-hidden="true"
626
- >
627
- <polyline points="1 5 4.5 9 11 1" />
628
- </svg>
629
- </span>
630
- @if (itemTpl()) {
631
- <ng-container
632
- [ngTemplateOutlet]="itemTpl()!.templateRef"
633
- [ngTemplateOutletContext]="{ $implicit: option }"
634
- />
635
- } @else {
636
- {{ option.label }}
637
- }
638
- </div>
677
+ <ng-container *cdkVirtualFor="let option of filteredOptions(); trackBy: trackByOptionValue">
678
+ <ng-container
679
+ [ngTemplateOutlet]="multiselectOptionTpl"
680
+ [ngTemplateOutletContext]="{ $implicit: option }"
681
+ />
682
+ </ng-container>
639
683
  </cdk-virtual-scroll-viewport>
640
684
  } @else {
641
685
  @for (option of filteredOptions(); track option.value) {
642
- <div
643
- class="neu-multiselect__option"
644
- [class.neu-multiselect__option--selected]="isSelected(option.value)"
645
- [class.neu-multiselect__option--disabled]="option.disabled"
646
- role="option"
647
- [id]="'neu-ms-opt-' + option.value"
648
- [attr.aria-selected]="isSelected(option.value)"
649
- [attr.aria-disabled]="option.disabled"
650
- [attr.tabindex]="option.disabled ? null : '-1'"
651
- (click)="toggleOption(option)"
652
- (keydown.enter)="toggleOption(option)"
653
- (keydown.space)="toggleOption(option)"
654
- (keydown.arrowDown)="focusOptionByIndex($any($event), option, 1)"
655
- (keydown.arrowUp)="focusOptionByIndex($any($event), option, -1)"
656
- >
657
- <span
658
- class="neu-multiselect__checkbox"
659
- [class.neu-multiselect__checkbox--checked]="isSelected(option.value)"
660
- >
661
- <svg
662
- class="neu-multiselect__checkbox-check"
663
- viewBox="0 0 12 10"
664
- fill="none"
665
- stroke="currentColor"
666
- stroke-width="2"
667
- stroke-linecap="round"
668
- stroke-linejoin="round"
669
- aria-hidden="true"
670
- >
671
- <polyline points="1 5 4.5 9 11 1" />
672
- </svg>
673
- </span>
674
- @if (itemTpl()) {
675
- <ng-container
676
- [ngTemplateOutlet]="itemTpl()!.templateRef"
677
- [ngTemplateOutletContext]="{ $implicit: option }"
678
- />
679
- } @else {
680
- {{ option.label }}
681
- }
682
- </div>
686
+ <ng-container
687
+ [ngTemplateOutlet]="multiselectOptionTpl"
688
+ [ngTemplateOutletContext]="{ $implicit: option }"
689
+ />
683
690
  }
684
691
  }
685
692
 
686
- @if (filteredOptions().length === 0) {
693
+ @if (!loading() && filteredOptions().length === 0) {
687
694
  <div class="neu-multiselect__empty">{{ noResultsMessage() }}</div>
688
695
  }
689
696
  </div>
@@ -728,7 +735,7 @@ class NeuMultiselectComponent {
728
735
  } @else if (hint()) {
729
736
  <p class="neu-multiselect__hint" [id]="_triggerId + '-hint'">{{ hint() }}</p>
730
737
  }
731
- `, isInline: true, styles: [".neu-multiselect__static-label{display:block;font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);margin-bottom:var(--neu-space-2)}.neu-multiselect__label{position:absolute;left:var(--neu-space-3);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base);color:var(--neu-text-muted);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-8));transition:top var(--neu-transition),font-size var(--neu-transition),color var(--neu-transition),transform var(--neu-transition),padding var(--neu-transition),background var(--neu-transition)}.neu-multiselect--open .neu-multiselect__label,.neu-multiselect--has-value .neu-multiselect__label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface);padding:0 4px;left:calc(var(--neu-space-3) - 4px)}.neu-multiselect--open .neu-multiselect__label{color:var(--neu-primary)}.neu-multiselect--error .neu-multiselect__label{color:var(--neu-error)}.neu-multiselect--disabled .neu-multiselect__label{background:var(--neu-surface-2)}.neu-multiselect{position:relative;font-family:var(--neu-font-sans)}.neu-multiselect--sm .neu-multiselect__trigger{min-height:36px;font-size:var(--neu-text-sm);padding:var(--neu-space-1) var(--neu-space-2);padding-right:36px}.neu-multiselect--lg .neu-multiselect__trigger{min-height:56px}.neu-multiselect__trigger{display:flex;align-items:center;width:100%;min-height:48px;padding:var(--neu-space-2) var(--neu-space-3);padding-right:36px;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);cursor:pointer;text-align:left;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-multiselect__trigger:hover:not([aria-disabled=true]){border-color:var(--neu-border-hover)}.neu-multiselect__trigger:focus-visible{outline:none;border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-multiselect__trigger[aria-disabled=true]{opacity:.6;cursor:not-allowed;background:var(--neu-surface-2)}.neu-multiselect--open .neu-multiselect__trigger{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-multiselect--error .neu-multiselect__trigger{border-color:var(--neu-error)}.neu-multiselect--error .neu-multiselect__trigger:focus-visible{box-shadow:0 0 0 3px #ef44441f}.neu-multiselect__chips{display:flex;flex-wrap:wrap;gap:var(--neu-space-1);flex:1;min-width:0}.neu-multiselect__placeholder{color:var(--neu-text-disabled);font-size:var(--neu-text-base);line-height:1.5}.neu-multiselect:not(.neu-multiselect--no-float):not(.neu-multiselect--open) .neu-multiselect__placeholder{visibility:hidden}.neu-multiselect__chip{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 8px;background:var(--neu-primary-soft, rgba(0, 122, 255, .1));color:var(--neu-primary);border-radius:var(--neu-radius-sm);font-size:var(--neu-text-xs);font-weight:500;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.neu-multiselect__chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;cursor:pointer;color:inherit;opacity:.7;border-radius:2px;transition:opacity var(--neu-transition);flex-shrink:0}.neu-multiselect__chip-remove:hover{opacity:1}.neu-multiselect__chip-remove:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__chip-remove svg{width:10px;height:10px}.neu-multiselect__clear{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:2px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);flex-shrink:0;transition:color var(--neu-transition),background var(--neu-transition)}.neu-multiselect__clear svg{width:14px;height:14px}.neu-multiselect__clear:hover{color:var(--neu-text);background:var(--neu-surface-3)}.neu-multiselect__clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__chevron{position:absolute;right:var(--neu-space-3);top:50%;transform:translateY(-50%);width:16px;height:16px;color:var(--neu-text-muted);pointer-events:none;transition:transform var(--neu-transition);flex-shrink:0}.neu-multiselect--open .neu-multiselect__chevron{transform:translateY(-50%) rotate(180deg)}.neu-multiselect__panel{position:relative;z-index:200;box-sizing:border-box;width:100%;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);box-shadow:var(--neu-shadow-lg);overflow:hidden;max-height:280px;display:flex;flex-direction:column;animation:neu-multiselect-fade-in .12s ease}.neu-multiselect__panel--virtual{overflow:visible}@media(max-width:600px){.neu-multiselect__panel{left:auto;right:0;width:min(max(100%,240px),100vw - 2rem);max-width:calc(100vw - 2rem)}}@keyframes neu-multiselect-fade-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-multiselect__search{padding:var(--neu-space-2);border-bottom:1px solid var(--neu-border);flex-shrink:0}.neu-multiselect__search-input{width:100%;height:34px;padding:0 var(--neu-space-3);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-bg);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-multiselect__search-input:focus{border-color:var(--neu-primary);box-shadow:0 0 0 2px #007aff1f}.neu-multiselect__search-input::placeholder{color:var(--neu-text-disabled)}.neu-multiselect__options{flex:1;overflow-y:auto;min-height:0}.neu-multiselect__panel--virtual .neu-multiselect__options{overflow:hidden}.neu-multiselect__viewport{width:100%}.neu-multiselect__option{display:flex;align-items:center;gap:var(--neu-space-2);padding:10px var(--neu-space-3);min-height:var(--neu-multiselect-option-height, 44px);box-sizing:border-box;cursor:pointer;font-size:var(--neu-text-sm);color:var(--neu-text);transition:background var(--neu-transition)}.neu-multiselect__option:hover:not(.neu-multiselect__option--disabled){background:var(--neu-surface-2)}.neu-multiselect__option--selected{background:var(--neu-primary-soft, rgba(0, 122, 255, .06));color:var(--neu-primary);font-weight:500}.neu-multiselect__option--disabled{opacity:.4;cursor:not-allowed}.neu-multiselect__checkbox{display:flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:3px;border:1.5px solid var(--neu-border);background:var(--neu-bg);flex-shrink:0;transition:border-color var(--neu-transition),background var(--neu-transition)}.neu-multiselect__checkbox--checked{background:var(--neu-primary);border-color:var(--neu-primary);color:#fff}.neu-multiselect__checkbox-check{width:10px;height:8px;opacity:0;transform:scale(.6);transition:opacity .12s ease,transform .12s ease}.neu-multiselect__checkbox--checked .neu-multiselect__checkbox-check{opacity:1;transform:scale(1)}.neu-multiselect__empty{padding:var(--neu-space-4);text-align:center;font-size:var(--neu-text-sm);color:var(--neu-text-disabled);font-family:var(--neu-font-sans)}.neu-multiselect__footer{display:flex;align-items:center;justify-content:space-between;padding:var(--neu-space-2) var(--neu-space-3);border-top:1px solid var(--neu-border);background:var(--neu-surface);flex-shrink:0}.neu-multiselect__footer-count{font-size:var(--neu-text-xs);color:var(--neu-text-muted)}.neu-multiselect__footer-actions{display:flex;align-items:center;gap:var(--neu-space-2)}.neu-multiselect__footer-mode{background:none;border:1px solid var(--neu-border);border-radius:var(--neu-radius-sm);padding:2px 6px;font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);color:var(--neu-text-muted);cursor:pointer;line-height:1.4}.neu-multiselect__footer-mode:hover{background:var(--neu-surface-2);color:var(--neu-text)}.neu-multiselect__footer-mode:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__footer-clear{background:none;border:none;padding:0;font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);color:var(--neu-primary);cursor:pointer;font-weight:500}.neu-multiselect__footer-clear:hover{text-decoration:underline}.neu-multiselect__footer-clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px;border-radius:var(--neu-radius-sm)}.neu-multiselect__count-badge{display:inline-flex;align-items:center;padding:2px 10px;background:var(--neu-primary-100, rgba(14, 165, 233, .12));color:var(--neu-primary-dark, var(--neu-primary));border-radius:var(--neu-radius-full);font-size:var(--neu-text-sm);font-weight:500}.neu-multiselect__chip--overflow{background:var(--neu-surface-2);color:var(--neu-text-muted);border:1px dashed var(--neu-border);cursor:default;pointer-events:none}.neu-multiselect__error{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-error-text, var(--neu-error));font-family:var(--neu-font-sans)}.neu-multiselect__hint{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-text-muted);font-family:var(--neu-font-sans)}.neu-multiselect__sr-status{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: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: i1.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: ScrollingModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
738
+ `, isInline: true, styles: [".neu-multiselect__static-label{display:block;font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);margin-bottom:var(--neu-space-2)}.neu-multiselect__label{position:absolute;left:var(--neu-space-3);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base);color:var(--neu-text-muted);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-8));transition:top var(--neu-transition),font-size var(--neu-transition),color var(--neu-transition),transform var(--neu-transition),padding var(--neu-transition),background var(--neu-transition)}.neu-multiselect--open .neu-multiselect__label,.neu-multiselect--has-value .neu-multiselect__label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface);padding:0 4px;left:calc(var(--neu-space-3) - 4px)}.neu-multiselect--open .neu-multiselect__label{color:var(--neu-primary)}.neu-multiselect--error .neu-multiselect__label{color:var(--neu-error)}.neu-multiselect--disabled .neu-multiselect__label{background:var(--neu-surface-2)}.neu-multiselect{position:relative;font-family:var(--neu-font-sans)}.neu-multiselect--sm .neu-multiselect__trigger{min-height:36px;font-size:var(--neu-text-sm);padding:var(--neu-space-1) var(--neu-space-2);padding-right:36px}.neu-multiselect--lg .neu-multiselect__trigger{min-height:56px}.neu-multiselect__trigger{display:flex;align-items:center;width:100%;min-height:48px;padding:var(--neu-space-2) var(--neu-space-3);padding-right:36px;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);cursor:pointer;text-align:left;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-multiselect__trigger:hover:not([aria-disabled=true]){border-color:var(--neu-border-hover)}.neu-multiselect__trigger:focus-visible{outline:none;border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-multiselect__trigger[aria-disabled=true]{opacity:.6;cursor:not-allowed;background:var(--neu-surface-2)}.neu-multiselect--open .neu-multiselect__trigger{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-multiselect--error .neu-multiselect__trigger{border-color:var(--neu-error)}.neu-multiselect--error .neu-multiselect__trigger:focus-visible{box-shadow:0 0 0 3px #ef44441f}.neu-multiselect__chips{display:flex;flex-wrap:wrap;gap:var(--neu-space-1);flex:1;min-width:0}.neu-multiselect__placeholder{color:var(--neu-text-disabled);font-size:var(--neu-text-base);line-height:1.5}.neu-multiselect:not(.neu-multiselect--no-float):not(.neu-multiselect--open) .neu-multiselect__placeholder{visibility:hidden}.neu-multiselect__chip{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 8px;background:var(--neu-primary-soft, rgba(0, 122, 255, .1));color:var(--neu-primary);border-radius:var(--neu-radius-sm);font-size:var(--neu-text-xs);font-weight:500;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.neu-multiselect__chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;cursor:pointer;color:inherit;opacity:.7;border-radius:2px;transition:opacity var(--neu-transition);flex-shrink:0}.neu-multiselect__chip-remove:hover{opacity:1}.neu-multiselect__chip-remove:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__chip-remove svg{width:10px;height:10px}.neu-multiselect__clear{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:2px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);flex-shrink:0;transition:color var(--neu-transition),background var(--neu-transition)}.neu-multiselect__clear svg{width:14px;height:14px}.neu-multiselect__clear:hover{color:var(--neu-text);background:var(--neu-surface-3)}.neu-multiselect__clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__chevron{position:absolute;right:var(--neu-space-3);top:50%;transform:translateY(-50%);width:16px;height:16px;color:var(--neu-text-muted);pointer-events:none;transition:transform var(--neu-transition);flex-shrink:0}.neu-multiselect--open .neu-multiselect__chevron{transform:translateY(-50%) rotate(180deg)}.neu-multiselect__panel{position:relative;z-index:200;box-sizing:border-box;width:100%;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);box-shadow:var(--neu-shadow-lg);overflow:hidden;max-height:280px;display:flex;flex-direction:column;animation:neu-multiselect-fade-in .12s ease}.neu-multiselect__panel--virtual{overflow:visible}@media(max-width:600px){.neu-multiselect__panel{left:auto;right:0;width:min(max(100%,240px),100vw - 2rem);max-width:calc(100vw - 2rem)}}@keyframes neu-multiselect-fade-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-multiselect__search{padding:var(--neu-space-2);border-bottom:1px solid var(--neu-border);flex-shrink:0}.neu-multiselect__search-input{width:100%;height:34px;padding:0 var(--neu-space-3);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-bg);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-multiselect__search-input:focus{border-color:var(--neu-primary);box-shadow:0 0 0 2px #007aff1f}.neu-multiselect__search-input::placeholder{color:var(--neu-text-disabled)}.neu-multiselect__options{flex:1;overflow-y:auto;min-height:0}.neu-multiselect__panel--virtual .neu-multiselect__options{overflow:hidden}.neu-multiselect__viewport{width:100%}.neu-multiselect__option{display:flex;align-items:center;gap:var(--neu-space-2);padding:10px var(--neu-space-3);min-height:var(--neu-multiselect-option-height, 44px);box-sizing:border-box;cursor:pointer;font-size:var(--neu-text-sm);color:var(--neu-text);transition:background var(--neu-transition)}.neu-multiselect__option:hover:not(.neu-multiselect__option--disabled){background:var(--neu-surface-2)}.neu-multiselect__option--selected{background:var(--neu-primary-soft, rgba(0, 122, 255, .06));color:var(--neu-primary);font-weight:500}.neu-multiselect__option--disabled{opacity:.4;cursor:not-allowed}.neu-multiselect__checkbox{display:flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:3px;border:1.5px solid var(--neu-border);background:var(--neu-bg);flex-shrink:0;transition:border-color var(--neu-transition),background var(--neu-transition)}.neu-multiselect__checkbox--checked{background:var(--neu-primary);border-color:var(--neu-primary);color:#fff}.neu-multiselect__checkbox-check{width:10px;height:8px;opacity:0;transform:scale(.6);transition:opacity .12s ease,transform .12s ease}.neu-multiselect__checkbox--checked .neu-multiselect__checkbox-check{opacity:1;transform:scale(1)}.neu-multiselect__empty{padding:var(--neu-space-4);text-align:center;font-size:var(--neu-text-sm);color:var(--neu-text-disabled);font-family:var(--neu-font-sans)}.neu-multiselect__footer{display:flex;align-items:center;justify-content:space-between;padding:var(--neu-space-2) var(--neu-space-3);border-top:1px solid var(--neu-border);background:var(--neu-surface);flex-shrink:0}.neu-multiselect__footer-count{font-size:var(--neu-text-xs);color:var(--neu-text-muted)}.neu-multiselect__footer-actions{display:flex;align-items:center;gap:var(--neu-space-2)}.neu-multiselect__footer-mode{background:none;border:1px solid var(--neu-border);border-radius:var(--neu-radius-sm);padding:2px 6px;font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);color:var(--neu-text-muted);cursor:pointer;line-height:1.4}.neu-multiselect__footer-mode:hover{background:var(--neu-surface-2);color:var(--neu-text)}.neu-multiselect__footer-mode:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__footer-clear{background:none;border:none;padding:0;font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);color:var(--neu-primary);cursor:pointer;font-weight:500}.neu-multiselect__footer-clear:hover{text-decoration:underline}.neu-multiselect__footer-clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px;border-radius:var(--neu-radius-sm)}.neu-multiselect__count-badge{display:inline-flex;align-items:center;padding:2px 10px;background:var(--neu-primary-100, rgba(14, 165, 233, .12));color:var(--neu-primary-dark, var(--neu-primary));border-radius:var(--neu-radius-full);font-size:var(--neu-text-sm);font-weight:500}html[data-theme=dark] .neu-multiselect__count-badge{background:#0b66d4;color:#fff}.neu-multiselect__chip--overflow{background:var(--neu-surface-2);color:var(--neu-text-muted);border:1px dashed var(--neu-border);cursor:default;pointer-events:none}.neu-multiselect__error{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-error-text, var(--neu-error));font-family:var(--neu-font-sans)}.neu-multiselect__hint{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-text-muted);font-family:var(--neu-font-sans)}.neu-multiselect__sr-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.neu-multiselect__select-all{width:calc(100% - 16px);margin:8px;border:1px solid var(--neu-border);border-radius:var(--neu-radius-md);background:var(--neu-surface-2);color:var(--neu-text);padding:8px 10px;text-align:left;cursor:pointer}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: i1.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: ScrollingModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
732
739
  }
733
740
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuMultiselectComponent, decorators: [{
734
741
  type: Component,
@@ -896,105 +903,83 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
896
903
  />
897
904
  </div>
898
905
  }
906
+ @if (selectAll()) {
907
+ <button type="button" class="neu-multiselect__select-all" (click)="toggleAllFiltered($event)">
908
+ {{ allFilteredSelected() ? unselectAllLabel() : selectAllLabel() }}
909
+ </button>
910
+ }
899
911
 
900
912
  <!-- Opciones -->
901
913
  <div class="neu-multiselect__options">
902
- @if (virtualScroll()) {
914
+ <ng-template #multiselectOptionTpl let-option>
915
+ <div
916
+ class="neu-multiselect__option"
917
+ [class.neu-multiselect__option--selected]="isSelected(option.value)"
918
+ [class.neu-multiselect__option--disabled]="option.disabled"
919
+ role="option"
920
+ [id]="'neu-ms-opt-' + option.value"
921
+ [attr.aria-selected]="isSelected(option.value)"
922
+ [attr.aria-disabled]="option.disabled"
923
+ [attr.tabindex]="option.disabled ? null : '-1'"
924
+ (click)="toggleOption(option)"
925
+ (keydown.enter)="toggleOption(option)"
926
+ (keydown.space)="toggleOption(option)"
927
+ (keydown.arrowDown)="focusOptionByIndex($any($event), option, 1)"
928
+ (keydown.arrowUp)="focusOptionByIndex($any($event), option, -1)"
929
+ >
930
+ <span
931
+ class="neu-multiselect__checkbox"
932
+ [class.neu-multiselect__checkbox--checked]="isSelected(option.value)"
933
+ >
934
+ <svg
935
+ class="neu-multiselect__checkbox-check"
936
+ viewBox="0 0 12 10"
937
+ fill="none"
938
+ stroke="currentColor"
939
+ stroke-width="2"
940
+ stroke-linecap="round"
941
+ stroke-linejoin="round"
942
+ aria-hidden="true"
943
+ >
944
+ <polyline points="1 5 4.5 9 11 1" />
945
+ </svg>
946
+ </span>
947
+ @if (itemTpl()) {
948
+ <ng-container
949
+ [ngTemplateOutlet]="itemTpl()!.templateRef"
950
+ [ngTemplateOutletContext]="{ $implicit: option }"
951
+ />
952
+ } @else {
953
+ {{ option.label }}
954
+ }
955
+ </div>
956
+ </ng-template>
957
+
958
+ @if (loading()) {
959
+ <div class="neu-multiselect__empty" role="status">{{ loadingLabel() }}</div>
960
+ } @else if (virtualScroll()) {
903
961
  <cdk-virtual-scroll-viewport
904
962
  class="neu-multiselect__viewport"
905
963
  [itemSize]="virtualScrollItemSize()"
906
964
  [style.height]="virtualViewportHeight()"
907
965
  >
908
- <div
909
- *cdkVirtualFor="let option of filteredOptions(); trackBy: trackByOptionValue"
910
- class="neu-multiselect__option"
911
- [class.neu-multiselect__option--selected]="isSelected(option.value)"
912
- [class.neu-multiselect__option--disabled]="option.disabled"
913
- role="option"
914
- [id]="'neu-ms-opt-' + option.value"
915
- [attr.aria-selected]="isSelected(option.value)"
916
- [attr.aria-disabled]="option.disabled"
917
- [attr.tabindex]="option.disabled ? null : '-1'"
918
- (click)="toggleOption(option)"
919
- (keydown.enter)="toggleOption(option)"
920
- (keydown.space)="toggleOption(option)"
921
- (keydown.arrowDown)="focusOptionByIndex($any($event), option, 1)"
922
- (keydown.arrowUp)="focusOptionByIndex($any($event), option, -1)"
923
- >
924
- <span
925
- class="neu-multiselect__checkbox"
926
- [class.neu-multiselect__checkbox--checked]="isSelected(option.value)"
927
- >
928
- <svg
929
- class="neu-multiselect__checkbox-check"
930
- viewBox="0 0 12 10"
931
- fill="none"
932
- stroke="currentColor"
933
- stroke-width="2"
934
- stroke-linecap="round"
935
- stroke-linejoin="round"
936
- aria-hidden="true"
937
- >
938
- <polyline points="1 5 4.5 9 11 1" />
939
- </svg>
940
- </span>
941
- @if (itemTpl()) {
942
- <ng-container
943
- [ngTemplateOutlet]="itemTpl()!.templateRef"
944
- [ngTemplateOutletContext]="{ $implicit: option }"
945
- />
946
- } @else {
947
- {{ option.label }}
948
- }
949
- </div>
966
+ <ng-container *cdkVirtualFor="let option of filteredOptions(); trackBy: trackByOptionValue">
967
+ <ng-container
968
+ [ngTemplateOutlet]="multiselectOptionTpl"
969
+ [ngTemplateOutletContext]="{ $implicit: option }"
970
+ />
971
+ </ng-container>
950
972
  </cdk-virtual-scroll-viewport>
951
973
  } @else {
952
974
  @for (option of filteredOptions(); track option.value) {
953
- <div
954
- class="neu-multiselect__option"
955
- [class.neu-multiselect__option--selected]="isSelected(option.value)"
956
- [class.neu-multiselect__option--disabled]="option.disabled"
957
- role="option"
958
- [id]="'neu-ms-opt-' + option.value"
959
- [attr.aria-selected]="isSelected(option.value)"
960
- [attr.aria-disabled]="option.disabled"
961
- [attr.tabindex]="option.disabled ? null : '-1'"
962
- (click)="toggleOption(option)"
963
- (keydown.enter)="toggleOption(option)"
964
- (keydown.space)="toggleOption(option)"
965
- (keydown.arrowDown)="focusOptionByIndex($any($event), option, 1)"
966
- (keydown.arrowUp)="focusOptionByIndex($any($event), option, -1)"
967
- >
968
- <span
969
- class="neu-multiselect__checkbox"
970
- [class.neu-multiselect__checkbox--checked]="isSelected(option.value)"
971
- >
972
- <svg
973
- class="neu-multiselect__checkbox-check"
974
- viewBox="0 0 12 10"
975
- fill="none"
976
- stroke="currentColor"
977
- stroke-width="2"
978
- stroke-linecap="round"
979
- stroke-linejoin="round"
980
- aria-hidden="true"
981
- >
982
- <polyline points="1 5 4.5 9 11 1" />
983
- </svg>
984
- </span>
985
- @if (itemTpl()) {
986
- <ng-container
987
- [ngTemplateOutlet]="itemTpl()!.templateRef"
988
- [ngTemplateOutletContext]="{ $implicit: option }"
989
- />
990
- } @else {
991
- {{ option.label }}
992
- }
993
- </div>
975
+ <ng-container
976
+ [ngTemplateOutlet]="multiselectOptionTpl"
977
+ [ngTemplateOutletContext]="{ $implicit: option }"
978
+ />
994
979
  }
995
980
  }
996
981
 
997
- @if (filteredOptions().length === 0) {
982
+ @if (!loading() && filteredOptions().length === 0) {
998
983
  <div class="neu-multiselect__empty">{{ noResultsMessage() }}</div>
999
984
  }
1000
985
  </div>
@@ -1039,8 +1024,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1039
1024
  } @else if (hint()) {
1040
1025
  <p class="neu-multiselect__hint" [id]="_triggerId + '-hint'">{{ hint() }}</p>
1041
1026
  }
1042
- `, styles: [".neu-multiselect__static-label{display:block;font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);margin-bottom:var(--neu-space-2)}.neu-multiselect__label{position:absolute;left:var(--neu-space-3);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base);color:var(--neu-text-muted);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-8));transition:top var(--neu-transition),font-size var(--neu-transition),color var(--neu-transition),transform var(--neu-transition),padding var(--neu-transition),background var(--neu-transition)}.neu-multiselect--open .neu-multiselect__label,.neu-multiselect--has-value .neu-multiselect__label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface);padding:0 4px;left:calc(var(--neu-space-3) - 4px)}.neu-multiselect--open .neu-multiselect__label{color:var(--neu-primary)}.neu-multiselect--error .neu-multiselect__label{color:var(--neu-error)}.neu-multiselect--disabled .neu-multiselect__label{background:var(--neu-surface-2)}.neu-multiselect{position:relative;font-family:var(--neu-font-sans)}.neu-multiselect--sm .neu-multiselect__trigger{min-height:36px;font-size:var(--neu-text-sm);padding:var(--neu-space-1) var(--neu-space-2);padding-right:36px}.neu-multiselect--lg .neu-multiselect__trigger{min-height:56px}.neu-multiselect__trigger{display:flex;align-items:center;width:100%;min-height:48px;padding:var(--neu-space-2) var(--neu-space-3);padding-right:36px;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);cursor:pointer;text-align:left;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-multiselect__trigger:hover:not([aria-disabled=true]){border-color:var(--neu-border-hover)}.neu-multiselect__trigger:focus-visible{outline:none;border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-multiselect__trigger[aria-disabled=true]{opacity:.6;cursor:not-allowed;background:var(--neu-surface-2)}.neu-multiselect--open .neu-multiselect__trigger{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-multiselect--error .neu-multiselect__trigger{border-color:var(--neu-error)}.neu-multiselect--error .neu-multiselect__trigger:focus-visible{box-shadow:0 0 0 3px #ef44441f}.neu-multiselect__chips{display:flex;flex-wrap:wrap;gap:var(--neu-space-1);flex:1;min-width:0}.neu-multiselect__placeholder{color:var(--neu-text-disabled);font-size:var(--neu-text-base);line-height:1.5}.neu-multiselect:not(.neu-multiselect--no-float):not(.neu-multiselect--open) .neu-multiselect__placeholder{visibility:hidden}.neu-multiselect__chip{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 8px;background:var(--neu-primary-soft, rgba(0, 122, 255, .1));color:var(--neu-primary);border-radius:var(--neu-radius-sm);font-size:var(--neu-text-xs);font-weight:500;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.neu-multiselect__chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;cursor:pointer;color:inherit;opacity:.7;border-radius:2px;transition:opacity var(--neu-transition);flex-shrink:0}.neu-multiselect__chip-remove:hover{opacity:1}.neu-multiselect__chip-remove:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__chip-remove svg{width:10px;height:10px}.neu-multiselect__clear{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:2px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);flex-shrink:0;transition:color var(--neu-transition),background var(--neu-transition)}.neu-multiselect__clear svg{width:14px;height:14px}.neu-multiselect__clear:hover{color:var(--neu-text);background:var(--neu-surface-3)}.neu-multiselect__clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__chevron{position:absolute;right:var(--neu-space-3);top:50%;transform:translateY(-50%);width:16px;height:16px;color:var(--neu-text-muted);pointer-events:none;transition:transform var(--neu-transition);flex-shrink:0}.neu-multiselect--open .neu-multiselect__chevron{transform:translateY(-50%) rotate(180deg)}.neu-multiselect__panel{position:relative;z-index:200;box-sizing:border-box;width:100%;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);box-shadow:var(--neu-shadow-lg);overflow:hidden;max-height:280px;display:flex;flex-direction:column;animation:neu-multiselect-fade-in .12s ease}.neu-multiselect__panel--virtual{overflow:visible}@media(max-width:600px){.neu-multiselect__panel{left:auto;right:0;width:min(max(100%,240px),100vw - 2rem);max-width:calc(100vw - 2rem)}}@keyframes neu-multiselect-fade-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-multiselect__search{padding:var(--neu-space-2);border-bottom:1px solid var(--neu-border);flex-shrink:0}.neu-multiselect__search-input{width:100%;height:34px;padding:0 var(--neu-space-3);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-bg);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-multiselect__search-input:focus{border-color:var(--neu-primary);box-shadow:0 0 0 2px #007aff1f}.neu-multiselect__search-input::placeholder{color:var(--neu-text-disabled)}.neu-multiselect__options{flex:1;overflow-y:auto;min-height:0}.neu-multiselect__panel--virtual .neu-multiselect__options{overflow:hidden}.neu-multiselect__viewport{width:100%}.neu-multiselect__option{display:flex;align-items:center;gap:var(--neu-space-2);padding:10px var(--neu-space-3);min-height:var(--neu-multiselect-option-height, 44px);box-sizing:border-box;cursor:pointer;font-size:var(--neu-text-sm);color:var(--neu-text);transition:background var(--neu-transition)}.neu-multiselect__option:hover:not(.neu-multiselect__option--disabled){background:var(--neu-surface-2)}.neu-multiselect__option--selected{background:var(--neu-primary-soft, rgba(0, 122, 255, .06));color:var(--neu-primary);font-weight:500}.neu-multiselect__option--disabled{opacity:.4;cursor:not-allowed}.neu-multiselect__checkbox{display:flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:3px;border:1.5px solid var(--neu-border);background:var(--neu-bg);flex-shrink:0;transition:border-color var(--neu-transition),background var(--neu-transition)}.neu-multiselect__checkbox--checked{background:var(--neu-primary);border-color:var(--neu-primary);color:#fff}.neu-multiselect__checkbox-check{width:10px;height:8px;opacity:0;transform:scale(.6);transition:opacity .12s ease,transform .12s ease}.neu-multiselect__checkbox--checked .neu-multiselect__checkbox-check{opacity:1;transform:scale(1)}.neu-multiselect__empty{padding:var(--neu-space-4);text-align:center;font-size:var(--neu-text-sm);color:var(--neu-text-disabled);font-family:var(--neu-font-sans)}.neu-multiselect__footer{display:flex;align-items:center;justify-content:space-between;padding:var(--neu-space-2) var(--neu-space-3);border-top:1px solid var(--neu-border);background:var(--neu-surface);flex-shrink:0}.neu-multiselect__footer-count{font-size:var(--neu-text-xs);color:var(--neu-text-muted)}.neu-multiselect__footer-actions{display:flex;align-items:center;gap:var(--neu-space-2)}.neu-multiselect__footer-mode{background:none;border:1px solid var(--neu-border);border-radius:var(--neu-radius-sm);padding:2px 6px;font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);color:var(--neu-text-muted);cursor:pointer;line-height:1.4}.neu-multiselect__footer-mode:hover{background:var(--neu-surface-2);color:var(--neu-text)}.neu-multiselect__footer-mode:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__footer-clear{background:none;border:none;padding:0;font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);color:var(--neu-primary);cursor:pointer;font-weight:500}.neu-multiselect__footer-clear:hover{text-decoration:underline}.neu-multiselect__footer-clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px;border-radius:var(--neu-radius-sm)}.neu-multiselect__count-badge{display:inline-flex;align-items:center;padding:2px 10px;background:var(--neu-primary-100, rgba(14, 165, 233, .12));color:var(--neu-primary-dark, var(--neu-primary));border-radius:var(--neu-radius-full);font-size:var(--neu-text-sm);font-weight:500}.neu-multiselect__chip--overflow{background:var(--neu-surface-2);color:var(--neu-text-muted);border:1px dashed var(--neu-border);cursor:default;pointer-events:none}.neu-multiselect__error{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-error-text, var(--neu-error));font-family:var(--neu-font-sans)}.neu-multiselect__hint{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-text-muted);font-family:var(--neu-font-sans)}.neu-multiselect__sr-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
1043
- }], ctorParameters: () => [], propDecorators: { _viewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NeuMultiselectItemDirective), { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], floatingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatingLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], noResultsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsMessage", required: false }] }], clearAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearAllLabel", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollVisibleItems", required: false }] }], clearAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearAriaLabel", required: false }] }], urlParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "urlParam", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
1027
+ `, styles: [".neu-multiselect__static-label{display:block;font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);margin-bottom:var(--neu-space-2)}.neu-multiselect__label{position:absolute;left:var(--neu-space-3);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base);color:var(--neu-text-muted);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-8));transition:top var(--neu-transition),font-size var(--neu-transition),color var(--neu-transition),transform var(--neu-transition),padding var(--neu-transition),background var(--neu-transition)}.neu-multiselect--open .neu-multiselect__label,.neu-multiselect--has-value .neu-multiselect__label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface);padding:0 4px;left:calc(var(--neu-space-3) - 4px)}.neu-multiselect--open .neu-multiselect__label{color:var(--neu-primary)}.neu-multiselect--error .neu-multiselect__label{color:var(--neu-error)}.neu-multiselect--disabled .neu-multiselect__label{background:var(--neu-surface-2)}.neu-multiselect{position:relative;font-family:var(--neu-font-sans)}.neu-multiselect--sm .neu-multiselect__trigger{min-height:36px;font-size:var(--neu-text-sm);padding:var(--neu-space-1) var(--neu-space-2);padding-right:36px}.neu-multiselect--lg .neu-multiselect__trigger{min-height:56px}.neu-multiselect__trigger{display:flex;align-items:center;width:100%;min-height:48px;padding:var(--neu-space-2) var(--neu-space-3);padding-right:36px;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);cursor:pointer;text-align:left;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-multiselect__trigger:hover:not([aria-disabled=true]){border-color:var(--neu-border-hover)}.neu-multiselect__trigger:focus-visible{outline:none;border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-multiselect__trigger[aria-disabled=true]{opacity:.6;cursor:not-allowed;background:var(--neu-surface-2)}.neu-multiselect--open .neu-multiselect__trigger{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-multiselect--error .neu-multiselect__trigger{border-color:var(--neu-error)}.neu-multiselect--error .neu-multiselect__trigger:focus-visible{box-shadow:0 0 0 3px #ef44441f}.neu-multiselect__chips{display:flex;flex-wrap:wrap;gap:var(--neu-space-1);flex:1;min-width:0}.neu-multiselect__placeholder{color:var(--neu-text-disabled);font-size:var(--neu-text-base);line-height:1.5}.neu-multiselect:not(.neu-multiselect--no-float):not(.neu-multiselect--open) .neu-multiselect__placeholder{visibility:hidden}.neu-multiselect__chip{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 8px;background:var(--neu-primary-soft, rgba(0, 122, 255, .1));color:var(--neu-primary);border-radius:var(--neu-radius-sm);font-size:var(--neu-text-xs);font-weight:500;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.neu-multiselect__chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;cursor:pointer;color:inherit;opacity:.7;border-radius:2px;transition:opacity var(--neu-transition);flex-shrink:0}.neu-multiselect__chip-remove:hover{opacity:1}.neu-multiselect__chip-remove:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__chip-remove svg{width:10px;height:10px}.neu-multiselect__clear{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:2px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);flex-shrink:0;transition:color var(--neu-transition),background var(--neu-transition)}.neu-multiselect__clear svg{width:14px;height:14px}.neu-multiselect__clear:hover{color:var(--neu-text);background:var(--neu-surface-3)}.neu-multiselect__clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__chevron{position:absolute;right:var(--neu-space-3);top:50%;transform:translateY(-50%);width:16px;height:16px;color:var(--neu-text-muted);pointer-events:none;transition:transform var(--neu-transition);flex-shrink:0}.neu-multiselect--open .neu-multiselect__chevron{transform:translateY(-50%) rotate(180deg)}.neu-multiselect__panel{position:relative;z-index:200;box-sizing:border-box;width:100%;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);box-shadow:var(--neu-shadow-lg);overflow:hidden;max-height:280px;display:flex;flex-direction:column;animation:neu-multiselect-fade-in .12s ease}.neu-multiselect__panel--virtual{overflow:visible}@media(max-width:600px){.neu-multiselect__panel{left:auto;right:0;width:min(max(100%,240px),100vw - 2rem);max-width:calc(100vw - 2rem)}}@keyframes neu-multiselect-fade-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-multiselect__search{padding:var(--neu-space-2);border-bottom:1px solid var(--neu-border);flex-shrink:0}.neu-multiselect__search-input{width:100%;height:34px;padding:0 var(--neu-space-3);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-bg);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-multiselect__search-input:focus{border-color:var(--neu-primary);box-shadow:0 0 0 2px #007aff1f}.neu-multiselect__search-input::placeholder{color:var(--neu-text-disabled)}.neu-multiselect__options{flex:1;overflow-y:auto;min-height:0}.neu-multiselect__panel--virtual .neu-multiselect__options{overflow:hidden}.neu-multiselect__viewport{width:100%}.neu-multiselect__option{display:flex;align-items:center;gap:var(--neu-space-2);padding:10px var(--neu-space-3);min-height:var(--neu-multiselect-option-height, 44px);box-sizing:border-box;cursor:pointer;font-size:var(--neu-text-sm);color:var(--neu-text);transition:background var(--neu-transition)}.neu-multiselect__option:hover:not(.neu-multiselect__option--disabled){background:var(--neu-surface-2)}.neu-multiselect__option--selected{background:var(--neu-primary-soft, rgba(0, 122, 255, .06));color:var(--neu-primary);font-weight:500}.neu-multiselect__option--disabled{opacity:.4;cursor:not-allowed}.neu-multiselect__checkbox{display:flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:3px;border:1.5px solid var(--neu-border);background:var(--neu-bg);flex-shrink:0;transition:border-color var(--neu-transition),background var(--neu-transition)}.neu-multiselect__checkbox--checked{background:var(--neu-primary);border-color:var(--neu-primary);color:#fff}.neu-multiselect__checkbox-check{width:10px;height:8px;opacity:0;transform:scale(.6);transition:opacity .12s ease,transform .12s ease}.neu-multiselect__checkbox--checked .neu-multiselect__checkbox-check{opacity:1;transform:scale(1)}.neu-multiselect__empty{padding:var(--neu-space-4);text-align:center;font-size:var(--neu-text-sm);color:var(--neu-text-disabled);font-family:var(--neu-font-sans)}.neu-multiselect__footer{display:flex;align-items:center;justify-content:space-between;padding:var(--neu-space-2) var(--neu-space-3);border-top:1px solid var(--neu-border);background:var(--neu-surface);flex-shrink:0}.neu-multiselect__footer-count{font-size:var(--neu-text-xs);color:var(--neu-text-muted)}.neu-multiselect__footer-actions{display:flex;align-items:center;gap:var(--neu-space-2)}.neu-multiselect__footer-mode{background:none;border:1px solid var(--neu-border);border-radius:var(--neu-radius-sm);padding:2px 6px;font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);color:var(--neu-text-muted);cursor:pointer;line-height:1.4}.neu-multiselect__footer-mode:hover{background:var(--neu-surface-2);color:var(--neu-text)}.neu-multiselect__footer-mode:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-multiselect__footer-clear{background:none;border:none;padding:0;font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);color:var(--neu-primary);cursor:pointer;font-weight:500}.neu-multiselect__footer-clear:hover{text-decoration:underline}.neu-multiselect__footer-clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px;border-radius:var(--neu-radius-sm)}.neu-multiselect__count-badge{display:inline-flex;align-items:center;padding:2px 10px;background:var(--neu-primary-100, rgba(14, 165, 233, .12));color:var(--neu-primary-dark, var(--neu-primary));border-radius:var(--neu-radius-full);font-size:var(--neu-text-sm);font-weight:500}html[data-theme=dark] .neu-multiselect__count-badge{background:#0b66d4;color:#fff}.neu-multiselect__chip--overflow{background:var(--neu-surface-2);color:var(--neu-text-muted);border:1px dashed var(--neu-border);cursor:default;pointer-events:none}.neu-multiselect__error{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-error-text, var(--neu-error));font-family:var(--neu-font-sans)}.neu-multiselect__hint{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-text-muted);font-family:var(--neu-font-sans)}.neu-multiselect__sr-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.neu-multiselect__select-all{width:calc(100% - 16px);margin:8px;border:1px solid var(--neu-border);border-radius:var(--neu-radius-md);background:var(--neu-surface-2);color:var(--neu-text);padding:8px 10px;text-align:left;cursor:pointer}\n"] }]
1028
+ }], ctorParameters: () => [], propDecorators: { _viewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NeuMultiselectItemDirective), { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], floatingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatingLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingLabel", required: false }] }], selectAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAll", required: false }] }], selectAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllLabel", required: false }] }], unselectAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "unselectAllLabel", required: false }] }], noResultsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsMessage", required: false }] }], clearAllLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearAllLabel", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollVisibleItems", required: false }] }], clearAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearAriaLabel", required: false }] }], urlParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "urlParam", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
1044
1029
 
1045
1030
  /**
1046
1031
  * Generated bundle index. Do not edit.