ngx-com 0.0.21 → 0.1.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.
- package/README.md +137 -33
- package/fesm2022/ngx-com-components-alert.mjs +21 -11
- package/fesm2022/ngx-com-components-alert.mjs.map +1 -1
- package/fesm2022/ngx-com-components-avatar.mjs +9 -7
- package/fesm2022/ngx-com-components-avatar.mjs.map +1 -1
- package/fesm2022/ngx-com-components-button.mjs +1 -1
- package/fesm2022/ngx-com-components-button.mjs.map +1 -1
- package/fesm2022/ngx-com-components-calendar.mjs +27 -3112
- package/fesm2022/ngx-com-components-calendar.mjs.map +1 -1
- package/fesm2022/ngx-com-components-card.mjs +8 -8
- package/fesm2022/ngx-com-components-card.mjs.map +1 -1
- package/fesm2022/ngx-com-components-carousel.mjs +16 -4
- package/fesm2022/ngx-com-components-carousel.mjs.map +1 -1
- package/fesm2022/ngx-com-components-checkbox.mjs +1 -1
- package/fesm2022/ngx-com-components-checkbox.mjs.map +1 -1
- package/fesm2022/ngx-com-components-code-block.mjs +9 -9
- package/fesm2022/ngx-com-components-code-block.mjs.map +1 -1
- package/fesm2022/ngx-com-components-collapsible.mjs +15 -13
- package/fesm2022/ngx-com-components-collapsible.mjs.map +1 -1
- package/fesm2022/ngx-com-components-confirm.mjs +4 -4
- package/fesm2022/ngx-com-components-confirm.mjs.map +1 -1
- package/fesm2022/ngx-com-components-datepicker.mjs +2334 -0
- package/fesm2022/ngx-com-components-datepicker.mjs.map +1 -0
- package/fesm2022/ngx-com-components-dialog.mjs +47 -45
- package/fesm2022/ngx-com-components-dialog.mjs.map +1 -1
- package/fesm2022/ngx-com-components-dropdown.mjs +446 -340
- package/fesm2022/ngx-com-components-dropdown.mjs.map +1 -1
- package/fesm2022/ngx-com-components-empty-state.mjs +5 -3
- package/fesm2022/ngx-com-components-empty-state.mjs.map +1 -1
- package/fesm2022/ngx-com-components-form-field.mjs +11 -6
- package/fesm2022/ngx-com-components-form-field.mjs.map +1 -1
- package/fesm2022/ngx-com-components-icon-lucide.mjs +41 -0
- package/fesm2022/ngx-com-components-icon-lucide.mjs.map +1 -0
- package/fesm2022/ngx-com-components-icon.mjs +89 -61
- package/fesm2022/ngx-com-components-icon.mjs.map +1 -1
- package/fesm2022/ngx-com-components-item.mjs +14 -4
- package/fesm2022/ngx-com-components-item.mjs.map +1 -1
- package/fesm2022/ngx-com-components-menu.mjs +61 -69
- package/fesm2022/ngx-com-components-menu.mjs.map +1 -1
- package/fesm2022/ngx-com-components-native-control.mjs +170 -0
- package/fesm2022/ngx-com-components-native-control.mjs.map +1 -0
- package/fesm2022/ngx-com-components-paginator.mjs +11 -3
- package/fesm2022/ngx-com-components-paginator.mjs.map +1 -1
- package/fesm2022/ngx-com-components-popover.mjs +58 -33
- package/fesm2022/ngx-com-components-popover.mjs.map +1 -1
- package/fesm2022/ngx-com-components-radio.mjs +4 -4
- package/fesm2022/ngx-com-components-radio.mjs.map +1 -1
- package/fesm2022/ngx-com-components-segmented-control.mjs +6 -4
- package/fesm2022/ngx-com-components-segmented-control.mjs.map +1 -1
- package/fesm2022/ngx-com-components-sort.mjs +63 -57
- package/fesm2022/ngx-com-components-sort.mjs.map +1 -1
- package/fesm2022/ngx-com-components-spinner.mjs +6 -6
- package/fesm2022/ngx-com-components-spinner.mjs.map +1 -1
- package/fesm2022/ngx-com-components-switch.mjs +18 -9
- package/fesm2022/ngx-com-components-switch.mjs.map +1 -1
- package/fesm2022/ngx-com-components-table.mjs +23 -9
- package/fesm2022/ngx-com-components-table.mjs.map +1 -1
- package/fesm2022/ngx-com-components-tabs.mjs +81 -58
- package/fesm2022/ngx-com-components-tabs.mjs.map +1 -1
- package/fesm2022/ngx-com-components-timepicker.mjs +1048 -0
- package/fesm2022/ngx-com-components-timepicker.mjs.map +1 -0
- package/fesm2022/ngx-com-components-toast.mjs +18 -14
- package/fesm2022/ngx-com-components-toast.mjs.map +1 -1
- package/fesm2022/ngx-com-components-tooltip.mjs +5 -5
- package/fesm2022/ngx-com-components-tooltip.mjs.map +1 -1
- package/fesm2022/ngx-com-components.mjs +0 -13
- package/fesm2022/ngx-com-components.mjs.map +1 -1
- package/fesm2022/ngx-com-tokens.mjs +0 -8
- package/fesm2022/ngx-com-tokens.mjs.map +1 -1
- package/fesm2022/ngx-com-utils.mjs +13 -1
- package/fesm2022/ngx-com-utils.mjs.map +1 -1
- package/fesm2022/ngx-com.mjs +1 -1
- package/fesm2022/ngx-com.mjs.map +1 -1
- package/package.json +51 -8
- package/styles/animations.css +38 -0
- package/styles/candy.css +121 -0
- package/styles/dark.css +159 -0
- package/styles/forest.css +117 -0
- package/styles/ocean.css +117 -0
- package/styles/themes.css +7 -0
- package/styles/tokens.css +277 -0
- package/styles/utilities.css +16 -0
- package/types/ngx-com-components-alert.d.ts +14 -4
- package/types/ngx-com-components-avatar.d.ts +2 -0
- package/types/ngx-com-components-calendar.d.ts +3 -747
- package/types/ngx-com-components-card.d.ts +2 -2
- package/types/ngx-com-components-carousel.d.ts +11 -1
- package/types/ngx-com-components-code-block.d.ts +4 -4
- package/types/ngx-com-components-collapsible.d.ts +10 -2
- package/types/ngx-com-components-confirm.d.ts +2 -2
- package/types/ngx-com-components-datepicker.d.ts +623 -0
- package/types/ngx-com-components-dialog.d.ts +5 -2
- package/types/ngx-com-components-dropdown.d.ts +22 -4
- package/types/ngx-com-components-empty-state.d.ts +2 -0
- package/types/ngx-com-components-form-field.d.ts +4 -1
- package/types/ngx-com-components-icon-lucide.d.ts +32 -0
- package/types/ngx-com-components-icon.d.ts +49 -35
- package/types/ngx-com-components-item.d.ts +12 -2
- package/types/ngx-com-components-menu.d.ts +38 -38
- package/types/ngx-com-components-native-control.d.ts +99 -0
- package/types/ngx-com-components-paginator.d.ts +2 -0
- package/types/ngx-com-components-popover.d.ts +19 -12
- package/types/ngx-com-components-segmented-control.d.ts +3 -1
- package/types/ngx-com-components-sort.d.ts +13 -10
- package/types/ngx-com-components-switch.d.ts +7 -2
- package/types/ngx-com-components-table.d.ts +16 -2
- package/types/ngx-com-components-tabs.d.ts +46 -34
- package/types/ngx-com-components-timepicker.d.ts +273 -0
- package/types/ngx-com-components-toast.d.ts +4 -2
- package/types/ngx-com-components-tooltip.d.ts +1 -1
- package/types/ngx-com-components.d.ts +6 -7
- package/types/ngx-com-tokens.d.ts +5 -3
- package/types/ngx-com-utils.d.ts +11 -1
- package/types/ngx-com.d.ts +1 -1
|
@@ -4,12 +4,13 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
|
4
4
|
import { NgTemplateOutlet } from '@angular/common';
|
|
5
5
|
import { NgForm, FormGroupDirective, NgControl } from '@angular/forms';
|
|
6
6
|
import { ErrorStateMatcher, FormFieldControl } from 'ngx-com/components/form-field';
|
|
7
|
+
import * as i1 from '@angular/cdk/overlay';
|
|
7
8
|
import { Overlay, OverlayModule } from '@angular/cdk/overlay';
|
|
9
|
+
import { CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll, CdkVirtualForOf } from '@angular/cdk/scrolling';
|
|
8
10
|
import { TemplatePortal } from '@angular/cdk/portal';
|
|
9
11
|
import { LiveAnnouncer } from '@angular/cdk/a11y';
|
|
10
12
|
import { cva } from 'class-variance-authority';
|
|
11
13
|
import { mergeClasses } from 'ngx-com/utils';
|
|
12
|
-
import { CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll, CdkVirtualForOf } from '@angular/cdk/scrolling';
|
|
13
14
|
import { Subject } from 'rxjs';
|
|
14
15
|
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
|
15
16
|
|
|
@@ -31,7 +32,7 @@ const dropdownTriggerVariants = cva([
|
|
|
31
32
|
'bg-input-background',
|
|
32
33
|
'text-input-foreground',
|
|
33
34
|
'transition-colors',
|
|
34
|
-
'duration-
|
|
35
|
+
'duration-normal',
|
|
35
36
|
'placeholder:text-input-placeholder',
|
|
36
37
|
'focus-visible:outline-[1px]',
|
|
37
38
|
'focus-visible:outline-offset-2',
|
|
@@ -130,7 +131,7 @@ const dropdownTriggerVariants = cva([
|
|
|
130
131
|
/**
|
|
131
132
|
* CVA variants for the dropdown panel (overlay).
|
|
132
133
|
*
|
|
133
|
-
* @tokens `--color-popover`, `--color-popover-foreground`, `--color-border-subtle`, `--radius-overlay`
|
|
134
|
+
* @tokens `--color-popover`, `--color-popover-foreground`, `--color-border-subtle`, `--shadow-overlay`, `--radius-overlay`
|
|
134
135
|
*/
|
|
135
136
|
const dropdownPanelVariants = cva([
|
|
136
137
|
'z-50',
|
|
@@ -140,7 +141,7 @@ const dropdownPanelVariants = cva([
|
|
|
140
141
|
'border-border-subtle',
|
|
141
142
|
'bg-popover',
|
|
142
143
|
'text-popover-foreground',
|
|
143
|
-
'shadow-
|
|
144
|
+
'shadow-overlay',
|
|
144
145
|
'outline-none',
|
|
145
146
|
], {
|
|
146
147
|
variants: {
|
|
@@ -169,7 +170,7 @@ const dropdownOptionVariants = cva([
|
|
|
169
170
|
'items-center',
|
|
170
171
|
'outline-none',
|
|
171
172
|
'transition-colors',
|
|
172
|
-
'duration-
|
|
173
|
+
'duration-fast',
|
|
173
174
|
], {
|
|
174
175
|
variants: {
|
|
175
176
|
size: {
|
|
@@ -251,7 +252,7 @@ const dropdownTagVariants = cva([
|
|
|
251
252
|
'rounded-tag',
|
|
252
253
|
'font-medium',
|
|
253
254
|
'transition-colors',
|
|
254
|
-
'duration-
|
|
255
|
+
'duration-fast',
|
|
255
256
|
], {
|
|
256
257
|
variants: {
|
|
257
258
|
size: {
|
|
@@ -418,7 +419,7 @@ const dropdownChevronVariants = cva([
|
|
|
418
419
|
'shrink-0',
|
|
419
420
|
'text-muted-foreground',
|
|
420
421
|
'transition-transform',
|
|
421
|
-
'duration-
|
|
422
|
+
'duration-slow',
|
|
422
423
|
], {
|
|
423
424
|
variants: {
|
|
424
425
|
size: {
|
|
@@ -478,6 +479,7 @@ class ComDropdownOption {
|
|
|
478
479
|
/** Additional CSS classes to apply. */
|
|
479
480
|
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : {}), alias: 'class' });
|
|
480
481
|
/** Emitted when the option is selected. */
|
|
482
|
+
// eslint-disable-next-line @angular-eslint/no-output-native -- intentional: matches listbox/combobox select pattern
|
|
481
483
|
select = output();
|
|
482
484
|
/** Emitted when the mouse enters the option. */
|
|
483
485
|
hover = output();
|
|
@@ -545,7 +547,10 @@ class ComDropdownOption {
|
|
|
545
547
|
[attr.data-active]="active() || null"
|
|
546
548
|
[attr.data-selected]="selected() || null"
|
|
547
549
|
[attr.data-disabled]="disabled() || null"
|
|
550
|
+
tabindex="-1"
|
|
548
551
|
(click)="onOptionClick($event)"
|
|
552
|
+
(keydown.enter)="onOptionClick($event)"
|
|
553
|
+
(keydown.space)="onOptionClick($event)"
|
|
549
554
|
(mouseenter)="onMouseEnter()"
|
|
550
555
|
>
|
|
551
556
|
@if (optionTemplate()) {
|
|
@@ -588,7 +593,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
588
593
|
[attr.data-active]="active() || null"
|
|
589
594
|
[attr.data-selected]="selected() || null"
|
|
590
595
|
[attr.data-disabled]="disabled() || null"
|
|
596
|
+
tabindex="-1"
|
|
591
597
|
(click)="onOptionClick($event)"
|
|
598
|
+
(keydown.enter)="onOptionClick($event)"
|
|
599
|
+
(keydown.space)="onOptionClick($event)"
|
|
592
600
|
(mouseenter)="onMouseEnter()"
|
|
593
601
|
>
|
|
594
602
|
@if (optionTemplate()) {
|
|
@@ -622,228 +630,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
622
630
|
}]
|
|
623
631
|
}], propDecorators: { optionRef: [{ type: i0.ViewChild, args: ['optionElement', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], displayText: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayText", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], optionTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionTemplate", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], select: [{ type: i0.Output, args: ["select"] }], hover: [{ type: i0.Output, args: ["hover"] }] } });
|
|
624
632
|
|
|
625
|
-
/**
|
|
626
|
-
* The overlay panel containing the dropdown options.
|
|
627
|
-
* Supports virtual scrolling for large lists.
|
|
628
|
-
*
|
|
629
|
-
* @example
|
|
630
|
-
* ```html
|
|
631
|
-
* <com-dropdown-panel
|
|
632
|
-
* [options]="filteredOptions()"
|
|
633
|
-
* [maxHeight]="'300px'"
|
|
634
|
-
* [virtualScrollEnabled]="true"
|
|
635
|
-
* >
|
|
636
|
-
* <ng-content />
|
|
637
|
-
* </com-dropdown-panel>
|
|
638
|
-
* ```
|
|
639
|
-
*
|
|
640
|
-
* @tokens `--color-popover`, `--color-popover-foreground`, `--color-border-subtle`,
|
|
641
|
-
* `--color-muted-foreground`, `--radius-overlay`
|
|
642
|
-
*/
|
|
643
|
-
class ComDropdownPanel {
|
|
644
|
-
/** Reference to the panel element. */
|
|
645
|
-
panelRef = viewChild('panelElement', ...(ngDevMode ? [{ debugName: "panelRef" }] : []));
|
|
646
|
-
/** Reference to the virtual scroll viewport (when enabled). */
|
|
647
|
-
viewport = viewChild('viewport', ...(ngDevMode ? [{ debugName: "viewport" }] : []));
|
|
648
|
-
/** Unique identifier for the panel. */
|
|
649
|
-
panelId = input('', ...(ngDevMode ? [{ debugName: "panelId" }] : []));
|
|
650
|
-
/** The processed options to display. */
|
|
651
|
-
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
652
|
-
/** Maximum height of the panel. */
|
|
653
|
-
maxHeight = input('256px', ...(ngDevMode ? [{ debugName: "maxHeight" }] : []));
|
|
654
|
-
/** Whether multiple selection is enabled. */
|
|
655
|
-
multiselectable = input(false, ...(ngDevMode ? [{ debugName: "multiselectable" }] : []));
|
|
656
|
-
/** Size variant for styling. */
|
|
657
|
-
size = input('default', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
658
|
-
/** Additional CSS classes to apply to the panel. */
|
|
659
|
-
panelClass = input('', ...(ngDevMode ? [{ debugName: "panelClass" }] : []));
|
|
660
|
-
/** Whether virtual scrolling is enabled. */
|
|
661
|
-
virtualScrollEnabled = input(false, ...(ngDevMode ? [{ debugName: "virtualScrollEnabled" }] : []));
|
|
662
|
-
/** Item size for virtual scrolling (in pixels). */
|
|
663
|
-
itemSize = input(40, ...(ngDevMode ? [{ debugName: "itemSize" }] : []));
|
|
664
|
-
/** The current search query (for empty state context). */
|
|
665
|
-
searchQuery = input('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
|
|
666
|
-
/** Custom empty state text. */
|
|
667
|
-
emptyText = input('No options available', ...(ngDevMode ? [{ debugName: "emptyText" }] : []));
|
|
668
|
-
/** Template for rendering each option. */
|
|
669
|
-
optionTemplate = input.required(...(ngDevMode ? [{ debugName: "optionTemplate" }] : []));
|
|
670
|
-
/** Custom template for the empty state. */
|
|
671
|
-
emptyTemplate = input(null, ...(ngDevMode ? [{ debugName: "emptyTemplate" }] : []));
|
|
672
|
-
/** Emitted when the panel is scrolled. */
|
|
673
|
-
scrolled = output();
|
|
674
|
-
/** Whether to show the empty state. */
|
|
675
|
-
showEmpty = computed(() => this.options().length === 0, ...(ngDevMode ? [{ debugName: "showEmpty" }] : []));
|
|
676
|
-
/** Computed CSS classes for the panel. */
|
|
677
|
-
panelClasses = computed(() => {
|
|
678
|
-
const baseClasses = dropdownPanelVariants({ size: this.size() });
|
|
679
|
-
return mergeClasses(baseClasses, this.panelClass());
|
|
680
|
-
}, ...(ngDevMode ? [{ debugName: "panelClasses" }] : []));
|
|
681
|
-
/** Computed CSS classes for the empty state. */
|
|
682
|
-
emptyClasses = computed(() => {
|
|
683
|
-
return dropdownEmptyVariants({ size: this.size() });
|
|
684
|
-
}, ...(ngDevMode ? [{ debugName: "emptyClasses" }] : []));
|
|
685
|
-
/** Template context for the empty state. */
|
|
686
|
-
emptyContext = computed(() => ({
|
|
687
|
-
$implicit: this.searchQuery(),
|
|
688
|
-
}), ...(ngDevMode ? [{ debugName: "emptyContext" }] : []));
|
|
689
|
-
/** Track function for options. */
|
|
690
|
-
trackByFn(_index, option) {
|
|
691
|
-
return option.id;
|
|
692
|
-
}
|
|
693
|
-
/** Scrolls to a specific index. */
|
|
694
|
-
scrollToIndex(index) {
|
|
695
|
-
const vp = this.viewport();
|
|
696
|
-
if (this.virtualScrollEnabled() && vp) {
|
|
697
|
-
vp.scrollToIndex(index);
|
|
698
|
-
}
|
|
699
|
-
else {
|
|
700
|
-
const panelEl = this.panelRef()?.nativeElement;
|
|
701
|
-
const optionEl = panelEl?.querySelector(`[data-index="${index}"]`);
|
|
702
|
-
optionEl?.scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
/** Scrolls an option into view. */
|
|
706
|
-
scrollOptionIntoView(optionElement) {
|
|
707
|
-
optionElement.scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
708
|
-
}
|
|
709
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDropdownPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
710
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComDropdownPanel, isStandalone: true, selector: "com-dropdown-panel", inputs: { panelId: { classPropertyName: "panelId", publicName: "panelId", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, multiselectable: { classPropertyName: "multiselectable", publicName: "multiselectable", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollEnabled: { classPropertyName: "virtualScrollEnabled", publicName: "virtualScrollEnabled", isSignal: true, isRequired: false, transformFunction: null }, itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: false, transformFunction: null }, searchQuery: { classPropertyName: "searchQuery", publicName: "searchQuery", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, optionTemplate: { classPropertyName: "optionTemplate", publicName: "optionTemplate", isSignal: true, isRequired: true, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scrolled: "scrolled" }, host: { classAttribute: "com-dropdown-panel-host block" }, viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panelElement"], descendants: true, isSignal: true }, { propertyName: "viewport", first: true, predicate: ["viewport"], descendants: true, isSignal: true }], exportAs: ["comDropdownPanel"], ngImport: i0, template: `
|
|
711
|
-
<div
|
|
712
|
-
#panelElement
|
|
713
|
-
[class]="panelClasses()"
|
|
714
|
-
[attr.role]="'listbox'"
|
|
715
|
-
[attr.aria-multiselectable]="multiselectable() || null"
|
|
716
|
-
[attr.id]="panelId()"
|
|
717
|
-
>
|
|
718
|
-
<!-- Search slot -->
|
|
719
|
-
<ng-content select="[comDropdownSearch]" />
|
|
720
|
-
|
|
721
|
-
<!-- Options container -->
|
|
722
|
-
@if (virtualScrollEnabled()) {
|
|
723
|
-
<cdk-virtual-scroll-viewport
|
|
724
|
-
[itemSize]="itemSize()"
|
|
725
|
-
[maxBufferPx]="400"
|
|
726
|
-
[minBufferPx]="200"
|
|
727
|
-
[style.height]="maxHeight()"
|
|
728
|
-
class="overflow-auto"
|
|
729
|
-
>
|
|
730
|
-
<div
|
|
731
|
-
*cdkVirtualFor="let option of options(); trackBy: trackByFn; let i = index"
|
|
732
|
-
[attr.data-index]="i"
|
|
733
|
-
>
|
|
734
|
-
<ng-container
|
|
735
|
-
[ngTemplateOutlet]="optionTemplate()"
|
|
736
|
-
[ngTemplateOutletContext]="{ $implicit: option, index: i }"
|
|
737
|
-
/>
|
|
738
|
-
</div>
|
|
739
|
-
</cdk-virtual-scroll-viewport>
|
|
740
|
-
} @else {
|
|
741
|
-
<div
|
|
742
|
-
class="overflow-auto"
|
|
743
|
-
[style.maxHeight]="maxHeight()"
|
|
744
|
-
>
|
|
745
|
-
@for (option of options(); track option.id; let i = $index) {
|
|
746
|
-
<ng-container
|
|
747
|
-
[ngTemplateOutlet]="optionTemplate()"
|
|
748
|
-
[ngTemplateOutletContext]="{ $implicit: option, index: i }"
|
|
749
|
-
/>
|
|
750
|
-
}
|
|
751
|
-
</div>
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
<!-- Empty state -->
|
|
755
|
-
@if (showEmpty()) {
|
|
756
|
-
@if (emptyTemplate()) {
|
|
757
|
-
<ng-container
|
|
758
|
-
[ngTemplateOutlet]="emptyTemplate()!"
|
|
759
|
-
[ngTemplateOutletContext]="emptyContext()"
|
|
760
|
-
/>
|
|
761
|
-
} @else {
|
|
762
|
-
<div [class]="emptyClasses()">
|
|
763
|
-
{{ emptyText() }}
|
|
764
|
-
</div>
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
</div>
|
|
768
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
769
|
-
}
|
|
770
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDropdownPanel, decorators: [{
|
|
771
|
-
type: Component,
|
|
772
|
-
args: [{
|
|
773
|
-
selector: 'com-dropdown-panel',
|
|
774
|
-
exportAs: 'comDropdownPanel',
|
|
775
|
-
template: `
|
|
776
|
-
<div
|
|
777
|
-
#panelElement
|
|
778
|
-
[class]="panelClasses()"
|
|
779
|
-
[attr.role]="'listbox'"
|
|
780
|
-
[attr.aria-multiselectable]="multiselectable() || null"
|
|
781
|
-
[attr.id]="panelId()"
|
|
782
|
-
>
|
|
783
|
-
<!-- Search slot -->
|
|
784
|
-
<ng-content select="[comDropdownSearch]" />
|
|
785
|
-
|
|
786
|
-
<!-- Options container -->
|
|
787
|
-
@if (virtualScrollEnabled()) {
|
|
788
|
-
<cdk-virtual-scroll-viewport
|
|
789
|
-
[itemSize]="itemSize()"
|
|
790
|
-
[maxBufferPx]="400"
|
|
791
|
-
[minBufferPx]="200"
|
|
792
|
-
[style.height]="maxHeight()"
|
|
793
|
-
class="overflow-auto"
|
|
794
|
-
>
|
|
795
|
-
<div
|
|
796
|
-
*cdkVirtualFor="let option of options(); trackBy: trackByFn; let i = index"
|
|
797
|
-
[attr.data-index]="i"
|
|
798
|
-
>
|
|
799
|
-
<ng-container
|
|
800
|
-
[ngTemplateOutlet]="optionTemplate()"
|
|
801
|
-
[ngTemplateOutletContext]="{ $implicit: option, index: i }"
|
|
802
|
-
/>
|
|
803
|
-
</div>
|
|
804
|
-
</cdk-virtual-scroll-viewport>
|
|
805
|
-
} @else {
|
|
806
|
-
<div
|
|
807
|
-
class="overflow-auto"
|
|
808
|
-
[style.maxHeight]="maxHeight()"
|
|
809
|
-
>
|
|
810
|
-
@for (option of options(); track option.id; let i = $index) {
|
|
811
|
-
<ng-container
|
|
812
|
-
[ngTemplateOutlet]="optionTemplate()"
|
|
813
|
-
[ngTemplateOutletContext]="{ $implicit: option, index: i }"
|
|
814
|
-
/>
|
|
815
|
-
}
|
|
816
|
-
</div>
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
<!-- Empty state -->
|
|
820
|
-
@if (showEmpty()) {
|
|
821
|
-
@if (emptyTemplate()) {
|
|
822
|
-
<ng-container
|
|
823
|
-
[ngTemplateOutlet]="emptyTemplate()!"
|
|
824
|
-
[ngTemplateOutletContext]="emptyContext()"
|
|
825
|
-
/>
|
|
826
|
-
} @else {
|
|
827
|
-
<div [class]="emptyClasses()">
|
|
828
|
-
{{ emptyText() }}
|
|
829
|
-
</div>
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
</div>
|
|
833
|
-
`,
|
|
834
|
-
imports: [
|
|
835
|
-
NgTemplateOutlet,
|
|
836
|
-
CdkVirtualScrollViewport,
|
|
837
|
-
CdkFixedSizeVirtualScroll,
|
|
838
|
-
CdkVirtualForOf,
|
|
839
|
-
],
|
|
840
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
841
|
-
host: {
|
|
842
|
-
class: 'com-dropdown-panel-host block',
|
|
843
|
-
},
|
|
844
|
-
}]
|
|
845
|
-
}], propDecorators: { panelRef: [{ type: i0.ViewChild, args: ['panelElement', { isSignal: true }] }], viewport: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }], panelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelId", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], multiselectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiselectable", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], virtualScrollEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollEnabled", required: false }] }], itemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSize", required: false }] }], searchQuery: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchQuery", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], optionTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionTemplate", required: true }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], scrolled: [{ type: i0.Output, args: ["scrolled"] }] } });
|
|
846
|
-
|
|
847
633
|
/**
|
|
848
634
|
* Search input component for filtering dropdown options.
|
|
849
635
|
* Includes debouncing for better performance.
|
|
@@ -1305,6 +1091,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1305
1091
|
/**
|
|
1306
1092
|
* Directive to mark a template as the custom option template.
|
|
1307
1093
|
*
|
|
1094
|
+
* @tokens none
|
|
1095
|
+
*
|
|
1308
1096
|
* @example
|
|
1309
1097
|
* ```html
|
|
1310
1098
|
* <com-dropdown [options]="users()">
|
|
@@ -1342,6 +1130,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1342
1130
|
/**
|
|
1343
1131
|
* Directive to mark a template as the custom selected value template.
|
|
1344
1132
|
*
|
|
1133
|
+
* @tokens none
|
|
1134
|
+
*
|
|
1345
1135
|
* @example
|
|
1346
1136
|
* ```html
|
|
1347
1137
|
* <com-dropdown [options]="users()">
|
|
@@ -1381,6 +1171,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1381
1171
|
/**
|
|
1382
1172
|
* Directive to mark a template as the custom empty state template.
|
|
1383
1173
|
*
|
|
1174
|
+
* @tokens none
|
|
1175
|
+
*
|
|
1384
1176
|
* @example
|
|
1385
1177
|
* ```html
|
|
1386
1178
|
* <com-dropdown [options]="users()" [searchable]="true">
|
|
@@ -1416,6 +1208,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1416
1208
|
/**
|
|
1417
1209
|
* Directive to mark a template as the custom group header template.
|
|
1418
1210
|
*
|
|
1211
|
+
* @tokens none
|
|
1212
|
+
*
|
|
1419
1213
|
* @example
|
|
1420
1214
|
* ```html
|
|
1421
1215
|
* <com-dropdown [options]="users()" [groupBy]="groupByDepartment">
|
|
@@ -1451,6 +1245,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
1451
1245
|
/**
|
|
1452
1246
|
* Directive to mark a template as the custom tag template (multi-select mode).
|
|
1453
1247
|
*
|
|
1248
|
+
* @tokens none
|
|
1249
|
+
*
|
|
1454
1250
|
* @example
|
|
1455
1251
|
* ```html
|
|
1456
1252
|
* <com-dropdown [options]="users()" [multiple]="true">
|
|
@@ -1584,16 +1380,18 @@ class ComDropdown {
|
|
|
1584
1380
|
triggerRef = viewChild.required('triggerElement');
|
|
1585
1381
|
/** Reference to the panel template. */
|
|
1586
1382
|
panelTemplateRef = viewChild.required('panelTemplate');
|
|
1383
|
+
/** Reference to the virtual scroll viewport (when enabled). */
|
|
1384
|
+
virtualViewport = viewChild(CdkVirtualScrollViewport, ...(ngDevMode ? [{ debugName: "virtualViewport" }] : []));
|
|
1587
1385
|
/** Content query for custom option template. */
|
|
1588
|
-
optionTemplate = contentChild(
|
|
1386
|
+
optionTemplate = contentChild(ComDropdownOptionTpl, ...(ngDevMode ? [{ debugName: "optionTemplate" }] : []));
|
|
1589
1387
|
/** Content query for custom selected template. */
|
|
1590
|
-
selectedTemplate = contentChild(
|
|
1388
|
+
selectedTemplate = contentChild(ComDropdownSelectedTpl, ...(ngDevMode ? [{ debugName: "selectedTemplate" }] : []));
|
|
1591
1389
|
/** Content query for custom empty template. */
|
|
1592
1390
|
emptyTemplate = contentChild(ComDropdownEmptyTpl, ...(ngDevMode ? [{ debugName: "emptyTemplate" }] : []));
|
|
1593
1391
|
/** Content query for custom group template. */
|
|
1594
1392
|
groupTemplate = contentChild(ComDropdownGroupTpl, ...(ngDevMode ? [{ debugName: "groupTemplate" }] : []));
|
|
1595
1393
|
/** Content query for custom tag template. */
|
|
1596
|
-
tagTemplate = contentChild(
|
|
1394
|
+
tagTemplate = contentChild(ComDropdownTagTpl, ...(ngDevMode ? [{ debugName: "tagTemplate" }] : []));
|
|
1597
1395
|
/** Overlay reference. */
|
|
1598
1396
|
overlayRef = null;
|
|
1599
1397
|
/** Unique ID for the dropdown. */
|
|
@@ -1612,7 +1410,7 @@ class ComDropdown {
|
|
|
1612
1410
|
/** Search input placeholder. */
|
|
1613
1411
|
searchPlaceholder = input('Search...', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
|
|
1614
1412
|
/** Disable the dropdown. */
|
|
1615
|
-
disabled =
|
|
1413
|
+
disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
1616
1414
|
/** Mark as required. */
|
|
1617
1415
|
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
|
|
1618
1416
|
/** Show clear button. */
|
|
@@ -1643,6 +1441,8 @@ class ComDropdown {
|
|
|
1643
1441
|
searchDebounceMs = input(300, ...(ngDevMode ? [{ debugName: "searchDebounceMs" }] : []));
|
|
1644
1442
|
/** Virtual scroll threshold. */
|
|
1645
1443
|
virtualScrollThreshold = input(VIRTUAL_SCROLL_THRESHOLD, ...(ngDevMode ? [{ debugName: "virtualScrollThreshold" }] : []));
|
|
1444
|
+
/** Item size in pixels for virtual scrolling. */
|
|
1445
|
+
virtualScrollItemSize = input(40, ...(ngDevMode ? [{ debugName: "virtualScrollItemSize" }] : []));
|
|
1646
1446
|
/** Maximum number of tags to display in multi-select mode. Set to null for no limit. */
|
|
1647
1447
|
maxVisibleTags = input(2, ...(ngDevMode ? [{ debugName: "maxVisibleTags" }] : []));
|
|
1648
1448
|
/** Custom error state matcher for determining when to show errors. */
|
|
@@ -1838,7 +1638,7 @@ class ComDropdown {
|
|
|
1838
1638
|
}, ...(ngDevMode ? [{ debugName: "triggerClasses" }] : []));
|
|
1839
1639
|
/** Computed panel classes. */
|
|
1840
1640
|
panelClasses = computed(() => {
|
|
1841
|
-
return mergeClasses('w-full z-50 overflow-hidden rounded-overlay border border-border-subtle bg-popover text-popover-foreground shadow-
|
|
1641
|
+
return mergeClasses('w-full z-50 overflow-hidden rounded-overlay border border-border-subtle bg-popover text-popover-foreground shadow-overlay outline-none', this.panelClass());
|
|
1842
1642
|
}, ...(ngDevMode ? [{ debugName: "panelClasses" }] : []));
|
|
1843
1643
|
/** Computed chevron classes. */
|
|
1844
1644
|
chevronClasses = computed(() => {
|
|
@@ -1874,8 +1674,7 @@ class ComDropdown {
|
|
|
1874
1674
|
this.onTouched = fn;
|
|
1875
1675
|
}
|
|
1876
1676
|
setDisabledState(isDisabled) {
|
|
1877
|
-
|
|
1878
|
-
// When using forms, the form control's disabled state takes precedence
|
|
1677
|
+
this.disabled.set(isDisabled);
|
|
1879
1678
|
}
|
|
1880
1679
|
// ============ FormFieldControl IMPLEMENTATION ============
|
|
1881
1680
|
/**
|
|
@@ -2042,6 +1841,9 @@ class ComDropdown {
|
|
|
2042
1841
|
break;
|
|
2043
1842
|
case 'Enter':
|
|
2044
1843
|
case ' ':
|
|
1844
|
+
if (event.key === ' ' && this.searchable() && event.target instanceof HTMLInputElement) {
|
|
1845
|
+
return;
|
|
1846
|
+
}
|
|
2045
1847
|
event.preventDefault();
|
|
2046
1848
|
this.selectActiveOption();
|
|
2047
1849
|
break;
|
|
@@ -2109,6 +1911,10 @@ class ComDropdown {
|
|
|
2109
1911
|
trackByValue(item, _index) {
|
|
2110
1912
|
return item;
|
|
2111
1913
|
}
|
|
1914
|
+
/** Track function for virtual scroll options. */
|
|
1915
|
+
trackByOption(_index, option) {
|
|
1916
|
+
return option.id;
|
|
1917
|
+
}
|
|
2112
1918
|
getGlobalIndex(groupKey, localIndex) {
|
|
2113
1919
|
const groups = this.groupedOptions();
|
|
2114
1920
|
let globalIndex = 0;
|
|
@@ -2132,7 +1938,7 @@ class ComDropdown {
|
|
|
2132
1938
|
.withPositions(DEFAULT_POSITIONS)
|
|
2133
1939
|
.withFlexibleDimensions(false)
|
|
2134
1940
|
.withPush(true);
|
|
2135
|
-
const hostWidth = hostEl.getBoundingClientRect()
|
|
1941
|
+
const hostWidth = hostEl.getBoundingClientRect?.()?.width ?? 0;
|
|
2136
1942
|
this.overlayRef = this.overlay.create({
|
|
2137
1943
|
positionStrategy,
|
|
2138
1944
|
scrollStrategy: this.overlay.scrollStrategies.reposition(),
|
|
@@ -2233,20 +2039,37 @@ class ComDropdown {
|
|
|
2233
2039
|
const targetOption = options[nextIndex];
|
|
2234
2040
|
if (targetOption) {
|
|
2235
2041
|
this.activeOptionId.set(targetOption.id);
|
|
2042
|
+
this.scrollActiveOptionIntoView(nextIndex, targetOption.id);
|
|
2236
2043
|
}
|
|
2237
2044
|
}
|
|
2238
2045
|
navigateToFirst() {
|
|
2239
2046
|
const options = this.groupBy() ? this.flattenGroupedOptions() : this.filteredOptions();
|
|
2240
2047
|
const firstEnabled = options.find((opt) => !opt.disabled);
|
|
2241
2048
|
if (firstEnabled) {
|
|
2049
|
+
const index = options.indexOf(firstEnabled);
|
|
2242
2050
|
this.activeOptionId.set(firstEnabled.id);
|
|
2051
|
+
this.scrollActiveOptionIntoView(index, firstEnabled.id);
|
|
2243
2052
|
}
|
|
2244
2053
|
}
|
|
2245
2054
|
navigateToLast() {
|
|
2246
2055
|
const options = this.groupBy() ? this.flattenGroupedOptions() : this.filteredOptions();
|
|
2247
2056
|
const lastEnabled = [...options].reverse().find((opt) => !opt.disabled);
|
|
2248
2057
|
if (lastEnabled) {
|
|
2058
|
+
const index = options.indexOf(lastEnabled);
|
|
2249
2059
|
this.activeOptionId.set(lastEnabled.id);
|
|
2060
|
+
this.scrollActiveOptionIntoView(index, lastEnabled.id);
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
/** Scrolls the active option into view, using virtual viewport or native scroll. */
|
|
2064
|
+
scrollActiveOptionIntoView(index, optionId) {
|
|
2065
|
+
const viewport = this.virtualViewport();
|
|
2066
|
+
if (viewport) {
|
|
2067
|
+
viewport.scrollToIndex(index);
|
|
2068
|
+
}
|
|
2069
|
+
else {
|
|
2070
|
+
const panelEl = this.overlayRef?.overlayElement;
|
|
2071
|
+
const optionEl = panelEl?.querySelector(`[id="${optionId}"]`);
|
|
2072
|
+
optionEl?.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });
|
|
2250
2073
|
}
|
|
2251
2074
|
}
|
|
2252
2075
|
selectActiveOption() {
|
|
@@ -2280,7 +2103,7 @@ class ComDropdown {
|
|
|
2280
2103
|
this.liveAnnouncer.announce(message, 'polite');
|
|
2281
2104
|
}
|
|
2282
2105
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDropdown, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2283
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComDropdown, isStandalone: true, selector: "com-dropdown", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", 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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, displayWith: { classPropertyName: "displayWith", publicName: "displayWith", isSignal: true, isRequired: false, transformFunction: null }, filterWith: { classPropertyName: "filterWith", publicName: "filterWith", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null }, searchDebounceMs: { classPropertyName: "searchDebounceMs", publicName: "searchDebounceMs", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollThreshold: { classPropertyName: "virtualScrollThreshold", publicName: "virtualScrollThreshold", isSignal: true, isRequired: false, transformFunction: null }, maxVisibleTags: { classPropertyName: "maxVisibleTags", publicName: "maxVisibleTags", isSignal: true, isRequired: false, transformFunction: null }, errorStateMatcher: { classPropertyName: "errorStateMatcher", publicName: "errorStateMatcher", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, sfErrors: { classPropertyName: "sfErrors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", searchChange: "searchChange", opened: "opened", closed: "closed" }, host: { properties: { "class.com-dropdown-disabled": "disabled()", "class.com-dropdown-open": "isOpen()" }, classAttribute: "com-dropdown-host inline-block" }, providers: [{ provide: FormFieldControl, useExisting: forwardRef(() => ComDropdown) }], queries: [{ propertyName: "optionTemplate", first: true, predicate:
|
|
2106
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComDropdown, isStandalone: true, selector: "com-dropdown", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", 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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null }, displayWith: { classPropertyName: "displayWith", publicName: "displayWith", isSignal: true, isRequired: false, transformFunction: null }, filterWith: { classPropertyName: "filterWith", publicName: "filterWith", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, panelWidth: { classPropertyName: "panelWidth", publicName: "panelWidth", isSignal: true, isRequired: false, transformFunction: null }, searchDebounceMs: { classPropertyName: "searchDebounceMs", publicName: "searchDebounceMs", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollThreshold: { classPropertyName: "virtualScrollThreshold", publicName: "virtualScrollThreshold", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollItemSize: { classPropertyName: "virtualScrollItemSize", publicName: "virtualScrollItemSize", isSignal: true, isRequired: false, transformFunction: null }, maxVisibleTags: { classPropertyName: "maxVisibleTags", publicName: "maxVisibleTags", isSignal: true, isRequired: false, transformFunction: null }, errorStateMatcher: { classPropertyName: "errorStateMatcher", publicName: "errorStateMatcher", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, sfErrors: { classPropertyName: "sfErrors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", disabled: "disabledChange", touched: "touchedChange", searchChange: "searchChange", opened: "opened", closed: "closed" }, host: { properties: { "class.com-dropdown-disabled": "disabled()", "class.com-dropdown-open": "isOpen()" }, classAttribute: "com-dropdown-host inline-block" }, providers: [{ provide: FormFieldControl, useExisting: forwardRef(() => ComDropdown) }], queries: [{ propertyName: "optionTemplate", first: true, predicate: ComDropdownOptionTpl, descendants: true, isSignal: true }, { propertyName: "selectedTemplate", first: true, predicate: ComDropdownSelectedTpl, descendants: true, isSignal: true }, { propertyName: "emptyTemplate", first: true, predicate: ComDropdownEmptyTpl, descendants: true, isSignal: true }, { propertyName: "groupTemplate", first: true, predicate: ComDropdownGroupTpl, descendants: true, isSignal: true }, { propertyName: "tagTemplate", first: true, predicate: ComDropdownTagTpl, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerElement"], descendants: true, isSignal: true }, { propertyName: "panelTemplateRef", first: true, predicate: ["panelTemplate"], descendants: true, isSignal: true }, { propertyName: "virtualViewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], exportAs: ["comDropdown"], ngImport: i0, template: `
|
|
2284
2107
|
<!-- Trigger button -->
|
|
2285
2108
|
<button
|
|
2286
2109
|
#triggerElement
|
|
@@ -2295,6 +2118,7 @@ class ComDropdown {
|
|
|
2295
2118
|
[attr.aria-required]="required() || null"
|
|
2296
2119
|
[attr.aria-invalid]="effectiveState() === 'error' || null"
|
|
2297
2120
|
[attr.aria-describedby]="ariaDescribedBy()"
|
|
2121
|
+
[attr.aria-label]="hasValue() ? null : placeholder()"
|
|
2298
2122
|
[attr.aria-disabled]="disabled() || null"
|
|
2299
2123
|
[attr.tabindex]="disabled() ? -1 : 0"
|
|
2300
2124
|
[disabled]="disabled()"
|
|
@@ -2386,6 +2210,7 @@ class ComDropdown {
|
|
|
2386
2210
|
[class]="panelClasses()"
|
|
2387
2211
|
[attr.id]="panelId()"
|
|
2388
2212
|
[attr.role]="'listbox'"
|
|
2213
|
+
tabindex="-1"
|
|
2389
2214
|
[attr.aria-multiselectable]="multiple() || null"
|
|
2390
2215
|
[attr.aria-label]="placeholder()"
|
|
2391
2216
|
(keydown)="onPanelKeydown($event)"
|
|
@@ -2402,28 +2227,71 @@ class ComDropdown {
|
|
|
2402
2227
|
}
|
|
2403
2228
|
|
|
2404
2229
|
<!-- Options list -->
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2230
|
+
@if (virtualScrollEnabled() && groupedOptions().length === 0 && filteredOptions().length > 0) {
|
|
2231
|
+
<!-- Virtual scrolling for large ungrouped lists -->
|
|
2232
|
+
<cdk-virtual-scroll-viewport
|
|
2233
|
+
[itemSize]="virtualScrollItemSize()"
|
|
2234
|
+
[maxBufferPx]="400"
|
|
2235
|
+
[minBufferPx]="200"
|
|
2236
|
+
[style.height]="maxHeight()"
|
|
2237
|
+
class="overflow-auto"
|
|
2238
|
+
>
|
|
2239
|
+
<com-dropdown-option
|
|
2240
|
+
*cdkVirtualFor="let option of filteredOptions(); trackBy: trackByOption; let i = index"
|
|
2241
|
+
[value]="option.value"
|
|
2242
|
+
[displayText]="option.displayText"
|
|
2243
|
+
[id]="option.id"
|
|
2244
|
+
[index]="i"
|
|
2245
|
+
[selected]="isSelected(option.value)"
|
|
2246
|
+
[active]="isActive(option.id)"
|
|
2247
|
+
[disabled]="option.disabled"
|
|
2248
|
+
[size]="size()"
|
|
2249
|
+
[optionTemplate]="optionTemplate()?.templateRef ?? null"
|
|
2250
|
+
(select)="selectOption($event)"
|
|
2251
|
+
(hover)="onOptionHover(option.id)"
|
|
2252
|
+
/>
|
|
2253
|
+
</cdk-virtual-scroll-viewport>
|
|
2254
|
+
} @else {
|
|
2255
|
+
<!-- Standard rendering for small lists and grouped options -->
|
|
2256
|
+
<div
|
|
2257
|
+
class="overflow-auto"
|
|
2258
|
+
[style.maxHeight]="maxHeight()"
|
|
2259
|
+
>
|
|
2260
|
+
@if (groupedOptions().length > 0) {
|
|
2261
|
+
@for (group of groupedOptions(); track group.key) {
|
|
2262
|
+
<!-- Group header -->
|
|
2263
|
+
<com-dropdown-group
|
|
2264
|
+
[label]="group.key"
|
|
2265
|
+
[count]="group.options.length"
|
|
2266
|
+
[expanded]="group.expanded"
|
|
2267
|
+
[size]="size()"
|
|
2268
|
+
[groupTemplate]="groupTemplate()?.templateRef ?? null"
|
|
2269
|
+
/>
|
|
2419
2270
|
|
|
2420
|
-
|
|
2421
|
-
|
|
2271
|
+
<!-- Group options -->
|
|
2272
|
+
@for (option of group.options; track option.id; let i = $index) {
|
|
2273
|
+
<com-dropdown-option
|
|
2274
|
+
[value]="option.value"
|
|
2275
|
+
[displayText]="option.displayText"
|
|
2276
|
+
[id]="option.id"
|
|
2277
|
+
[index]="getGlobalIndex(group.key, i)"
|
|
2278
|
+
[selected]="isSelected(option.value)"
|
|
2279
|
+
[active]="isActive(option.id)"
|
|
2280
|
+
[disabled]="option.disabled"
|
|
2281
|
+
[size]="size()"
|
|
2282
|
+
[optionTemplate]="optionTemplate()?.templateRef ?? null"
|
|
2283
|
+
(select)="selectOption($event)"
|
|
2284
|
+
(hover)="onOptionHover(option.id)"
|
|
2285
|
+
/>
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
} @else if (filteredOptions().length > 0) {
|
|
2289
|
+
@for (option of filteredOptions(); track option.id; let i = $index) {
|
|
2422
2290
|
<com-dropdown-option
|
|
2423
2291
|
[value]="option.value"
|
|
2424
2292
|
[displayText]="option.displayText"
|
|
2425
2293
|
[id]="option.id"
|
|
2426
|
-
[index]="
|
|
2294
|
+
[index]="i"
|
|
2427
2295
|
[selected]="isSelected(option.value)"
|
|
2428
2296
|
[active]="isActive(option.id)"
|
|
2429
2297
|
[disabled]="option.disabled"
|
|
@@ -2433,41 +2301,25 @@ class ComDropdown {
|
|
|
2433
2301
|
(hover)="onOptionHover(option.id)"
|
|
2434
2302
|
/>
|
|
2435
2303
|
}
|
|
2436
|
-
}
|
|
2437
|
-
} @else if (filteredOptions().length > 0) {
|
|
2438
|
-
@for (option of filteredOptions(); track option.id; let i = $index) {
|
|
2439
|
-
<com-dropdown-option
|
|
2440
|
-
[value]="option.value"
|
|
2441
|
-
[displayText]="option.displayText"
|
|
2442
|
-
[id]="option.id"
|
|
2443
|
-
[index]="i"
|
|
2444
|
-
[selected]="isSelected(option.value)"
|
|
2445
|
-
[active]="isActive(option.id)"
|
|
2446
|
-
[disabled]="option.disabled"
|
|
2447
|
-
[size]="size()"
|
|
2448
|
-
[optionTemplate]="optionTemplate()?.templateRef ?? null"
|
|
2449
|
-
(select)="selectOption($event)"
|
|
2450
|
-
(hover)="onOptionHover(option.id)"
|
|
2451
|
-
/>
|
|
2452
|
-
}
|
|
2453
|
-
} @else {
|
|
2454
|
-
<!-- Empty state -->
|
|
2455
|
-
@if (emptyTemplate()) {
|
|
2456
|
-
<ng-container
|
|
2457
|
-
[ngTemplateOutlet]="emptyTemplate()!.templateRef"
|
|
2458
|
-
[ngTemplateOutletContext]="emptyContext()"
|
|
2459
|
-
/>
|
|
2460
2304
|
} @else {
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2305
|
+
<!-- Empty state -->
|
|
2306
|
+
@if (emptyTemplate()) {
|
|
2307
|
+
<ng-container
|
|
2308
|
+
[ngTemplateOutlet]="emptyTemplate()!.templateRef"
|
|
2309
|
+
[ngTemplateOutletContext]="emptyContext()"
|
|
2310
|
+
/>
|
|
2311
|
+
} @else {
|
|
2312
|
+
<div class="flex items-center justify-center px-3 py-6 text-muted-foreground">
|
|
2313
|
+
@if (searchQuery()) {
|
|
2314
|
+
No results for "{{ searchQuery() }}"
|
|
2315
|
+
} @else {
|
|
2316
|
+
No options available
|
|
2317
|
+
}
|
|
2318
|
+
</div>
|
|
2319
|
+
}
|
|
2468
2320
|
}
|
|
2469
|
-
|
|
2470
|
-
|
|
2321
|
+
</div>
|
|
2322
|
+
}
|
|
2471
2323
|
</div>
|
|
2472
2324
|
</ng-template>
|
|
2473
2325
|
|
|
@@ -2475,7 +2327,7 @@ class ComDropdown {
|
|
|
2475
2327
|
<div class="sr-only" aria-live="polite" aria-atomic="true">
|
|
2476
2328
|
{{ liveAnnouncement() }}
|
|
2477
2329
|
</div>
|
|
2478
|
-
`, isInline: true, styles: [".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: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "component", type: ComDropdownOption, selector: "com-dropdown-option", inputs: ["value", "displayText", "id", "index", "selected", "active", "disabled", "size", "optionTemplate", "class"], outputs: ["select", "hover"], exportAs: ["comDropdownOption"] }, { kind: "component", type: ComDropdownSearch, selector: "com-dropdown-search", inputs: ["placeholder", "ariaLabel", "disabled", "debounceMs", "size", "class"], outputs: ["searchChange", "keyNav"], exportAs: ["comDropdownSearch"] }, { kind: "component", type: ComDropdownTag, selector: "com-dropdown-tag", inputs: ["value", "displayText", "index", "disabled", "size", "variant", "class", "tagTemplate"], outputs: ["remove"], exportAs: ["comDropdownTag"] }, { kind: "component", type: ComDropdownGroup, selector: "com-dropdown-group", inputs: ["label", "count", "expanded", "showCount", "size", "class", "groupTemplate"], exportAs: ["comDropdownGroup"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2330
|
+
`, isInline: true, styles: [".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: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: OverlayModule }, { 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: "component", type: ComDropdownOption, selector: "com-dropdown-option", inputs: ["value", "displayText", "id", "index", "selected", "active", "disabled", "size", "optionTemplate", "class"], outputs: ["select", "hover"], exportAs: ["comDropdownOption"] }, { kind: "component", type: ComDropdownSearch, selector: "com-dropdown-search", inputs: ["placeholder", "ariaLabel", "disabled", "debounceMs", "size", "class"], outputs: ["searchChange", "keyNav"], exportAs: ["comDropdownSearch"] }, { kind: "component", type: ComDropdownTag, selector: "com-dropdown-tag", inputs: ["value", "displayText", "index", "disabled", "size", "variant", "class", "tagTemplate"], outputs: ["remove"], exportAs: ["comDropdownTag"] }, { kind: "component", type: ComDropdownGroup, selector: "com-dropdown-group", inputs: ["label", "count", "expanded", "showCount", "size", "class", "groupTemplate"], exportAs: ["comDropdownGroup"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2479
2331
|
}
|
|
2480
2332
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDropdown, decorators: [{
|
|
2481
2333
|
type: Component,
|
|
@@ -2494,6 +2346,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2494
2346
|
[attr.aria-required]="required() || null"
|
|
2495
2347
|
[attr.aria-invalid]="effectiveState() === 'error' || null"
|
|
2496
2348
|
[attr.aria-describedby]="ariaDescribedBy()"
|
|
2349
|
+
[attr.aria-label]="hasValue() ? null : placeholder()"
|
|
2497
2350
|
[attr.aria-disabled]="disabled() || null"
|
|
2498
2351
|
[attr.tabindex]="disabled() ? -1 : 0"
|
|
2499
2352
|
[disabled]="disabled()"
|
|
@@ -2585,6 +2438,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2585
2438
|
[class]="panelClasses()"
|
|
2586
2439
|
[attr.id]="panelId()"
|
|
2587
2440
|
[attr.role]="'listbox'"
|
|
2441
|
+
tabindex="-1"
|
|
2588
2442
|
[attr.aria-multiselectable]="multiple() || null"
|
|
2589
2443
|
[attr.aria-label]="placeholder()"
|
|
2590
2444
|
(keydown)="onPanelKeydown($event)"
|
|
@@ -2601,28 +2455,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2601
2455
|
}
|
|
2602
2456
|
|
|
2603
2457
|
<!-- Options list -->
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2458
|
+
@if (virtualScrollEnabled() && groupedOptions().length === 0 && filteredOptions().length > 0) {
|
|
2459
|
+
<!-- Virtual scrolling for large ungrouped lists -->
|
|
2460
|
+
<cdk-virtual-scroll-viewport
|
|
2461
|
+
[itemSize]="virtualScrollItemSize()"
|
|
2462
|
+
[maxBufferPx]="400"
|
|
2463
|
+
[minBufferPx]="200"
|
|
2464
|
+
[style.height]="maxHeight()"
|
|
2465
|
+
class="overflow-auto"
|
|
2466
|
+
>
|
|
2467
|
+
<com-dropdown-option
|
|
2468
|
+
*cdkVirtualFor="let option of filteredOptions(); trackBy: trackByOption; let i = index"
|
|
2469
|
+
[value]="option.value"
|
|
2470
|
+
[displayText]="option.displayText"
|
|
2471
|
+
[id]="option.id"
|
|
2472
|
+
[index]="i"
|
|
2473
|
+
[selected]="isSelected(option.value)"
|
|
2474
|
+
[active]="isActive(option.id)"
|
|
2475
|
+
[disabled]="option.disabled"
|
|
2476
|
+
[size]="size()"
|
|
2477
|
+
[optionTemplate]="optionTemplate()?.templateRef ?? null"
|
|
2478
|
+
(select)="selectOption($event)"
|
|
2479
|
+
(hover)="onOptionHover(option.id)"
|
|
2480
|
+
/>
|
|
2481
|
+
</cdk-virtual-scroll-viewport>
|
|
2482
|
+
} @else {
|
|
2483
|
+
<!-- Standard rendering for small lists and grouped options -->
|
|
2484
|
+
<div
|
|
2485
|
+
class="overflow-auto"
|
|
2486
|
+
[style.maxHeight]="maxHeight()"
|
|
2487
|
+
>
|
|
2488
|
+
@if (groupedOptions().length > 0) {
|
|
2489
|
+
@for (group of groupedOptions(); track group.key) {
|
|
2490
|
+
<!-- Group header -->
|
|
2491
|
+
<com-dropdown-group
|
|
2492
|
+
[label]="group.key"
|
|
2493
|
+
[count]="group.options.length"
|
|
2494
|
+
[expanded]="group.expanded"
|
|
2495
|
+
[size]="size()"
|
|
2496
|
+
[groupTemplate]="groupTemplate()?.templateRef ?? null"
|
|
2497
|
+
/>
|
|
2618
2498
|
|
|
2619
|
-
|
|
2620
|
-
|
|
2499
|
+
<!-- Group options -->
|
|
2500
|
+
@for (option of group.options; track option.id; let i = $index) {
|
|
2501
|
+
<com-dropdown-option
|
|
2502
|
+
[value]="option.value"
|
|
2503
|
+
[displayText]="option.displayText"
|
|
2504
|
+
[id]="option.id"
|
|
2505
|
+
[index]="getGlobalIndex(group.key, i)"
|
|
2506
|
+
[selected]="isSelected(option.value)"
|
|
2507
|
+
[active]="isActive(option.id)"
|
|
2508
|
+
[disabled]="option.disabled"
|
|
2509
|
+
[size]="size()"
|
|
2510
|
+
[optionTemplate]="optionTemplate()?.templateRef ?? null"
|
|
2511
|
+
(select)="selectOption($event)"
|
|
2512
|
+
(hover)="onOptionHover(option.id)"
|
|
2513
|
+
/>
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2516
|
+
} @else if (filteredOptions().length > 0) {
|
|
2517
|
+
@for (option of filteredOptions(); track option.id; let i = $index) {
|
|
2621
2518
|
<com-dropdown-option
|
|
2622
2519
|
[value]="option.value"
|
|
2623
2520
|
[displayText]="option.displayText"
|
|
2624
2521
|
[id]="option.id"
|
|
2625
|
-
[index]="
|
|
2522
|
+
[index]="i"
|
|
2626
2523
|
[selected]="isSelected(option.value)"
|
|
2627
2524
|
[active]="isActive(option.id)"
|
|
2628
2525
|
[disabled]="option.disabled"
|
|
@@ -2632,41 +2529,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2632
2529
|
(hover)="onOptionHover(option.id)"
|
|
2633
2530
|
/>
|
|
2634
2531
|
}
|
|
2635
|
-
}
|
|
2636
|
-
} @else if (filteredOptions().length > 0) {
|
|
2637
|
-
@for (option of filteredOptions(); track option.id; let i = $index) {
|
|
2638
|
-
<com-dropdown-option
|
|
2639
|
-
[value]="option.value"
|
|
2640
|
-
[displayText]="option.displayText"
|
|
2641
|
-
[id]="option.id"
|
|
2642
|
-
[index]="i"
|
|
2643
|
-
[selected]="isSelected(option.value)"
|
|
2644
|
-
[active]="isActive(option.id)"
|
|
2645
|
-
[disabled]="option.disabled"
|
|
2646
|
-
[size]="size()"
|
|
2647
|
-
[optionTemplate]="optionTemplate()?.templateRef ?? null"
|
|
2648
|
-
(select)="selectOption($event)"
|
|
2649
|
-
(hover)="onOptionHover(option.id)"
|
|
2650
|
-
/>
|
|
2651
|
-
}
|
|
2652
|
-
} @else {
|
|
2653
|
-
<!-- Empty state -->
|
|
2654
|
-
@if (emptyTemplate()) {
|
|
2655
|
-
<ng-container
|
|
2656
|
-
[ngTemplateOutlet]="emptyTemplate()!.templateRef"
|
|
2657
|
-
[ngTemplateOutletContext]="emptyContext()"
|
|
2658
|
-
/>
|
|
2659
2532
|
} @else {
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2533
|
+
<!-- Empty state -->
|
|
2534
|
+
@if (emptyTemplate()) {
|
|
2535
|
+
<ng-container
|
|
2536
|
+
[ngTemplateOutlet]="emptyTemplate()!.templateRef"
|
|
2537
|
+
[ngTemplateOutletContext]="emptyContext()"
|
|
2538
|
+
/>
|
|
2539
|
+
} @else {
|
|
2540
|
+
<div class="flex items-center justify-center px-3 py-6 text-muted-foreground">
|
|
2541
|
+
@if (searchQuery()) {
|
|
2542
|
+
No results for "{{ searchQuery() }}"
|
|
2543
|
+
} @else {
|
|
2544
|
+
No options available
|
|
2545
|
+
}
|
|
2546
|
+
</div>
|
|
2547
|
+
}
|
|
2667
2548
|
}
|
|
2668
|
-
|
|
2669
|
-
|
|
2549
|
+
</div>
|
|
2550
|
+
}
|
|
2670
2551
|
</div>
|
|
2671
2552
|
</ng-template>
|
|
2672
2553
|
|
|
@@ -2677,6 +2558,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2677
2558
|
`, imports: [
|
|
2678
2559
|
NgTemplateOutlet,
|
|
2679
2560
|
OverlayModule,
|
|
2561
|
+
CdkVirtualScrollViewport,
|
|
2562
|
+
CdkFixedSizeVirtualScroll,
|
|
2563
|
+
CdkVirtualForOf,
|
|
2680
2564
|
ComDropdownOption,
|
|
2681
2565
|
ComDropdownSearch,
|
|
2682
2566
|
ComDropdownTag,
|
|
@@ -2686,7 +2570,229 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
|
|
|
2686
2570
|
'[class.com-dropdown-disabled]': 'disabled()',
|
|
2687
2571
|
'[class.com-dropdown-open]': 'isOpen()',
|
|
2688
2572
|
}, styles: [".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"] }]
|
|
2689
|
-
}], ctorParameters: () => [], propDecorators: { triggerRef: [{ type: i0.ViewChild, args: ['triggerElement', { isSignal: true }] }], panelTemplateRef: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], optionTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComDropdownOptionTpl), { isSignal: true }] }], selectedTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComDropdownSelectedTpl), { isSignal: true }] }], emptyTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComDropdownEmptyTpl), { isSignal: true }] }], groupTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComDropdownGroupTpl), { isSignal: true }] }], tagTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComDropdownTagTpl), { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "compareWith", required: false }] }], displayWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayWith", required: false }] }], filterWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterWith", required: false }] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], panelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelWidth", required: false }] }], searchDebounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchDebounceMs", required: false }] }], virtualScrollThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollThreshold", required: false }] }], maxVisibleTags: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisibleTags", required: false }] }], errorStateMatcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStateMatcher", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], sfErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
|
|
2573
|
+
}], ctorParameters: () => [], propDecorators: { triggerRef: [{ type: i0.ViewChild, args: ['triggerElement', { isSignal: true }] }], panelTemplateRef: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], virtualViewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], optionTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComDropdownOptionTpl), { isSignal: true }] }], selectedTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComDropdownSelectedTpl), { isSignal: true }] }], emptyTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComDropdownEmptyTpl), { isSignal: true }] }], groupTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComDropdownGroupTpl), { isSignal: true }] }], tagTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ComDropdownTagTpl), { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "compareWith", required: false }] }], displayWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayWith", required: false }] }], filterWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterWith", required: false }] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], panelWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelWidth", required: false }] }], searchDebounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchDebounceMs", required: false }] }], virtualScrollThreshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollThreshold", required: false }] }], virtualScrollItemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollItemSize", required: false }] }], maxVisibleTags: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisibleTags", required: false }] }], errorStateMatcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStateMatcher", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], sfErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
|
|
2574
|
+
|
|
2575
|
+
/**
|
|
2576
|
+
* The overlay panel containing the dropdown options.
|
|
2577
|
+
* Supports virtual scrolling for large lists.
|
|
2578
|
+
*
|
|
2579
|
+
* @example
|
|
2580
|
+
* ```html
|
|
2581
|
+
* <com-dropdown-panel
|
|
2582
|
+
* [options]="filteredOptions()"
|
|
2583
|
+
* [maxHeight]="'300px'"
|
|
2584
|
+
* [virtualScrollEnabled]="true"
|
|
2585
|
+
* >
|
|
2586
|
+
* <ng-content />
|
|
2587
|
+
* </com-dropdown-panel>
|
|
2588
|
+
* ```
|
|
2589
|
+
*
|
|
2590
|
+
* @tokens `--color-popover`, `--color-popover-foreground`, `--color-border-subtle`,
|
|
2591
|
+
* `--color-muted-foreground`, `--radius-overlay`
|
|
2592
|
+
*/
|
|
2593
|
+
class ComDropdownPanel {
|
|
2594
|
+
/** Reference to the panel element. */
|
|
2595
|
+
panelRef = viewChild('panelElement', ...(ngDevMode ? [{ debugName: "panelRef" }] : []));
|
|
2596
|
+
/** Reference to the virtual scroll viewport (when enabled). */
|
|
2597
|
+
viewport = viewChild('viewport', ...(ngDevMode ? [{ debugName: "viewport" }] : []));
|
|
2598
|
+
/** Unique identifier for the panel. */
|
|
2599
|
+
panelId = input('', ...(ngDevMode ? [{ debugName: "panelId" }] : []));
|
|
2600
|
+
/** The processed options to display. */
|
|
2601
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
2602
|
+
/** Maximum height of the panel. */
|
|
2603
|
+
maxHeight = input('256px', ...(ngDevMode ? [{ debugName: "maxHeight" }] : []));
|
|
2604
|
+
/** Whether multiple selection is enabled. */
|
|
2605
|
+
multiselectable = input(false, ...(ngDevMode ? [{ debugName: "multiselectable" }] : []));
|
|
2606
|
+
/** Size variant for styling. */
|
|
2607
|
+
size = input('default', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
2608
|
+
/** Additional CSS classes to apply to the panel. */
|
|
2609
|
+
panelClass = input('', ...(ngDevMode ? [{ debugName: "panelClass" }] : []));
|
|
2610
|
+
/** Whether virtual scrolling is enabled. */
|
|
2611
|
+
virtualScrollEnabled = input(false, ...(ngDevMode ? [{ debugName: "virtualScrollEnabled" }] : []));
|
|
2612
|
+
/** Item size for virtual scrolling (in pixels). */
|
|
2613
|
+
itemSize = input(40, ...(ngDevMode ? [{ debugName: "itemSize" }] : []));
|
|
2614
|
+
/** The current search query (for empty state context). */
|
|
2615
|
+
searchQuery = input('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
|
|
2616
|
+
/** Custom empty state text. */
|
|
2617
|
+
emptyText = input('No options available', ...(ngDevMode ? [{ debugName: "emptyText" }] : []));
|
|
2618
|
+
/** Template for rendering each option. */
|
|
2619
|
+
optionTemplate = input.required(...(ngDevMode ? [{ debugName: "optionTemplate" }] : []));
|
|
2620
|
+
/** Custom template for the empty state. */
|
|
2621
|
+
emptyTemplate = input(null, ...(ngDevMode ? [{ debugName: "emptyTemplate" }] : []));
|
|
2622
|
+
/** Emitted when the panel is scrolled. */
|
|
2623
|
+
scrolled = output();
|
|
2624
|
+
/** Whether to show the empty state. */
|
|
2625
|
+
showEmpty = computed(() => this.options().length === 0, ...(ngDevMode ? [{ debugName: "showEmpty" }] : []));
|
|
2626
|
+
/** Computed CSS classes for the panel. */
|
|
2627
|
+
panelClasses = computed(() => {
|
|
2628
|
+
const baseClasses = dropdownPanelVariants({ size: this.size() });
|
|
2629
|
+
return mergeClasses(baseClasses, this.panelClass());
|
|
2630
|
+
}, ...(ngDevMode ? [{ debugName: "panelClasses" }] : []));
|
|
2631
|
+
/** Computed CSS classes for the empty state. */
|
|
2632
|
+
emptyClasses = computed(() => {
|
|
2633
|
+
return dropdownEmptyVariants({ size: this.size() });
|
|
2634
|
+
}, ...(ngDevMode ? [{ debugName: "emptyClasses" }] : []));
|
|
2635
|
+
/** Template context for the empty state. */
|
|
2636
|
+
emptyContext = computed(() => ({
|
|
2637
|
+
$implicit: this.searchQuery(),
|
|
2638
|
+
}), ...(ngDevMode ? [{ debugName: "emptyContext" }] : []));
|
|
2639
|
+
/** Track function for options. */
|
|
2640
|
+
trackByFn(_index, option) {
|
|
2641
|
+
return option.id;
|
|
2642
|
+
}
|
|
2643
|
+
/** Scrolls to a specific index. */
|
|
2644
|
+
scrollToIndex(index) {
|
|
2645
|
+
const vp = this.viewport();
|
|
2646
|
+
if (this.virtualScrollEnabled() && vp) {
|
|
2647
|
+
vp.scrollToIndex(index);
|
|
2648
|
+
}
|
|
2649
|
+
else {
|
|
2650
|
+
const panelEl = this.panelRef()?.nativeElement;
|
|
2651
|
+
const optionEl = panelEl?.querySelector(`[data-index="${index}"]`);
|
|
2652
|
+
optionEl?.scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
/** Scrolls an option into view. */
|
|
2656
|
+
scrollOptionIntoView(optionElement) {
|
|
2657
|
+
optionElement.scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
2658
|
+
}
|
|
2659
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDropdownPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2660
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: ComDropdownPanel, isStandalone: true, selector: "com-dropdown-panel", inputs: { panelId: { classPropertyName: "panelId", publicName: "panelId", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, multiselectable: { classPropertyName: "multiselectable", publicName: "multiselectable", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollEnabled: { classPropertyName: "virtualScrollEnabled", publicName: "virtualScrollEnabled", isSignal: true, isRequired: false, transformFunction: null }, itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: false, transformFunction: null }, searchQuery: { classPropertyName: "searchQuery", publicName: "searchQuery", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, optionTemplate: { classPropertyName: "optionTemplate", publicName: "optionTemplate", isSignal: true, isRequired: true, transformFunction: null }, emptyTemplate: { classPropertyName: "emptyTemplate", publicName: "emptyTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { scrolled: "scrolled" }, host: { classAttribute: "com-dropdown-panel-host block" }, viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panelElement"], descendants: true, isSignal: true }, { propertyName: "viewport", first: true, predicate: ["viewport"], descendants: true, isSignal: true }], exportAs: ["comDropdownPanel"], ngImport: i0, template: `
|
|
2661
|
+
<div
|
|
2662
|
+
#panelElement
|
|
2663
|
+
[class]="panelClasses()"
|
|
2664
|
+
[attr.role]="'listbox'"
|
|
2665
|
+
[attr.aria-multiselectable]="multiselectable() || null"
|
|
2666
|
+
[attr.id]="panelId()"
|
|
2667
|
+
>
|
|
2668
|
+
<!-- Search slot -->
|
|
2669
|
+
<ng-content select="[comDropdownSearch]" />
|
|
2670
|
+
|
|
2671
|
+
<!-- Options container -->
|
|
2672
|
+
@if (virtualScrollEnabled()) {
|
|
2673
|
+
<cdk-virtual-scroll-viewport
|
|
2674
|
+
[itemSize]="itemSize()"
|
|
2675
|
+
[maxBufferPx]="400"
|
|
2676
|
+
[minBufferPx]="200"
|
|
2677
|
+
[style.height]="maxHeight()"
|
|
2678
|
+
class="overflow-auto"
|
|
2679
|
+
>
|
|
2680
|
+
<div
|
|
2681
|
+
*cdkVirtualFor="let option of options(); trackBy: trackByFn; let i = index"
|
|
2682
|
+
[attr.data-index]="i"
|
|
2683
|
+
>
|
|
2684
|
+
<ng-container
|
|
2685
|
+
[ngTemplateOutlet]="optionTemplate()"
|
|
2686
|
+
[ngTemplateOutletContext]="{ $implicit: option, index: i }"
|
|
2687
|
+
/>
|
|
2688
|
+
</div>
|
|
2689
|
+
</cdk-virtual-scroll-viewport>
|
|
2690
|
+
} @else {
|
|
2691
|
+
<div
|
|
2692
|
+
class="overflow-auto"
|
|
2693
|
+
[style.maxHeight]="maxHeight()"
|
|
2694
|
+
>
|
|
2695
|
+
@for (option of options(); track option.id; let i = $index) {
|
|
2696
|
+
<ng-container
|
|
2697
|
+
[ngTemplateOutlet]="optionTemplate()"
|
|
2698
|
+
[ngTemplateOutletContext]="{ $implicit: option, index: i }"
|
|
2699
|
+
/>
|
|
2700
|
+
}
|
|
2701
|
+
</div>
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
<!-- Empty state -->
|
|
2705
|
+
@if (showEmpty()) {
|
|
2706
|
+
@if (emptyTemplate()) {
|
|
2707
|
+
<ng-container
|
|
2708
|
+
[ngTemplateOutlet]="emptyTemplate()!"
|
|
2709
|
+
[ngTemplateOutletContext]="emptyContext()"
|
|
2710
|
+
/>
|
|
2711
|
+
} @else {
|
|
2712
|
+
<div [class]="emptyClasses()">
|
|
2713
|
+
{{ emptyText() }}
|
|
2714
|
+
</div>
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
</div>
|
|
2718
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2719
|
+
}
|
|
2720
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: ComDropdownPanel, decorators: [{
|
|
2721
|
+
type: Component,
|
|
2722
|
+
args: [{
|
|
2723
|
+
selector: 'com-dropdown-panel',
|
|
2724
|
+
exportAs: 'comDropdownPanel',
|
|
2725
|
+
template: `
|
|
2726
|
+
<div
|
|
2727
|
+
#panelElement
|
|
2728
|
+
[class]="panelClasses()"
|
|
2729
|
+
[attr.role]="'listbox'"
|
|
2730
|
+
[attr.aria-multiselectable]="multiselectable() || null"
|
|
2731
|
+
[attr.id]="panelId()"
|
|
2732
|
+
>
|
|
2733
|
+
<!-- Search slot -->
|
|
2734
|
+
<ng-content select="[comDropdownSearch]" />
|
|
2735
|
+
|
|
2736
|
+
<!-- Options container -->
|
|
2737
|
+
@if (virtualScrollEnabled()) {
|
|
2738
|
+
<cdk-virtual-scroll-viewport
|
|
2739
|
+
[itemSize]="itemSize()"
|
|
2740
|
+
[maxBufferPx]="400"
|
|
2741
|
+
[minBufferPx]="200"
|
|
2742
|
+
[style.height]="maxHeight()"
|
|
2743
|
+
class="overflow-auto"
|
|
2744
|
+
>
|
|
2745
|
+
<div
|
|
2746
|
+
*cdkVirtualFor="let option of options(); trackBy: trackByFn; let i = index"
|
|
2747
|
+
[attr.data-index]="i"
|
|
2748
|
+
>
|
|
2749
|
+
<ng-container
|
|
2750
|
+
[ngTemplateOutlet]="optionTemplate()"
|
|
2751
|
+
[ngTemplateOutletContext]="{ $implicit: option, index: i }"
|
|
2752
|
+
/>
|
|
2753
|
+
</div>
|
|
2754
|
+
</cdk-virtual-scroll-viewport>
|
|
2755
|
+
} @else {
|
|
2756
|
+
<div
|
|
2757
|
+
class="overflow-auto"
|
|
2758
|
+
[style.maxHeight]="maxHeight()"
|
|
2759
|
+
>
|
|
2760
|
+
@for (option of options(); track option.id; let i = $index) {
|
|
2761
|
+
<ng-container
|
|
2762
|
+
[ngTemplateOutlet]="optionTemplate()"
|
|
2763
|
+
[ngTemplateOutletContext]="{ $implicit: option, index: i }"
|
|
2764
|
+
/>
|
|
2765
|
+
}
|
|
2766
|
+
</div>
|
|
2767
|
+
}
|
|
2768
|
+
|
|
2769
|
+
<!-- Empty state -->
|
|
2770
|
+
@if (showEmpty()) {
|
|
2771
|
+
@if (emptyTemplate()) {
|
|
2772
|
+
<ng-container
|
|
2773
|
+
[ngTemplateOutlet]="emptyTemplate()!"
|
|
2774
|
+
[ngTemplateOutletContext]="emptyContext()"
|
|
2775
|
+
/>
|
|
2776
|
+
} @else {
|
|
2777
|
+
<div [class]="emptyClasses()">
|
|
2778
|
+
{{ emptyText() }}
|
|
2779
|
+
</div>
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
</div>
|
|
2783
|
+
`,
|
|
2784
|
+
imports: [
|
|
2785
|
+
NgTemplateOutlet,
|
|
2786
|
+
CdkVirtualScrollViewport,
|
|
2787
|
+
CdkFixedSizeVirtualScroll,
|
|
2788
|
+
CdkVirtualForOf,
|
|
2789
|
+
],
|
|
2790
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2791
|
+
host: {
|
|
2792
|
+
class: 'com-dropdown-panel-host block',
|
|
2793
|
+
},
|
|
2794
|
+
}]
|
|
2795
|
+
}], propDecorators: { panelRef: [{ type: i0.ViewChild, args: ['panelElement', { isSignal: true }] }], viewport: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }], panelId: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelId", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], multiselectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiselectable", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], virtualScrollEnabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollEnabled", required: false }] }], itemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSize", required: false }] }], searchQuery: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchQuery", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], optionTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionTemplate", required: true }] }], emptyTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTemplate", required: false }] }], scrolled: [{ type: i0.Output, args: ["scrolled"] }] } });
|
|
2690
2796
|
|
|
2691
2797
|
// Public API for the dropdown component
|
|
2692
2798
|
// Main component
|