@nanahoshi/mona-ui 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.
Files changed (134) hide show
  1. package/README.md +25 -0
  2. package/fesm2022/nanahoshi-mona-ui-auto-complete.mjs +590 -0
  3. package/fesm2022/nanahoshi-mona-ui-avatar.mjs +168 -0
  4. package/fesm2022/nanahoshi-mona-ui-breadcrumb.mjs +220 -0
  5. package/fesm2022/nanahoshi-mona-ui-button-group.mjs +225 -0
  6. package/fesm2022/nanahoshi-mona-ui-button.mjs +497 -0
  7. package/fesm2022/nanahoshi-mona-ui-calendar.mjs +1569 -0
  8. package/fesm2022/nanahoshi-mona-ui-check-box.mjs +339 -0
  9. package/fesm2022/nanahoshi-mona-ui-chip.mjs +453 -0
  10. package/fesm2022/nanahoshi-mona-ui-circular-progress-bar.mjs +200 -0
  11. package/fesm2022/nanahoshi-mona-ui-color-gradient.mjs +853 -0
  12. package/fesm2022/nanahoshi-mona-ui-color-palette.mjs +923 -0
  13. package/fesm2022/nanahoshi-mona-ui-color-picker.mjs +495 -0
  14. package/fesm2022/nanahoshi-mona-ui-combo-box.mjs +686 -0
  15. package/fesm2022/nanahoshi-mona-ui-common.mjs +642 -0
  16. package/fesm2022/nanahoshi-mona-ui-contextmenu.mjs +485 -0
  17. package/fesm2022/nanahoshi-mona-ui-date-input.mjs +132 -0
  18. package/fesm2022/nanahoshi-mona-ui-date-picker.mjs +460 -0
  19. package/fesm2022/nanahoshi-mona-ui-datetime-picker.mjs +659 -0
  20. package/fesm2022/nanahoshi-mona-ui-dialog.mjs +828 -0
  21. package/fesm2022/nanahoshi-mona-ui-dropdown-button.mjs +523 -0
  22. package/fesm2022/nanahoshi-mona-ui-dropdown-list.mjs +615 -0
  23. package/fesm2022/nanahoshi-mona-ui-dropdowns.mjs +701 -0
  24. package/fesm2022/nanahoshi-mona-ui-editor.mjs +1400 -0
  25. package/fesm2022/nanahoshi-mona-ui-expansion-panel.mjs +245 -0
  26. package/fesm2022/nanahoshi-mona-ui-fieldset.mjs +170 -0
  27. package/fesm2022/nanahoshi-mona-ui-filter.mjs +680 -0
  28. package/fesm2022/nanahoshi-mona-ui-grid-grid-footer-cell.component-B9SQH5N-.mjs +105 -0
  29. package/fesm2022/nanahoshi-mona-ui-grid-grid-footer-table-cell.directive-DlLwcCFT.mjs +42 -0
  30. package/fesm2022/nanahoshi-mona-ui-grid-grid-list.component-Dgea-O0X.mjs +130 -0
  31. package/fesm2022/nanahoshi-mona-ui-grid-grid-toggle.component-DIUutx9s.mjs +773 -0
  32. package/fesm2022/nanahoshi-mona-ui-grid-grid-virtual-list.component-DRHycGIh.mjs +240 -0
  33. package/fesm2022/nanahoshi-mona-ui-grid-nanahoshi-mona-ui-grid-C3eZIaJK.mjs +5374 -0
  34. package/fesm2022/nanahoshi-mona-ui-grid.mjs +2 -0
  35. package/fesm2022/nanahoshi-mona-ui-internal-filter-input.mjs +87 -0
  36. package/fesm2022/nanahoshi-mona-ui-internal-indicator-icon.mjs +154 -0
  37. package/fesm2022/nanahoshi-mona-ui-internal-list.mjs +1356 -0
  38. package/fesm2022/nanahoshi-mona-ui-internal-tree.mjs +2263 -0
  39. package/fesm2022/nanahoshi-mona-ui-internal.mjs +379 -0
  40. package/fesm2022/nanahoshi-mona-ui-list-box.mjs +630 -0
  41. package/fesm2022/nanahoshi-mona-ui-list-view.mjs +527 -0
  42. package/fesm2022/nanahoshi-mona-ui-list.mjs +4 -0
  43. package/fesm2022/nanahoshi-mona-ui-menubar.mjs +966 -0
  44. package/fesm2022/nanahoshi-mona-ui-multi-select.mjs +641 -0
  45. package/fesm2022/nanahoshi-mona-ui-notification.mjs +536 -0
  46. package/fesm2022/nanahoshi-mona-ui-numeric-text-box.mjs +597 -0
  47. package/fesm2022/nanahoshi-mona-ui-pager.mjs +790 -0
  48. package/fesm2022/nanahoshi-mona-ui-placeholder.mjs +83 -0
  49. package/fesm2022/nanahoshi-mona-ui-popover.mjs +325 -0
  50. package/fesm2022/nanahoshi-mona-ui-popup-menu.mjs +1559 -0
  51. package/fesm2022/nanahoshi-mona-ui-popup.mjs +1321 -0
  52. package/fesm2022/nanahoshi-mona-ui-progress-bar.mjs +294 -0
  53. package/fesm2022/nanahoshi-mona-ui-query.mjs +175 -0
  54. package/fesm2022/nanahoshi-mona-ui-radio-button.mjs +339 -0
  55. package/fesm2022/nanahoshi-mona-ui-scroll-view.mjs +565 -0
  56. package/fesm2022/nanahoshi-mona-ui-slider.mjs +1049 -0
  57. package/fesm2022/nanahoshi-mona-ui-split-button.mjs +636 -0
  58. package/fesm2022/nanahoshi-mona-ui-splitter.mjs +843 -0
  59. package/fesm2022/nanahoshi-mona-ui-stepper.mjs +537 -0
  60. package/fesm2022/nanahoshi-mona-ui-switch.mjs +308 -0
  61. package/fesm2022/nanahoshi-mona-ui-tabs.mjs +664 -0
  62. package/fesm2022/nanahoshi-mona-ui-text-area.mjs +111 -0
  63. package/fesm2022/nanahoshi-mona-ui-text-box.mjs +369 -0
  64. package/fesm2022/nanahoshi-mona-ui-theme.mjs +314 -0
  65. package/fesm2022/nanahoshi-mona-ui-time-picker.mjs +450 -0
  66. package/fesm2022/nanahoshi-mona-ui-time-selector.mjs +723 -0
  67. package/fesm2022/nanahoshi-mona-ui-tooltip.mjs +716 -0
  68. package/fesm2022/nanahoshi-mona-ui-tree-view.mjs +733 -0
  69. package/fesm2022/nanahoshi-mona-ui-window.mjs +1329 -0
  70. package/fesm2022/nanahoshi-mona-ui.mjs +9 -0
  71. package/package.json +289 -0
  72. package/types/nanahoshi-mona-ui-auto-complete.d.ts +223 -0
  73. package/types/nanahoshi-mona-ui-avatar.d.ts +642 -0
  74. package/types/nanahoshi-mona-ui-breadcrumb.d.ts +70 -0
  75. package/types/nanahoshi-mona-ui-button-group.d.ts +77 -0
  76. package/types/nanahoshi-mona-ui-button.d.ts +111 -0
  77. package/types/nanahoshi-mona-ui-calendar.d.ts +262 -0
  78. package/types/nanahoshi-mona-ui-check-box.d.ts +133 -0
  79. package/types/nanahoshi-mona-ui-chip.d.ts +130 -0
  80. package/types/nanahoshi-mona-ui-circular-progress-bar.d.ts +113 -0
  81. package/types/nanahoshi-mona-ui-color-gradient.d.ts +201 -0
  82. package/types/nanahoshi-mona-ui-color-palette.d.ts +102 -0
  83. package/types/nanahoshi-mona-ui-color-picker.d.ts +156 -0
  84. package/types/nanahoshi-mona-ui-combo-box.d.ts +232 -0
  85. package/types/nanahoshi-mona-ui-common.d.ts +386 -0
  86. package/types/nanahoshi-mona-ui-contextmenu.d.ts +129 -0
  87. package/types/nanahoshi-mona-ui-date-input.d.ts +60 -0
  88. package/types/nanahoshi-mona-ui-date-picker.d.ts +177 -0
  89. package/types/nanahoshi-mona-ui-datetime-picker.d.ts +199 -0
  90. package/types/nanahoshi-mona-ui-dialog.d.ts +261 -0
  91. package/types/nanahoshi-mona-ui-dropdown-button.d.ts +159 -0
  92. package/types/nanahoshi-mona-ui-dropdown-list.d.ts +219 -0
  93. package/types/nanahoshi-mona-ui-dropdowns.d.ts +176 -0
  94. package/types/nanahoshi-mona-ui-editor.d.ts +113 -0
  95. package/types/nanahoshi-mona-ui-expansion-panel.d.ts +87 -0
  96. package/types/nanahoshi-mona-ui-fieldset.d.ts +68 -0
  97. package/types/nanahoshi-mona-ui-filter.d.ts +115 -0
  98. package/types/nanahoshi-mona-ui-grid.d.ts +1114 -0
  99. package/types/nanahoshi-mona-ui-internal-filter-input.d.ts +25 -0
  100. package/types/nanahoshi-mona-ui-internal-indicator-icon.d.ts +28 -0
  101. package/types/nanahoshi-mona-ui-internal-list.d.ts +269 -0
  102. package/types/nanahoshi-mona-ui-internal-tree.d.ts +391 -0
  103. package/types/nanahoshi-mona-ui-internal.d.ts +136 -0
  104. package/types/nanahoshi-mona-ui-list-box.d.ts +225 -0
  105. package/types/nanahoshi-mona-ui-list-view.d.ts +188 -0
  106. package/types/nanahoshi-mona-ui-list.d.ts +1 -0
  107. package/types/nanahoshi-mona-ui-menubar.d.ts +198 -0
  108. package/types/nanahoshi-mona-ui-multi-select.d.ts +247 -0
  109. package/types/nanahoshi-mona-ui-notification.d.ts +106 -0
  110. package/types/nanahoshi-mona-ui-numeric-text-box.d.ts +161 -0
  111. package/types/nanahoshi-mona-ui-pager.d.ts +238 -0
  112. package/types/nanahoshi-mona-ui-placeholder.d.ts +35 -0
  113. package/types/nanahoshi-mona-ui-popover.d.ts +130 -0
  114. package/types/nanahoshi-mona-ui-popup-menu.d.ts +412 -0
  115. package/types/nanahoshi-mona-ui-popup.d.ts +485 -0
  116. package/types/nanahoshi-mona-ui-progress-bar.d.ts +139 -0
  117. package/types/nanahoshi-mona-ui-query.d.ts +89 -0
  118. package/types/nanahoshi-mona-ui-radio-button.d.ts +128 -0
  119. package/types/nanahoshi-mona-ui-scroll-view.d.ts +166 -0
  120. package/types/nanahoshi-mona-ui-slider.d.ts +305 -0
  121. package/types/nanahoshi-mona-ui-split-button.d.ts +182 -0
  122. package/types/nanahoshi-mona-ui-splitter.d.ts +70 -0
  123. package/types/nanahoshi-mona-ui-stepper.d.ts +173 -0
  124. package/types/nanahoshi-mona-ui-switch.d.ts +125 -0
  125. package/types/nanahoshi-mona-ui-tabs.d.ts +158 -0
  126. package/types/nanahoshi-mona-ui-text-area.d.ts +42 -0
  127. package/types/nanahoshi-mona-ui-text-box.d.ts +164 -0
  128. package/types/nanahoshi-mona-ui-theme.d.ts +23 -0
  129. package/types/nanahoshi-mona-ui-time-picker.d.ts +184 -0
  130. package/types/nanahoshi-mona-ui-time-selector.d.ts +143 -0
  131. package/types/nanahoshi-mona-ui-tooltip.d.ts +130 -0
  132. package/types/nanahoshi-mona-ui-tree-view.d.ts +274 -0
  133. package/types/nanahoshi-mona-ui-window.d.ts +295 -0
  134. package/types/nanahoshi-mona-ui.d.ts +2 -0
@@ -0,0 +1,1356 @@
1
+ import { CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll, CdkVirtualForOf } from '@angular/cdk/scrolling';
2
+ import { NgTemplateOutlet } from '@angular/common';
3
+ import * as i0 from '@angular/core';
4
+ import { Directive, signal, computed, Injectable, inject, input, ElementRef, output, ChangeDetectionStrategy, Component, DestroyRef, viewChild, contentChild, TemplateRef, effect, untracked, afterNextRender } from '@angular/core';
5
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
+ import { isTypeaheadKey, setupTypeahead } from '@nanahoshi/mona-ui/internal';
7
+ import { FilterInputComponent } from '@nanahoshi/mona-ui/internal/filter-input';
8
+ import { PlaceholderComponent } from '@nanahoshi/mona-ui/placeholder';
9
+ import { Subject, ReplaySubject, fromEvent, asyncScheduler, filter, tap } from 'rxjs';
10
+ import { twMerge } from 'tailwind-merge';
11
+ import { cva } from 'class-variance-authority';
12
+ import { ImmutableList, from, ImmutableSet, toImmutableSet } from '@mirei/ts-collections';
13
+ import { v4 } from 'uuid';
14
+ import * as i1 from '@angular/forms';
15
+ import { FormsModule } from '@angular/forms';
16
+ import { CheckboxDirective } from '@nanahoshi/mona-ui/check-box';
17
+
18
+ class ListFooterTemplateDirective {
19
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListFooterTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
20
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.6", type: ListFooterTemplateDirective, isStandalone: true, selector: "ng-template[monaListFooterTemplate]", ngImport: i0 }); }
21
+ }
22
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListFooterTemplateDirective, decorators: [{
23
+ type: Directive,
24
+ args: [{
25
+ selector: "ng-template[monaListFooterTemplate]",
26
+ standalone: true
27
+ }]
28
+ }] });
29
+
30
+ class ListGroupHeaderTemplateDirective {
31
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListGroupHeaderTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
32
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.6", type: ListGroupHeaderTemplateDirective, isStandalone: true, selector: "ng-template[monaListGroupHeaderTemplate]", ngImport: i0 }); }
33
+ }
34
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListGroupHeaderTemplateDirective, decorators: [{
35
+ type: Directive,
36
+ args: [{
37
+ selector: "ng-template[monaListGroupHeaderTemplate]",
38
+ standalone: true
39
+ }]
40
+ }] });
41
+
42
+ class ListHeaderTemplateDirective {
43
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListHeaderTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
44
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.6", type: ListHeaderTemplateDirective, isStandalone: true, selector: "ng-template[monaListHeaderTemplate]", ngImport: i0 }); }
45
+ }
46
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListHeaderTemplateDirective, decorators: [{
47
+ type: Directive,
48
+ args: [{
49
+ selector: "ng-template[monaListHeaderTemplate]",
50
+ standalone: true
51
+ }]
52
+ }] });
53
+
54
+ class ListItemTemplateDirective {
55
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListItemTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
56
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.6", type: ListItemTemplateDirective, isStandalone: true, selector: "ng-template[monaListItemTemplate]", ngImport: i0 }); }
57
+ }
58
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListItemTemplateDirective, decorators: [{
59
+ type: Directive,
60
+ args: [{
61
+ selector: "ng-template[monaListItemTemplate]",
62
+ standalone: true
63
+ }]
64
+ }] });
65
+
66
+ const listVariants = cva(`
67
+ h-full flex flex-col overflow-hidden outline-none
68
+ `);
69
+ const listInnerListVariants = cva(`
70
+ list-none p-0 m-0 overflow-x-hidden overflow-y-auto
71
+ h-full outline-none
72
+ `);
73
+ const listGroupHeaderVariants = cva(``, {
74
+ variants: {
75
+ hasTemplate: {
76
+ true: "",
77
+ false: "py-1 font-bold"
78
+ }
79
+ }
80
+ });
81
+ const listGroupHeaderTextVariants = cva(`select-none`, {
82
+ variants: {
83
+ hasTemplate: {
84
+ true: "",
85
+ false: "font-bold w-full px-3 py-1"
86
+ }
87
+ }
88
+ });
89
+ const listItemBaseVariants = cva(`
90
+ w-full h-full flex gap-2 items-center
91
+ `);
92
+ const listItemContentVariants = cva(`
93
+ relative flex cursor-default select-none items-center
94
+ outline-none px-3 py-1
95
+ hover:bg-accent hover:text-accent-foreground
96
+ focus:bg-accent focus:text-accent-foreground
97
+ `, {
98
+ variants: {
99
+ checkboxes: {
100
+ true: "gap-2",
101
+ false: ""
102
+ },
103
+ highlighted: {
104
+ true: "bg-accent text-accent-foreground rounded-none inset-ring-1 inset-ring-gray-400/70",
105
+ false: ""
106
+ },
107
+ selected: {
108
+ true: "bg-primary text-primary-foreground inset-ring-1 inset-ring-primary-foreground/40",
109
+ false: ""
110
+ },
111
+ disabled: {
112
+ true: "pointer-events-none opacity-50 cursor-default",
113
+ false: "cursor-pointer"
114
+ }
115
+ },
116
+ compoundVariants: [
117
+ {
118
+ selected: true,
119
+ checkboxes: false,
120
+ class: `
121
+ bg-primary text-primary-foreground rounded-none
122
+ inset-ring-1 inset-ring-primary-foreground/40
123
+ hover:bg-primary hover:text-primary-foreground
124
+ focus:bg-primary focus:text-primary-foreground
125
+ `
126
+ },
127
+ {
128
+ highlighted: true,
129
+ selected: true,
130
+ checkboxes: false,
131
+ class: `
132
+ bg-primary text-primary-foreground rounded-none
133
+ inset-ring-1 inset-ring-primary-foreground/40
134
+ hover:bg-primary hover:text-primary-foreground
135
+ focus:bg-primary focus:text-primary-foreground
136
+ `
137
+ },
138
+ {
139
+ selected: true,
140
+ checkboxes: true,
141
+ class: `bg-transparent text-foreground`
142
+ }
143
+ ]
144
+ });
145
+
146
+ class ListItem {
147
+ constructor(options) {
148
+ this.header = "";
149
+ this.uid = v4();
150
+ this.data = options.data;
151
+ this.header = options.header ?? this.header;
152
+ }
153
+ }
154
+
155
+ const cycleThroughMatchedItems = (items, activeItem, // highlighted or selected item
156
+ predicate) => {
157
+ const matchedItems = Array.from(items).filter(predicate);
158
+ if (matchedItems.length === 0) {
159
+ return null;
160
+ }
161
+ const currentIndex = activeItem ? matchedItems.indexOf(activeItem) : -1;
162
+ const nextIndex = (currentIndex + 1) % matchedItems.length;
163
+ return matchedItems[nextIndex];
164
+ };
165
+
166
+ class ListService {
167
+ constructor() {
168
+ this.#data = signal(ImmutableList.create(), /* @ts-ignore */
169
+ ...(ngDevMode ? [{ debugName: "#data" }] : /* istanbul ignore next */ []));
170
+ this.#listItems = computed(() => {
171
+ const data = this.#data();
172
+ return from(data)
173
+ .select(item => new ListItem({ data: item, header: "" }))
174
+ .toImmutableSet();
175
+ }, /* @ts-ignore */
176
+ ...(ngDevMode ? [{ debugName: "#listItems" }] : /* istanbul ignore next */ []));
177
+ this.disabledBy = signal("", /* @ts-ignore */
178
+ ...(ngDevMode ? [{ debugName: "disabledBy" }] : /* istanbul ignore next */ []));
179
+ this.filterChange$ = new Subject();
180
+ this.filterInputVisible = signal(true, /* @ts-ignore */
181
+ ...(ngDevMode ? [{ debugName: "filterInputVisible" }] : /* istanbul ignore next */ []));
182
+ this.filterPlaceholder = signal("", /* @ts-ignore */
183
+ ...(ngDevMode ? [{ debugName: "filterPlaceholder" }] : /* istanbul ignore next */ []));
184
+ this.filterText = signal("", /* @ts-ignore */
185
+ ...(ngDevMode ? [{ debugName: "filterText" }] : /* istanbul ignore next */ []));
186
+ this.filterableOptions = signal({
187
+ enabled: false,
188
+ caseSensitive: false,
189
+ debounce: 0,
190
+ operator: "contains"
191
+ }, /* @ts-ignore */
192
+ ...(ngDevMode ? [{ debugName: "filterableOptions" }] : /* istanbul ignore next */ []));
193
+ this.focus$ = new Subject();
194
+ this.focusableItem = computed(() => {
195
+ const highlighted = this.highlightedItem();
196
+ if (highlighted) {
197
+ return highlighted;
198
+ }
199
+ const selected = this.selectedListItems().lastOrDefault();
200
+ if (selected) {
201
+ return selected;
202
+ }
203
+ return this.viewItems().firstOrDefault(i => !i.header && !this.isDisabled(i));
204
+ }, /* @ts-ignore */
205
+ ...(ngDevMode ? [{ debugName: "focusableItem" }] : /* istanbul ignore next */ []));
206
+ this.groupBy = signal(null, /* @ts-ignore */
207
+ ...(ngDevMode ? [{ debugName: "groupBy" }] : /* istanbul ignore next */ []));
208
+ this.groupableOptions = signal({
209
+ enabled: false,
210
+ headerOrder: "asc"
211
+ }, /* @ts-ignore */
212
+ ...(ngDevMode ? [{ debugName: "groupableOptions" }] : /* istanbul ignore next */ []));
213
+ this.highlightedItem = signal(null, /* @ts-ignore */
214
+ ...(ngDevMode ? [{ debugName: "highlightedItem" }] : /* istanbul ignore next */ []));
215
+ this.itemFocusOut$ = new Subject();
216
+ this.navigatedItem$ = new Subject();
217
+ this.navigableOptions = signal({
218
+ enabled: false,
219
+ mode: "select",
220
+ wrap: false
221
+ }, /* @ts-ignore */
222
+ ...(ngDevMode ? [{ debugName: "navigableOptions" }] : /* istanbul ignore next */ []));
223
+ this.pageState = signal({ page: 1, skip: 0, take: 10 }, /* @ts-ignore */
224
+ ...(ngDevMode ? [{ debugName: "pageState" }] : /* istanbul ignore next */ []));
225
+ this.pageableOptions = signal({
226
+ enabled: false,
227
+ firstLast: false,
228
+ showInfo: true,
229
+ pageSizeValues: true,
230
+ previousNext: false,
231
+ type: "numeric",
232
+ visiblePages: 5
233
+ }, /* @ts-ignore */
234
+ ...(ngDevMode ? [{ debugName: "pageableOptions" }] : /* istanbul ignore next */ []));
235
+ this.scrollToItem$ = new ReplaySubject(1);
236
+ this.selectableOptions = signal({
237
+ checkboxes: false,
238
+ enabled: false,
239
+ mode: "single",
240
+ toggleable: false
241
+ }, /* @ts-ignore */
242
+ ...(ngDevMode ? [{ debugName: "selectableOptions" }] : /* istanbul ignore next */ []));
243
+ this.selectedKeys = signal(ImmutableSet.create(), /* @ts-ignore */
244
+ ...(ngDevMode ? [{ debugName: "selectedKeys" }] : /* istanbul ignore next */ []));
245
+ this.selectedKeysChange$ = new Subject();
246
+ this.selectedListItems = computed(() => {
247
+ const selectedKeys = this.selectedKeys();
248
+ return selectedKeys
249
+ .select(key => this.#listItems().firstOrDefault(i => this.getSelectionKey(i) === key))
250
+ .where(i => i != null)
251
+ .toImmutableSet();
252
+ }, /* @ts-ignore */
253
+ ...(ngDevMode ? [{ debugName: "selectedListItems" }] : /* istanbul ignore next */ []));
254
+ this.selectionChange$ = new Subject();
255
+ this.textField = signal("", /* @ts-ignore */
256
+ ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
257
+ this.valueField = signal("", /* @ts-ignore */
258
+ ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
259
+ this.viewItems = computed(() => {
260
+ const listItems = this.#listItems();
261
+ const filterText = this.filterText();
262
+ const groupableOptions = this.groupableOptions();
263
+ const virtualScrollOptions = this.virtualScrollOptions();
264
+ let enumerable = listItems;
265
+ if (filterText) {
266
+ enumerable = enumerable.where(item => this.filterItem(item, filterText));
267
+ }
268
+ let resultEnumerable;
269
+ if (groupableOptions.enabled) {
270
+ if (groupableOptions.orderBy) {
271
+ if (groupableOptions.orderByDirection === "desc") {
272
+ enumerable = enumerable.orderByDescending(item => this.getOrderKey(item));
273
+ }
274
+ else {
275
+ enumerable = enumerable.orderBy(item => this.getOrderKey(item));
276
+ }
277
+ }
278
+ let groupedEnumerable = enumerable.groupBy(item => this.getGroupField(item));
279
+ if (groupableOptions.headerOrder) {
280
+ if (groupableOptions.headerOrder === "desc") {
281
+ groupedEnumerable = groupedEnumerable.orderByDescending(g => g.key);
282
+ }
283
+ else {
284
+ groupedEnumerable = groupedEnumerable.orderBy(g => g.key);
285
+ }
286
+ }
287
+ resultEnumerable = groupedEnumerable.selectMany(g => {
288
+ const groupHeaderItem = new ListItem({ data: g.key, header: String(g.key) });
289
+ return g.source.prepend(groupHeaderItem);
290
+ });
291
+ }
292
+ else {
293
+ resultEnumerable = enumerable;
294
+ }
295
+ const pageableOptions = this.pageableOptions();
296
+ if (virtualScrollOptions.enabled) {
297
+ return resultEnumerable.toImmutableSet();
298
+ }
299
+ if (pageableOptions.enabled) {
300
+ const pageState = this.pageState();
301
+ const skip = pageState.skip;
302
+ const take = pageState.take;
303
+ return toImmutableSet(this.skipTakeWithGroups(resultEnumerable.toArray(), skip, take));
304
+ }
305
+ return resultEnumerable.toImmutableSet();
306
+ }, /* @ts-ignore */
307
+ ...(ngDevMode ? [{ debugName: "viewItems" }] : /* istanbul ignore next */ []));
308
+ this.virtualScrollOptions = signal({
309
+ enabled: false,
310
+ height: 28
311
+ }, /* @ts-ignore */
312
+ ...(ngDevMode ? [{ debugName: "virtualScrollOptions" }] : /* istanbul ignore next */ []));
313
+ this.itemPositions = computed(() => {
314
+ const viewItems = this.viewItems();
315
+ const nonHeaderItems = viewItems.where(i => !i.header).toArray();
316
+ const positions = new Map();
317
+ nonHeaderItems.forEach((item, index) => {
318
+ positions.set(item.uid, { position: index + 1, total: nonHeaderItems.length });
319
+ });
320
+ return positions;
321
+ }, /* @ts-ignore */
322
+ ...(ngDevMode ? [{ debugName: "itemPositions" }] : /* istanbul ignore next */ []));
323
+ }
324
+ #data;
325
+ #listItems;
326
+ getItemPosition(item) {
327
+ return this.itemPositions().get(item.uid) ?? null;
328
+ }
329
+ clearFilter() {
330
+ this.filterText.set("");
331
+ }
332
+ clearHighlightedItem() {
333
+ this.highlightedItem.set(null);
334
+ }
335
+ clearSelections() {
336
+ this.selectedKeys.update(set => set.clear());
337
+ this.highlightedItem.set(null);
338
+ }
339
+ cycleThroughMatchedItems(buffer) {
340
+ const activeItem = this.highlightedItem() || this.selectedListItems().lastOrDefault();
341
+ const viewItems = this.viewItems();
342
+ return cycleThroughMatchedItems(viewItems, activeItem, item => {
343
+ const text = this.getItemText(item);
344
+ return text.toLowerCase().startsWith(buffer.toLowerCase());
345
+ });
346
+ }
347
+ deselectItems(item) {
348
+ const keys = from(item)
349
+ .select(i => this.getSelectionKey(i))
350
+ .toImmutableSet();
351
+ this.selectedKeys.update(set => set.removeAll(keys));
352
+ }
353
+ getFilterDebounceDuration() {
354
+ const filterableOptions = this.filterableOptions();
355
+ return filterableOptions.enabled ? filterableOptions.debounce : 0;
356
+ }
357
+ getGroupField(item) {
358
+ const groupSelector = this.groupBy();
359
+ if (groupSelector == null) {
360
+ return "";
361
+ }
362
+ if (typeof groupSelector === "string") {
363
+ return item.data?.[groupSelector] ?? "";
364
+ }
365
+ return groupSelector(item.data);
366
+ }
367
+ getItemText(item) {
368
+ const textField = this.textField();
369
+ if (!textField) {
370
+ return item.data?.toString() ?? "";
371
+ }
372
+ if (typeof textField === "string") {
373
+ return item.data?.[textField] ?? "";
374
+ }
375
+ return textField(item.data);
376
+ }
377
+ getMatchingFilteredItem(text) {
378
+ const filterableOptions = this.filterableOptions();
379
+ const caseSensitive = filterableOptions.enabled ? filterableOptions.caseSensitive : false;
380
+ const viewItems = this.viewItems();
381
+ const allMatchingItems = viewItems.where(i => this.filterItem(i, text));
382
+ const fullMatchingItem = viewItems.firstOrDefault(i => {
383
+ if (!caseSensitive) {
384
+ return this.getItemText(i) === text;
385
+ }
386
+ return this.getItemText(i).toLowerCase() === text.toLowerCase();
387
+ });
388
+ if (fullMatchingItem) {
389
+ return fullMatchingItem;
390
+ }
391
+ return allMatchingItems.firstOrDefault();
392
+ }
393
+ isDisabled(item) {
394
+ const disabledBy = this.disabledBy();
395
+ if (typeof disabledBy === "string") {
396
+ return item.data?.[disabledBy] ?? false;
397
+ }
398
+ return disabledBy(item.data);
399
+ }
400
+ isFilteringEnabled() {
401
+ const filterableOptions = this.filterableOptions();
402
+ return filterableOptions.enabled;
403
+ }
404
+ isHighlighted(item) {
405
+ const highlightedItem = this.highlightedItem();
406
+ return highlightedItem === item;
407
+ }
408
+ isSelected(item) {
409
+ const options = this.selectableOptions();
410
+ if (!options.enabled) {
411
+ return false;
412
+ }
413
+ const selectedKeys = this.selectedKeys();
414
+ const key = this.getSelectionKey(item);
415
+ return selectedKeys.contains(key);
416
+ }
417
+ navigate(direction, mode, focus) {
418
+ const navigableOptions = this.navigableOptions();
419
+ if (!navigableOptions.enabled) {
420
+ return null;
421
+ }
422
+ const viewItems = this.viewItems()
423
+ .where(i => !i.header && !this.isDisabled(i))
424
+ .toImmutableSet();
425
+ if (viewItems.isEmpty()) {
426
+ return null;
427
+ }
428
+ const selectableOptions = this.selectableOptions();
429
+ if (mode === "select" && (!selectableOptions.enabled || selectableOptions.mode === "multiple")) {
430
+ mode = "highlight";
431
+ }
432
+ let item;
433
+ if (selectableOptions.mode === "single") {
434
+ item = this.navigateForSingleSelection(viewItems, direction, mode);
435
+ }
436
+ else {
437
+ item = this.navigateForMultipleSelection(viewItems, direction);
438
+ }
439
+ if (item) {
440
+ this.scrollToItem$.next({ item, focus });
441
+ this.navigatedItem$.next(item);
442
+ }
443
+ return item;
444
+ }
445
+ notifySelectionChange(item) {
446
+ this.selectionChange$.next(item);
447
+ }
448
+ scrollToItem(item, focus) {
449
+ this.scrollToItem$.next({ item, focus });
450
+ }
451
+ selectItem(item, scroll = false, focus = false) {
452
+ const key = this.getSelectionKey(item);
453
+ const options = this.selectableOptions();
454
+ if (options.mode === "single") {
455
+ if (options.toggleable) {
456
+ this.selectedKeys.update(set => {
457
+ if (set.contains(key)) {
458
+ if (set.size() > 1) {
459
+ return set.where(k => k === key).toImmutableSet();
460
+ }
461
+ return set.remove(key);
462
+ }
463
+ return set.clear().add(key);
464
+ });
465
+ }
466
+ else {
467
+ this.selectedKeys.update(set => set.clear().add(key));
468
+ }
469
+ }
470
+ else {
471
+ this.selectedKeys.update(set => {
472
+ if (set.contains(key)) {
473
+ return set.remove(key);
474
+ }
475
+ return set.add(key);
476
+ });
477
+ }
478
+ if (scroll) {
479
+ this.scrollToItem(item, focus);
480
+ }
481
+ this.notifySelectionChange(item);
482
+ }
483
+ setData(data) {
484
+ this.#data.update(list => list.clear().addAll(data));
485
+ }
486
+ setDisabledBy(disabledBy) {
487
+ this.disabledBy.set(disabledBy);
488
+ }
489
+ setFilter(filter) {
490
+ this.filterText.set(filter);
491
+ }
492
+ setFilterPlaceholder(placeholder) {
493
+ this.filterPlaceholder.set(placeholder);
494
+ }
495
+ setFilterableOptions(options) {
496
+ this.filterableOptions.update(o => ({ ...o, ...options }));
497
+ }
498
+ setGroupBy(groupSelector) {
499
+ this.groupBy.set(groupSelector);
500
+ }
501
+ setGroupableOptions(options) {
502
+ this.groupableOptions.update(o => ({ ...o, ...options }));
503
+ }
504
+ setNavigableOptions(options) {
505
+ this.navigableOptions.update(o => ({ ...o, ...options }));
506
+ }
507
+ setPageableOptions(settings) {
508
+ this.pageableOptions.set(settings);
509
+ }
510
+ setSelectableOptions(options) {
511
+ this.selectableOptions.update(o => ({ ...o, ...options }));
512
+ }
513
+ setSelectedDataItems(dataItems) {
514
+ const valueField = this.valueField();
515
+ if (!valueField) {
516
+ this.selectedKeys.update(set => set.clear().addAll(dataItems));
517
+ }
518
+ else {
519
+ const selectedKeys = from(dataItems)
520
+ .select(item => this.getDataItemSelectionKey(item))
521
+ .toImmutableSet();
522
+ this.selectedKeys.update(set => set.clear().addAll(selectedKeys));
523
+ }
524
+ }
525
+ setSelectedKeys(selectedKeys) {
526
+ this.selectedKeys.update(set => set.clear().addAll(selectedKeys));
527
+ }
528
+ setTextField(textField) {
529
+ this.textField.set(textField);
530
+ }
531
+ setValueField(valueField) {
532
+ this.valueField.set(valueField);
533
+ }
534
+ setVirtualScrollOptions(options) {
535
+ this.virtualScrollOptions.update(o => ({ ...o, ...options }));
536
+ }
537
+ filterItem(item, filterText) {
538
+ if (filterText === "") {
539
+ return true;
540
+ }
541
+ const options = this.filterableOptions();
542
+ const itemText = this.getItemText(item);
543
+ const text = options.caseSensitive ? itemText : itemText.toLowerCase();
544
+ const filter = options.caseSensitive ? filterText : filterText.toLowerCase();
545
+ const operator = options.enabled ? options.operator : "startsWith";
546
+ if (typeof operator === "function") {
547
+ return operator(text, filter);
548
+ }
549
+ switch (operator) {
550
+ case "contains":
551
+ return text.includes(filter);
552
+ case "startsWith":
553
+ return text.startsWith(filter);
554
+ case "endsWith":
555
+ return text.endsWith(filter);
556
+ default:
557
+ return false;
558
+ }
559
+ }
560
+ getDataItemSelectionKey(dataItem) {
561
+ const valueField = this.valueField();
562
+ if (!valueField) {
563
+ return dataItem;
564
+ }
565
+ if (typeof valueField === "string") {
566
+ return dataItem?.[valueField] ?? dataItem;
567
+ }
568
+ return valueField(dataItem);
569
+ }
570
+ getOrderKey(item) {
571
+ const orderBy = this.groupableOptions().orderBy;
572
+ if (orderBy) {
573
+ if (typeof orderBy === "string") {
574
+ return item.data[orderBy];
575
+ }
576
+ else {
577
+ return orderBy(item.data);
578
+ }
579
+ }
580
+ return null;
581
+ }
582
+ getPreviousItemForNavigation(viewItems, navigationItem) {
583
+ let prevItem = viewItems.takeWhile(i => i !== navigationItem).lastOrDefault(i => !this.isDisabled(i));
584
+ if (prevItem == null) {
585
+ const lastItem = viewItems.lastOrDefault(i => !this.isDisabled(i));
586
+ if (this.navigableOptions().wrap) {
587
+ prevItem = lastItem;
588
+ }
589
+ else if (!this.navigableOptions().wrap) {
590
+ prevItem = navigationItem;
591
+ }
592
+ }
593
+ return prevItem;
594
+ }
595
+ getSelectionKey(item) {
596
+ return this.getDataItemSelectionKey(item.data);
597
+ }
598
+ navigateForMultipleSelection(viewItems, direction) {
599
+ const selectedKeys = this.selectedKeys();
600
+ const firstItem = viewItems.first();
601
+ if (selectedKeys.isEmpty() && !this.highlightedItem()) {
602
+ this.highlightedItem.set(firstItem);
603
+ return firstItem;
604
+ }
605
+ const firstSelectedItem = viewItems.firstOrDefault(i => selectedKeys.contains(this.getSelectionKey(i)));
606
+ const lastSelectedItem = viewItems.lastOrDefault(i => selectedKeys.contains(this.getSelectionKey(i)));
607
+ const lastHighlightedItem = this.highlightedItem();
608
+ if (direction === "next") {
609
+ const navigationItem = lastHighlightedItem ?? lastSelectedItem ?? firstItem;
610
+ let nextItem = viewItems
611
+ .skipWhile(i => i !== navigationItem)
612
+ .skip(1)
613
+ .firstOrDefault(i => !this.isDisabled(i));
614
+ if (nextItem == null) {
615
+ const firstItem = viewItems.firstOrDefault(i => !this.isDisabled(i));
616
+ if (this.navigableOptions().wrap) {
617
+ nextItem = firstItem;
618
+ }
619
+ else if (!this.navigableOptions().wrap) {
620
+ nextItem = navigationItem;
621
+ }
622
+ }
623
+ if (nextItem) {
624
+ this.highlightedItem.set(nextItem);
625
+ return nextItem;
626
+ }
627
+ }
628
+ else {
629
+ const navigationItem = lastHighlightedItem ?? firstSelectedItem ?? firstItem;
630
+ const prevItem = this.getPreviousItemForNavigation(viewItems, navigationItem);
631
+ if (prevItem) {
632
+ this.highlightedItem.set(prevItem);
633
+ return prevItem;
634
+ }
635
+ }
636
+ return null;
637
+ }
638
+ navigateFirstForSingleSelection(viewItems, mode) {
639
+ const firstItem = viewItems.first();
640
+ if (mode === "select") {
641
+ this.selectItem(firstItem);
642
+ this.highlightedItem.set(null);
643
+ }
644
+ else {
645
+ this.highlightedItem.set(firstItem);
646
+ }
647
+ return firstItem;
648
+ }
649
+ navigateForSingleSelection(viewItems, direction, mode) {
650
+ const selectedKeys = this.selectedKeys();
651
+ const firstItem = viewItems.first();
652
+ if (selectedKeys.isEmpty() && !this.highlightedItem()) {
653
+ if (mode === "select") {
654
+ this.selectItem(firstItem);
655
+ }
656
+ else {
657
+ this.highlightedItem.set(firstItem);
658
+ }
659
+ return firstItem;
660
+ }
661
+ else if (selectedKeys.isEmpty() && this.highlightedItem()) {
662
+ const highlightedItem = this.highlightedItem();
663
+ if (mode === "select") {
664
+ this.selectItem(highlightedItem);
665
+ return highlightedItem;
666
+ }
667
+ }
668
+ const selectedItem = viewItems.lastOrDefault(i => selectedKeys.contains(this.getSelectionKey(i)));
669
+ const lastHighlightedItem = this.highlightedItem();
670
+ const navigationItem = lastHighlightedItem ?? selectedItem ?? firstItem;
671
+ if (direction === "next") {
672
+ return this.navigateNextForSingleSelection(viewItems, navigationItem, mode, firstItem);
673
+ }
674
+ else if (direction === "previous") {
675
+ return this.navigatePreviousForSingleSelection(viewItems, navigationItem, mode);
676
+ }
677
+ else if (direction === "first") {
678
+ return this.navigateFirstForSingleSelection(viewItems, mode);
679
+ }
680
+ else if (direction === "last") {
681
+ return this.navigateLastForSingleSelection(viewItems, mode);
682
+ }
683
+ return null;
684
+ }
685
+ navigateLastForSingleSelection(viewItems, mode) {
686
+ const lastItem = viewItems.last();
687
+ if (mode === "select") {
688
+ this.selectItem(lastItem);
689
+ this.highlightedItem.set(null);
690
+ }
691
+ else {
692
+ this.highlightedItem.set(lastItem);
693
+ }
694
+ return lastItem;
695
+ }
696
+ navigateNextForSingleSelection(viewItems, navigationItem, mode, firstItem) {
697
+ let nextItem = viewItems
698
+ .skipWhile(i => i !== navigationItem)
699
+ .skip(1)
700
+ .firstOrDefault(i => !this.isDisabled(i));
701
+ if (nextItem == null) {
702
+ if (this.navigableOptions().wrap) {
703
+ nextItem = firstItem;
704
+ }
705
+ else if (!this.navigableOptions().wrap) {
706
+ nextItem = navigationItem;
707
+ }
708
+ }
709
+ if (nextItem) {
710
+ if (mode === "select") {
711
+ const previouslySelectedItem = this.selectedListItems().firstOrDefault();
712
+ if (previouslySelectedItem === nextItem) {
713
+ return null;
714
+ }
715
+ this.selectItem(nextItem);
716
+ this.highlightedItem.set(null);
717
+ }
718
+ else {
719
+ this.highlightedItem.set(nextItem);
720
+ }
721
+ return nextItem;
722
+ }
723
+ return null;
724
+ }
725
+ navigatePreviousForSingleSelection(viewItems, navigationItem, mode) {
726
+ const prevItem = this.getPreviousItemForNavigation(viewItems, navigationItem);
727
+ if (!prevItem) {
728
+ return null;
729
+ }
730
+ if (mode === "select") {
731
+ const previouslySelectedItem = this.selectedListItems().firstOrDefault();
732
+ if (previouslySelectedItem === prevItem) {
733
+ return null;
734
+ }
735
+ this.selectItem(prevItem);
736
+ this.highlightedItem.set(null);
737
+ }
738
+ else {
739
+ this.highlightedItem.set(prevItem);
740
+ }
741
+ return prevItem;
742
+ }
743
+ skipTakeWithGroups(items, skip, take) {
744
+ let skipped = 0;
745
+ let taken = 0;
746
+ let capturing = false;
747
+ const result = [];
748
+ for (const item of items) {
749
+ if (item.header) {
750
+ // Include group headers when we're capturing
751
+ if (capturing) {
752
+ result.push(item);
753
+ }
754
+ }
755
+ else {
756
+ // Handle regular items
757
+ if (!capturing && skipped < skip) {
758
+ skipped++;
759
+ continue;
760
+ }
761
+ if (taken < take) {
762
+ // Check if we need to include the group header for this item
763
+ if (!capturing && result.length === 0) {
764
+ // Find the group header for this item
765
+ const itemIndex = items.indexOf(item);
766
+ for (let i = itemIndex - 1; i >= 0; i--) {
767
+ if (items[i].header) {
768
+ result.push(items[i]);
769
+ break;
770
+ }
771
+ }
772
+ }
773
+ capturing = true;
774
+ result.push(item);
775
+ taken++;
776
+ }
777
+ else {
778
+ break;
779
+ }
780
+ }
781
+ }
782
+ // Remove trailing group headers if they are at the end
783
+ let lastIndex = result.length - 1;
784
+ while (lastIndex >= 0 && result[lastIndex].header) {
785
+ result.pop();
786
+ lastIndex--;
787
+ }
788
+ return result;
789
+ }
790
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
791
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListService }); }
792
+ }
793
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListService, decorators: [{
794
+ type: Injectable
795
+ }] });
796
+
797
+ class ListItemDirective {
798
+ #listService;
799
+ constructor() {
800
+ this.#listService = inject((ListService));
801
+ this.disabled = computed(() => this.#listService.isDisabled(this.item()), /* @ts-ignore */
802
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
803
+ this.highlighted = computed(() => this.#listService.isHighlighted(this.item()), /* @ts-ignore */
804
+ ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
805
+ this.position = computed(() => {
806
+ const positionInfo = this.#listService.getItemPosition(this.item());
807
+ return positionInfo?.position ?? null;
808
+ }, /* @ts-ignore */
809
+ ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
810
+ this.rovingTabIndex = computed(() => (this.#listService.focusableItem() === this.item() ? 0 : -1), /* @ts-ignore */
811
+ ...(ngDevMode ? [{ debugName: "rovingTabIndex" }] : /* istanbul ignore next */ []));
812
+ this.selected = computed(() => this.#listService.isSelected(this.item()), /* @ts-ignore */
813
+ ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
814
+ this.setSize = computed(() => {
815
+ const positionInfo = this.#listService.getItemPosition(this.item());
816
+ return positionInfo?.total ?? null;
817
+ }, /* @ts-ignore */
818
+ ...(ngDevMode ? [{ debugName: "setSize" }] : /* istanbul ignore next */ []));
819
+ this.textClasses = computed(() => {
820
+ const disabled = this.disabled();
821
+ const highlighted = this.highlighted();
822
+ const selected = this.selected();
823
+ const checkboxes = this.#listService.selectableOptions().checkboxes;
824
+ const classes = listItemContentVariants({ disabled, highlighted, selected, checkboxes });
825
+ return twMerge(classes);
826
+ }, /* @ts-ignore */
827
+ ...(ngDevMode ? [{ debugName: "textClasses" }] : /* istanbul ignore next */ []));
828
+ this.item = input.required(/* @ts-ignore */
829
+ ...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
830
+ fromEvent(inject((ElementRef)).nativeElement, "focusout")
831
+ .pipe(takeUntilDestroyed())
832
+ .subscribe(() => this.#listService.itemFocusOut$.next(this.item()));
833
+ }
834
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
835
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.6", type: ListItemDirective, isStandalone: true, selector: "li[monaListItem]", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "attr.aria-current": "highlighted()", "attr.aria-disabled": "disabled()", "attr.aria-posinset": "position()", "attr.aria-selected": "selected()", "attr.aria-setsize": "setSize()", "attr.data-disabled": "disabled()", "attr.data-highlighted": "highlighted()", "attr.data-selected": "selected()", "attr.role": "'option'", "attr.tabindex": "rovingTabIndex()", "class": "textClasses()" } }, ngImport: i0 }); }
836
+ }
837
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListItemDirective, decorators: [{
838
+ type: Directive,
839
+ args: [{
840
+ selector: "li[monaListItem]",
841
+ standalone: true,
842
+ host: {
843
+ "[attr.aria-current]": "highlighted()",
844
+ "[attr.aria-disabled]": "disabled()",
845
+ "[attr.aria-posinset]": "position()",
846
+ "[attr.aria-selected]": "selected()",
847
+ "[attr.aria-setsize]": "setSize()",
848
+ "[attr.data-disabled]": "disabled()",
849
+ "[attr.data-highlighted]": "highlighted()",
850
+ "[attr.data-selected]": "selected()",
851
+ "[attr.role]": "'option'",
852
+ "[attr.tabindex]": "rovingTabIndex()",
853
+ "[class]": "textClasses()"
854
+ }
855
+ }]
856
+ }], ctorParameters: () => [], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }] } });
857
+
858
+ class ListNoDataTemplateDirective {
859
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListNoDataTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
860
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.6", type: ListNoDataTemplateDirective, isStandalone: true, selector: "ng-template[monaListNoDataTemplate]", ngImport: i0 }); }
861
+ }
862
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListNoDataTemplateDirective, decorators: [{
863
+ type: Directive,
864
+ args: [{
865
+ selector: "ng-template[monaListNoDataTemplate]",
866
+ standalone: true
867
+ }]
868
+ }] });
869
+
870
+ const getListNavigationDirection = (key) => {
871
+ switch (key) {
872
+ case "ArrowDown":
873
+ case "Down":
874
+ return "next";
875
+ case "ArrowUp":
876
+ case "Up":
877
+ return "previous";
878
+ case "Home":
879
+ return "first";
880
+ case "End":
881
+ return "last";
882
+ case "PageUp":
883
+ return "pageup";
884
+ case "PageDown":
885
+ return "pagedown";
886
+ default:
887
+ return null;
888
+ }
889
+ };
890
+
891
+ class ListItemComponent {
892
+ constructor() {
893
+ this.baseClass = computed(() => {
894
+ const isHeader = this.isHeader();
895
+ if (isHeader) {
896
+ return ``;
897
+ }
898
+ return listItemBaseVariants();
899
+ }, /* @ts-ignore */
900
+ ...(ngDevMode ? [{ debugName: "baseClass" }] : /* istanbul ignore next */ []));
901
+ this.checkboxes = computed(() => {
902
+ return this.listService.selectableOptions().checkboxes && !this.isHeader();
903
+ }, /* @ts-ignore */
904
+ ...(ngDevMode ? [{ debugName: "checkboxes" }] : /* istanbul ignore next */ []));
905
+ this.dataItem = computed(() => this.item()?.data ?? null, /* @ts-ignore */
906
+ ...(ngDevMode ? [{ debugName: "dataItem" }] : /* istanbul ignore next */ []));
907
+ this.itemChecked = computed(() => this.listService.isSelected(this.item()), /* @ts-ignore */
908
+ ...(ngDevMode ? [{ debugName: "itemChecked" }] : /* istanbul ignore next */ []));
909
+ this.itemText = computed(() => {
910
+ const item = this.item();
911
+ if (item == null) {
912
+ return "";
913
+ }
914
+ if (item.header) {
915
+ return item.header;
916
+ }
917
+ return this.listService.getItemText(item);
918
+ }, /* @ts-ignore */
919
+ ...(ngDevMode ? [{ debugName: "itemText" }] : /* istanbul ignore next */ []));
920
+ this.isHeader = computed(() => this.item()?.header ?? false, /* @ts-ignore */
921
+ ...(ngDevMode ? [{ debugName: "isHeader" }] : /* istanbul ignore next */ []));
922
+ this.listService = inject(ListService);
923
+ this.textClasses = computed(() => {
924
+ const isHeader = this.isHeader();
925
+ if (isHeader) {
926
+ const hasTemplate = this.template() != null;
927
+ const classes = listGroupHeaderTextVariants({ hasTemplate });
928
+ return twMerge(classes);
929
+ }
930
+ return ``; // TODO
931
+ }, /* @ts-ignore */
932
+ ...(ngDevMode ? [{ debugName: "textClasses" }] : /* istanbul ignore next */ []));
933
+ this.checked = output();
934
+ this.item = input.required(/* @ts-ignore */
935
+ ...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
936
+ this.template = input(/* @ts-ignore */
937
+ ...(ngDevMode ? [undefined, { debugName: "template" }] : /* istanbul ignore next */ []));
938
+ }
939
+ onCheckboxChange(checked) {
940
+ this.checked.emit(checked);
941
+ }
942
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
943
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: ListItemComponent, isStandalone: true, selector: "mona-list-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, template: { classPropertyName: "template", publicName: "template", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checked" }, host: { properties: { "class": "baseClass()" } }, ngImport: i0, template: "@if (checkboxes()) {\n <input\n type=\"checkbox\"\n [ngModel]=\"itemChecked()\"\n monaCheckbox\n class=\"aspect-square\"\n (click)=\"$event.stopPropagation()\"\n (ngModelChange)=\"onCheckboxChange($event)\"\n (change)=\"$event.preventDefault()\" />\n}\n\n@if (template()) {\n <ng-container [ngTemplateOutlet]=\"template()\" [ngTemplateOutletContext]=\"{ $implicit: dataItem() }\"></ng-container>\n} @else {\n <span [class]=\"textClasses()\">{{ itemText() }}</span>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: CheckboxDirective, selector: "input[type='checkbox'][monaCheckbox]", inputs: ["rounded", "class"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox]:not([ngNoCva])[formControlName],input[type=checkbox]:not([ngNoCva])[formControl],input[type=checkbox]:not([ngNoCva])[ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
944
+ }
945
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListItemComponent, decorators: [{
946
+ type: Component,
947
+ args: [{ selector: "mona-list-item", imports: [NgTemplateOutlet, CheckboxDirective, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, host: {
948
+ "[class]": "baseClass()"
949
+ }, template: "@if (checkboxes()) {\n <input\n type=\"checkbox\"\n [ngModel]=\"itemChecked()\"\n monaCheckbox\n class=\"aspect-square\"\n (click)=\"$event.stopPropagation()\"\n (ngModelChange)=\"onCheckboxChange($event)\"\n (change)=\"$event.preventDefault()\" />\n}\n\n@if (template()) {\n <ng-container [ngTemplateOutlet]=\"template()\" [ngTemplateOutletContext]=\"{ $implicit: dataItem() }\"></ng-container>\n} @else {\n <span [class]=\"textClasses()\">{{ itemText() }}</span>\n}\n" }]
950
+ }], propDecorators: { checked: [{ type: i0.Output, args: ["checked"] }], item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], template: [{ type: i0.Input, args: [{ isSignal: true, alias: "template", required: false }] }] } });
951
+
952
+ class ListComponent {
953
+ #destroyRef;
954
+ #hostElementRef;
955
+ #typeaheadKey$;
956
+ constructor() {
957
+ this.#destroyRef = inject(DestroyRef);
958
+ this.#hostElementRef = inject(ElementRef);
959
+ this.#typeaheadKey$ = new Subject();
960
+ this.filterInput = viewChild(FilterInputComponent, /* @ts-ignore */
961
+ ...(ngDevMode ? [{ debugName: "filterInput" }] : /* istanbul ignore next */ []));
962
+ this.classes = computed(() => {
963
+ const classes = listVariants();
964
+ return twMerge(classes);
965
+ }, /* @ts-ignore */
966
+ ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
967
+ this.footerTemplate = contentChild(ListFooterTemplateDirective, { ...(ngDevMode ? { debugName: "footerTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
968
+ this.groupHeaderClasses = computed(() => {
969
+ const listItemClass = this.listItemClass();
970
+ const hasTemplate = this.groupHeaderTemplate() != null;
971
+ const classes = listGroupHeaderVariants({ hasTemplate });
972
+ return twMerge(classes, listItemClass);
973
+ }, /* @ts-ignore */
974
+ ...(ngDevMode ? [{ debugName: "groupHeaderClasses" }] : /* istanbul ignore next */ []));
975
+ this.groupHeaderTemplate = contentChild(ListGroupHeaderTemplateDirective, { ...(ngDevMode ? { debugName: "groupHeaderTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
976
+ this.headerTemplate = contentChild(ListHeaderTemplateDirective, { ...(ngDevMode ? { debugName: "headerTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
977
+ this.hostTabIndex = computed(() => (this.listService.focusableItem() ? -1 : 0), /* @ts-ignore */
978
+ ...(ngDevMode ? [{ debugName: "hostTabIndex" }] : /* istanbul ignore next */ []));
979
+ this.itemTemplate = contentChild(ListItemTemplateDirective, { ...(ngDevMode ? { debugName: "itemTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
980
+ this.innerListClasses = computed(() => {
981
+ const classes = listInnerListVariants();
982
+ const listClass = this.listClass();
983
+ return twMerge(classes, listClass);
984
+ }, /* @ts-ignore */
985
+ ...(ngDevMode ? [{ debugName: "innerListClasses" }] : /* istanbul ignore next */ []));
986
+ this.listHeight = computed(() => {
987
+ const height = this.height();
988
+ if (height == null) {
989
+ return undefined;
990
+ }
991
+ if (typeof height === "number") {
992
+ return `${height}px`;
993
+ }
994
+ return height;
995
+ }, /* @ts-ignore */
996
+ ...(ngDevMode ? [{ debugName: "listHeight" }] : /* istanbul ignore next */ []));
997
+ this.listMaxHeight = computed(() => {
998
+ const maxHeight = this.maxHeight();
999
+ if (maxHeight == null) {
1000
+ return undefined;
1001
+ }
1002
+ if (typeof maxHeight === "number") {
1003
+ return `${maxHeight}px`;
1004
+ }
1005
+ return maxHeight;
1006
+ }, /* @ts-ignore */
1007
+ ...(ngDevMode ? [{ debugName: "listMaxHeight" }] : /* istanbul ignore next */ []));
1008
+ this.listMaxWidth = computed(() => {
1009
+ const maxWidth = this.maxWidth();
1010
+ if (maxWidth == null) {
1011
+ return undefined;
1012
+ }
1013
+ if (typeof maxWidth === "number") {
1014
+ return `${maxWidth}px`;
1015
+ }
1016
+ return maxWidth;
1017
+ }, /* @ts-ignore */
1018
+ ...(ngDevMode ? [{ debugName: "listMaxWidth" }] : /* istanbul ignore next */ []));
1019
+ this.listService = inject(ListService);
1020
+ this.listWidth = computed(() => {
1021
+ const width = this.width();
1022
+ if (width == null) {
1023
+ return undefined;
1024
+ }
1025
+ if (typeof width === "number") {
1026
+ return `${width}px`;
1027
+ }
1028
+ return width;
1029
+ }, /* @ts-ignore */
1030
+ ...(ngDevMode ? [{ debugName: "listWidth" }] : /* istanbul ignore next */ []));
1031
+ this.noDataTemplate = contentChild(ListNoDataTemplateDirective, { ...(ngDevMode ? { debugName: "noDataTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
1032
+ this.viewportHeight = computed(() => {
1033
+ const listHeight = this.listHeight();
1034
+ if (listHeight) {
1035
+ return listHeight;
1036
+ }
1037
+ const items = this.listService.viewItems().size();
1038
+ const headerItems = this.listService
1039
+ .viewItems()
1040
+ .where(i => !!i.header)
1041
+ .count();
1042
+ const itemHeight = this.listService.virtualScrollOptions().height ?? 28;
1043
+ const height = items * itemHeight + headerItems * 2;
1044
+ return `${height}px`;
1045
+ }, /* @ts-ignore */
1046
+ ...(ngDevMode ? [{ debugName: "viewportHeight" }] : /* istanbul ignore next */ []));
1047
+ this.virtualScrollViewport = viewChild(CdkVirtualScrollViewport, /* @ts-ignore */
1048
+ ...(ngDevMode ? [{ debugName: "virtualScrollViewport" }] : /* istanbul ignore next */ []));
1049
+ /**
1050
+ * @description Accessible name for the list's `listbox` element. Describe what the list represents.
1051
+ * @default ""
1052
+ */
1053
+ this.ariaLabel = input("", /* @ts-ignore */
1054
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
1055
+ this.data = input(null, /* @ts-ignore */
1056
+ ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
1057
+ this.focusOnMount = input(true, /* @ts-ignore */
1058
+ ...(ngDevMode ? [{ debugName: "focusOnMount" }] : /* istanbul ignore next */ []));
1059
+ this.height = input(undefined, /* @ts-ignore */
1060
+ ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
1061
+ this.itemSelect = output();
1062
+ this.listClass = input("", /* @ts-ignore */
1063
+ ...(ngDevMode ? [{ debugName: "listClass" }] : /* istanbul ignore next */ []));
1064
+ this.listId = input("", /* @ts-ignore */
1065
+ ...(ngDevMode ? [{ debugName: "listId" }] : /* istanbul ignore next */ []));
1066
+ this.listItemClass = input("", /* @ts-ignore */
1067
+ ...(ngDevMode ? [{ debugName: "listItemClass" }] : /* istanbul ignore next */ []));
1068
+ this.listItemStyle = input({}, /* @ts-ignore */
1069
+ ...(ngDevMode ? [{ debugName: "listItemStyle" }] : /* istanbul ignore next */ []));
1070
+ this.listStyle = input({}, /* @ts-ignore */
1071
+ ...(ngDevMode ? [{ debugName: "listStyle" }] : /* istanbul ignore next */ []));
1072
+ this.maxHeight = input(/* @ts-ignore */
1073
+ ...(ngDevMode ? [undefined, { debugName: "maxHeight" }] : /* istanbul ignore next */ []));
1074
+ this.maxWidth = input(/* @ts-ignore */
1075
+ ...(ngDevMode ? [undefined, { debugName: "maxWidth" }] : /* istanbul ignore next */ []));
1076
+ this.size = input("medium", /* @ts-ignore */
1077
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ [])); // TODO: Update this to a cva variable when list styles are added
1078
+ this.textField = input(null, /* @ts-ignore */
1079
+ ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
1080
+ this.width = input(/* @ts-ignore */
1081
+ ...(ngDevMode ? [undefined, { debugName: "width" }] : /* istanbul ignore next */ []));
1082
+ effect(() => {
1083
+ const textField = this.textField();
1084
+ untracked(() => {
1085
+ if (textField != null) {
1086
+ this.listService.setTextField(textField);
1087
+ }
1088
+ });
1089
+ });
1090
+ effect(() => {
1091
+ const data = this.data();
1092
+ untracked(() => {
1093
+ if (data != null) {
1094
+ this.listService.setData(data);
1095
+ }
1096
+ });
1097
+ });
1098
+ afterNextRender({
1099
+ read: () => this.setInitialSelectionOrFocus()
1100
+ });
1101
+ }
1102
+ ngOnInit() {
1103
+ this.setSubscriptions();
1104
+ }
1105
+ onFilterChange(event) {
1106
+ this.listService.filterChange$.next(event);
1107
+ if (!event.isDefaultPrevented()) {
1108
+ this.listService.setFilter(event.filter);
1109
+ }
1110
+ }
1111
+ onListItemCheck(item) {
1112
+ this.toggleItem(item);
1113
+ }
1114
+ onListItemClick(item) {
1115
+ this.toggleItem(item);
1116
+ }
1117
+ cycleThroughMatchedItems(buffer) {
1118
+ const nextItem = cycleThroughMatchedItems(this.listService.viewItems(), this.listService.highlightedItem(), item => {
1119
+ const text = this.listService.getItemText(item);
1120
+ return text.toLowerCase().startsWith(buffer.toLowerCase());
1121
+ });
1122
+ if (nextItem) {
1123
+ const navigationMode = this.listService.navigableOptions().mode;
1124
+ this.listService.highlightedItem.set(nextItem);
1125
+ if (navigationMode === "select") {
1126
+ this.selectItem(nextItem);
1127
+ }
1128
+ this.scrollToItem(nextItem, true, "instant");
1129
+ }
1130
+ }
1131
+ focusToItem(item) {
1132
+ if (this.listService.navigableOptions().enabled) {
1133
+ this.listService.highlightedItem.set(item);
1134
+ }
1135
+ this.scrollToItem(item, true);
1136
+ }
1137
+ handleNavigation(key) {
1138
+ const direction = getListNavigationDirection(key);
1139
+ if (!direction) {
1140
+ return;
1141
+ }
1142
+ if (direction === "pageup" || direction === "pagedown") {
1143
+ this.handlePageScroll(direction);
1144
+ return;
1145
+ }
1146
+ const navigableOptions = this.listService.navigableOptions();
1147
+ const selectableOptions = this.listService.selectableOptions();
1148
+ const previousSelectedItems = this.listService.selectedListItems();
1149
+ const item = this.listService.navigate(direction, navigableOptions.mode, true);
1150
+ if (item && navigableOptions.mode === "select" && selectableOptions.enabled) {
1151
+ this.itemSelect.emit({ item, source: { via: "keyboard", key } });
1152
+ if (previousSelectedItems.contains(item)) {
1153
+ return;
1154
+ }
1155
+ this.listService.selectedKeysChange$.next(this.listService.selectedKeys().toArray());
1156
+ }
1157
+ const filterInput = this.filterInput();
1158
+ if (filterInput) {
1159
+ filterInput.focus();
1160
+ }
1161
+ }
1162
+ handlePageScroll(direction) {
1163
+ const listElement = this.#hostElementRef.nativeElement.firstElementChild;
1164
+ switch (direction) {
1165
+ case "pagedown": {
1166
+ const virtualScrollViewport = this.virtualScrollViewport();
1167
+ if (virtualScrollViewport) {
1168
+ const scrollOffset = virtualScrollViewport.measureScrollOffset();
1169
+ virtualScrollViewport.scrollToOffset(scrollOffset + virtualScrollViewport.getViewportSize(), "smooth");
1170
+ }
1171
+ else {
1172
+ const top = listElement.scrollTop + listElement.clientHeight * 0.8;
1173
+ listElement.scrollTo({ top, behavior: "smooth" });
1174
+ }
1175
+ break;
1176
+ }
1177
+ case "pageup": {
1178
+ const virtualScrollViewport = this.virtualScrollViewport();
1179
+ if (virtualScrollViewport) {
1180
+ const scrollOffset = virtualScrollViewport.measureScrollOffset();
1181
+ virtualScrollViewport.scrollToOffset(scrollOffset - virtualScrollViewport.getViewportSize(), "smooth");
1182
+ }
1183
+ else {
1184
+ const top = listElement.scrollTop - listElement.clientHeight * 0.8;
1185
+ listElement.scrollTo({ top, behavior: "smooth" });
1186
+ }
1187
+ break;
1188
+ }
1189
+ }
1190
+ }
1191
+ scrollToItem(item, focus, behavior = "auto") {
1192
+ const element = this.#hostElementRef.nativeElement.querySelector(`[data-uid="${item.uid}"]`);
1193
+ if (element) {
1194
+ element.scrollIntoView({ block: "center", behavior });
1195
+ if (focus) {
1196
+ element.focus();
1197
+ }
1198
+ }
1199
+ else if (this.listService.virtualScrollOptions().enabled) {
1200
+ const index = this.listService.viewItems().toList().indexOf(item);
1201
+ const itemHeight = this.listService.virtualScrollOptions().height ?? 28;
1202
+ const rect = this.#hostElementRef.nativeElement.getBoundingClientRect();
1203
+ const offset = itemHeight * index - rect.height / 2;
1204
+ asyncScheduler.schedule(() => {
1205
+ this.virtualScrollViewport()?.scrollToOffset(offset, behavior);
1206
+ const scrolledElement = this.#hostElementRef.nativeElement.querySelector(`[data-uid="${item.uid}"]`);
1207
+ if (scrolledElement && focus) {
1208
+ scrolledElement.focus();
1209
+ }
1210
+ });
1211
+ }
1212
+ }
1213
+ selectItem(item) {
1214
+ const selectedItems = this.listService.selectedListItems();
1215
+ const options = this.listService.selectableOptions();
1216
+ if (!options.enabled) {
1217
+ return;
1218
+ }
1219
+ if ((options.mode === "single" && !selectedItems.contains(item)) ||
1220
+ (options.mode === "single" && options.toggleable) ||
1221
+ options.mode === "multiple" ||
1222
+ (options.mode === "single" && selectedItems.size() > 1)) {
1223
+ this.listService.selectItem(item);
1224
+ this.listService.highlightedItem.set(item);
1225
+ this.listService.selectedKeysChange$.next(this.listService.selectedKeys().toArray());
1226
+ }
1227
+ }
1228
+ setInitialSelectionOrFocus() {
1229
+ if (!this.focusOnMount()) {
1230
+ return;
1231
+ }
1232
+ const selectedItem = this.listService.selectedListItems().lastOrDefault();
1233
+ if (selectedItem) {
1234
+ this.focusToItem(selectedItem);
1235
+ return;
1236
+ }
1237
+ const firstItem = this.listService
1238
+ .viewItems()
1239
+ .where(i => !i.header && !this.listService.isDisabled(i))
1240
+ .firstOrDefault();
1241
+ if (firstItem) {
1242
+ this.focusToItem(firstItem);
1243
+ }
1244
+ }
1245
+ setKeyboardEvents() {
1246
+ fromEvent(this.#hostElementRef.nativeElement, "keydown")
1247
+ .pipe(takeUntilDestroyed(this.#destroyRef), filter(event => event.key === "Enter" || event.key === "NumPadEnter"))
1248
+ .subscribe((event) => {
1249
+ const highlightedItem = this.listService.highlightedItem();
1250
+ const selectedItem = this.listService.selectedListItems().firstOrDefault();
1251
+ const source = { via: "keyboard", key: event.key };
1252
+ if (highlightedItem) {
1253
+ this.selectItem(highlightedItem);
1254
+ this.itemSelect.emit({ item: highlightedItem, source });
1255
+ }
1256
+ else if (selectedItem) {
1257
+ this.selectItem(selectedItem);
1258
+ this.itemSelect.emit({ item: selectedItem, source });
1259
+ }
1260
+ });
1261
+ }
1262
+ setNavigationEvents() {
1263
+ fromEvent(this.#hostElementRef.nativeElement, "keydown")
1264
+ .pipe(takeUntilDestroyed(this.#destroyRef), filter(event => event.key !== "Tab"), filter(() => this.listService.navigableOptions().enabled), tap(event => {
1265
+ const navigableOptions = this.listService.navigableOptions();
1266
+ if (navigableOptions.enabled) {
1267
+ event.preventDefault();
1268
+ }
1269
+ }))
1270
+ .subscribe(event => {
1271
+ if (isTypeaheadKey(event.key)) {
1272
+ event.preventDefault();
1273
+ this.#typeaheadKey$.next(event.key);
1274
+ return;
1275
+ }
1276
+ this.#typeaheadKey$.next("");
1277
+ this.handleNavigation(event.key);
1278
+ });
1279
+ }
1280
+ setSubscriptions() {
1281
+ this.setNavigationEvents();
1282
+ this.setKeyboardEvents();
1283
+ this.setTypeaheadSubscription();
1284
+ this.listService.scrollToItem$
1285
+ .pipe(takeUntilDestroyed(this.#destroyRef))
1286
+ .subscribe(event => this.scrollToItem(event.item, event.focus));
1287
+ this.listService.focus$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(() => {
1288
+ this.#hostElementRef.nativeElement.focus();
1289
+ this.setInitialSelectionOrFocus();
1290
+ });
1291
+ fromEvent(this.#hostElementRef.nativeElement, "focus")
1292
+ .pipe(takeUntilDestroyed(this.#destroyRef))
1293
+ .subscribe(event => {
1294
+ const previous = event.relatedTarget;
1295
+ if (previous && this.#hostElementRef.nativeElement.contains(previous)) {
1296
+ return;
1297
+ }
1298
+ this.setInitialSelectionOrFocus();
1299
+ });
1300
+ fromEvent(this.#hostElementRef.nativeElement, "focusout")
1301
+ .pipe(takeUntilDestroyed(this.#destroyRef))
1302
+ .subscribe(event => {
1303
+ const next = event.relatedTarget;
1304
+ if (next && this.#hostElementRef.nativeElement.contains(next)) {
1305
+ return;
1306
+ }
1307
+ this.listService.highlightedItem.set(null);
1308
+ });
1309
+ }
1310
+ setTypeaheadSubscription() {
1311
+ setupTypeahead(this.#typeaheadKey$)
1312
+ .pipe(takeUntilDestroyed(this.#destroyRef))
1313
+ .subscribe(buffer => this.cycleThroughMatchedItems(buffer));
1314
+ }
1315
+ toggleItem(item) {
1316
+ this.listService.highlightedItem.set(item);
1317
+ if (!this.listService.selectableOptions().enabled) {
1318
+ return;
1319
+ }
1320
+ this.selectItem(item);
1321
+ this.itemSelect.emit({ item, source: { via: "mouse" } });
1322
+ }
1323
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1324
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: ListComponent, isStandalone: true, selector: "mona-list", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, focusOnMount: { classPropertyName: "focusOnMount", publicName: "focusOnMount", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, listClass: { classPropertyName: "listClass", publicName: "listClass", isSignal: true, isRequired: false, transformFunction: null }, listId: { classPropertyName: "listId", publicName: "listId", isSignal: true, isRequired: false, transformFunction: null }, listItemClass: { classPropertyName: "listItemClass", publicName: "listItemClass", isSignal: true, isRequired: false, transformFunction: null }, listItemStyle: { classPropertyName: "listItemStyle", publicName: "listItemStyle", isSignal: true, isRequired: false, transformFunction: null }, listStyle: { classPropertyName: "listStyle", publicName: "listStyle", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect" }, host: { properties: { "attr.tabindex": "hostTabIndex()", "class": "classes()", "style.height": "listHeight()", "style.max-height": "listMaxHeight()", "style.max-width": "listMaxWidth()", "style.width": "listWidth()" } }, queries: [{ propertyName: "footerTemplate", first: true, predicate: ListFooterTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "groupHeaderTemplate", first: true, predicate: ListGroupHeaderTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "headerTemplate", first: true, predicate: ListHeaderTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "itemTemplate", first: true, predicate: ListItemTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "noDataTemplate", first: true, predicate: ListNoDataTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }], viewQueries: [{ propertyName: "filterInput", first: true, predicate: FilterInputComponent, descendants: true, isSignal: true }, { propertyName: "virtualScrollViewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], ngImport: i0, template: "@if (headerTemplate()) {\n <ng-container [ngTemplateOutlet]=\"headerTemplate()\"></ng-container>\n}\n@if (listService.filterableOptions().enabled && listService.filterInputVisible()) {\n <div class=\"p-2\">\n <mona-filter-input\n [filter]=\"listService.filterText()\"\n [debounce]=\"listService.filterableOptions().debounce\"\n [placeholder]=\"listService.filterPlaceholder()\"\n [size]=\"size()\"\n (filterChange)=\"onFilterChange($event)\"></mona-filter-input>\n </div>\n}\n@if (listService.virtualScrollOptions().enabled) {\n @if (listService.viewItems().length !== 0) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"listService.virtualScrollOptions().height\"\n [style.height]=\"viewportHeight()\">\n <ul\n [class]=\"innerListClasses()\"\n [style]=\"listStyle()\"\n [tabIndex]=\"-1\"\n [id]=\"listId()\"\n role=\"listbox\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"listService.selectableOptions().mode === 'multiple' || null\">\n <ng-container *cdkVirtualFor=\"let item of listService.viewItems()\">\n <ng-container\n [ngTemplateOutlet]=\"listItemTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n </ng-container>\n </ul>\n </cdk-virtual-scroll-viewport>\n } @else if (noDataTemplate()) {\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()\"></ng-container>\n } @else {\n <mona-placeholder text=\"No data\" class=\"w-full h-full flex items-center justify-center\"></mona-placeholder>\n }\n} @else {\n @if (listService.viewItems().length !== 0) {\n <ul\n [class]=\"innerListClasses()\"\n [style]=\"listStyle()\"\n [tabIndex]=\"-1\"\n [id]=\"listId()\"\n role=\"listbox\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"listService.selectableOptions().mode === 'multiple' || null\">\n @for (item of listService.viewItems(); track item.uid) {\n <ng-container\n [ngTemplateOutlet]=\"listItemTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n }\n </ul>\n } @else if (noDataTemplate()) {\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()\"></ng-container>\n } @else {\n <mona-placeholder text=\"No data\" class=\"w-full h-full flex items-center justify-center\"></mona-placeholder>\n }\n}\n@if (footerTemplate()) {\n <ng-container [ngTemplateOutlet]=\"footerTemplate()\"></ng-container>\n}\n\n<ng-template #listItemTemplate let-item>\n @if (item.header) {\n <li [class]=\"groupHeaderClasses()\" [style]=\"listItemStyle()\">\n <mona-list-item [item]=\"item\" [template]=\"groupHeaderTemplate()\"></mona-list-item>\n </li>\n } @else {\n <li\n [class]=\"listItemClass()\"\n [class.px-0.5]=\"true\"\n [style]=\"listItemStyle()\"\n [id]=\"item.uid\"\n [attr.data-uid]=\"item.uid\"\n (click)=\"onListItemClick(item)\"\n monaListItem\n [item]=\"item\">\n <mona-list-item\n [item]=\"item\"\n [template]=\"itemTemplate()\"\n (checked)=\"onListItemCheck(item)\"></mona-list-item>\n </li>\n }\n</ng-template>\n", dependencies: [{ kind: "component", type: FilterInputComponent, selector: "mona-filter-input", inputs: ["debounce", "filter", "placeholder", "size"], outputs: ["filterChange", "inputBlur", "inputFocus"] }, { kind: "component", type: ListItemComponent, selector: "mona-list-item", inputs: ["item", "template"], outputs: ["checked"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: ListItemDirective, selector: "li[monaListItem]", inputs: ["item"] }, { kind: "component", type: PlaceholderComponent, selector: "mona-placeholder", inputs: ["text", "class"] }, { 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"] }] }); }
1325
+ }
1326
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: ListComponent, decorators: [{
1327
+ type: Component,
1328
+ args: [{ selector: "mona-list", imports: [
1329
+ FilterInputComponent,
1330
+ ListItemComponent,
1331
+ NgTemplateOutlet,
1332
+ ListItemDirective,
1333
+ PlaceholderComponent,
1334
+ CdkVirtualScrollViewport,
1335
+ CdkFixedSizeVirtualScroll,
1336
+ CdkVirtualForOf
1337
+ ], host: {
1338
+ "[attr.tabindex]": "hostTabIndex()",
1339
+ "[class]": "classes()",
1340
+ "[style.height]": "listHeight()",
1341
+ "[style.max-height]": "listMaxHeight()",
1342
+ "[style.max-width]": "listMaxWidth()",
1343
+ "[style.width]": "listWidth()"
1344
+ }, template: "@if (headerTemplate()) {\n <ng-container [ngTemplateOutlet]=\"headerTemplate()\"></ng-container>\n}\n@if (listService.filterableOptions().enabled && listService.filterInputVisible()) {\n <div class=\"p-2\">\n <mona-filter-input\n [filter]=\"listService.filterText()\"\n [debounce]=\"listService.filterableOptions().debounce\"\n [placeholder]=\"listService.filterPlaceholder()\"\n [size]=\"size()\"\n (filterChange)=\"onFilterChange($event)\"></mona-filter-input>\n </div>\n}\n@if (listService.virtualScrollOptions().enabled) {\n @if (listService.viewItems().length !== 0) {\n <cdk-virtual-scroll-viewport\n [itemSize]=\"listService.virtualScrollOptions().height\"\n [style.height]=\"viewportHeight()\">\n <ul\n [class]=\"innerListClasses()\"\n [style]=\"listStyle()\"\n [tabIndex]=\"-1\"\n [id]=\"listId()\"\n role=\"listbox\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"listService.selectableOptions().mode === 'multiple' || null\">\n <ng-container *cdkVirtualFor=\"let item of listService.viewItems()\">\n <ng-container\n [ngTemplateOutlet]=\"listItemTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n </ng-container>\n </ul>\n </cdk-virtual-scroll-viewport>\n } @else if (noDataTemplate()) {\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()\"></ng-container>\n } @else {\n <mona-placeholder text=\"No data\" class=\"w-full h-full flex items-center justify-center\"></mona-placeholder>\n }\n} @else {\n @if (listService.viewItems().length !== 0) {\n <ul\n [class]=\"innerListClasses()\"\n [style]=\"listStyle()\"\n [tabIndex]=\"-1\"\n [id]=\"listId()\"\n role=\"listbox\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"listService.selectableOptions().mode === 'multiple' || null\">\n @for (item of listService.viewItems(); track item.uid) {\n <ng-container\n [ngTemplateOutlet]=\"listItemTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"></ng-container>\n }\n </ul>\n } @else if (noDataTemplate()) {\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()\"></ng-container>\n } @else {\n <mona-placeholder text=\"No data\" class=\"w-full h-full flex items-center justify-center\"></mona-placeholder>\n }\n}\n@if (footerTemplate()) {\n <ng-container [ngTemplateOutlet]=\"footerTemplate()\"></ng-container>\n}\n\n<ng-template #listItemTemplate let-item>\n @if (item.header) {\n <li [class]=\"groupHeaderClasses()\" [style]=\"listItemStyle()\">\n <mona-list-item [item]=\"item\" [template]=\"groupHeaderTemplate()\"></mona-list-item>\n </li>\n } @else {\n <li\n [class]=\"listItemClass()\"\n [class.px-0.5]=\"true\"\n [style]=\"listItemStyle()\"\n [id]=\"item.uid\"\n [attr.data-uid]=\"item.uid\"\n (click)=\"onListItemClick(item)\"\n monaListItem\n [item]=\"item\">\n <mona-list-item\n [item]=\"item\"\n [template]=\"itemTemplate()\"\n (checked)=\"onListItemCheck(item)\"></mona-list-item>\n </li>\n }\n</ng-template>\n" }]
1345
+ }], ctorParameters: () => [], propDecorators: { filterInput: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FilterInputComponent), { isSignal: true }] }], footerTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ListFooterTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], groupHeaderTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ListGroupHeaderTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], headerTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ListHeaderTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ListItemTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], noDataTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ListNoDataTemplateDirective), { ...{ read: TemplateRef }, isSignal: true }] }], virtualScrollViewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], focusOnMount: [{ type: i0.Input, args: [{ isSignal: true, alias: "focusOnMount", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], itemSelect: [{ type: i0.Output, args: ["itemSelect"] }], listClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "listClass", required: false }] }], listId: [{ type: i0.Input, args: [{ isSignal: true, alias: "listId", required: false }] }], listItemClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "listItemClass", required: false }] }], listItemStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "listItemStyle", required: false }] }], listStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "listStyle", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }] } });
1346
+
1347
+ /*
1348
+ * Public API Surface of @nanahoshi/mona-ui/list
1349
+ */
1350
+
1351
+ /**
1352
+ * Generated bundle index. Do not edit.
1353
+ */
1354
+
1355
+ export { ListComponent, ListFooterTemplateDirective, ListGroupHeaderTemplateDirective, ListHeaderTemplateDirective, ListItem, ListItemTemplateDirective, ListNoDataTemplateDirective, ListService };
1356
+ //# sourceMappingURL=nanahoshi-mona-ui-internal-list.mjs.map