@yuuvis/client-framework 3.0.0-beta.21.0 → 3.0.0-beta.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/autocomplete/README.md +1 -1
  2. package/common/README.md +1 -1
  3. package/fesm2022/yuuvis-client-framework-autocomplete.mjs +5 -236
  4. package/fesm2022/yuuvis-client-framework-autocomplete.mjs.map +1 -1
  5. package/fesm2022/yuuvis-client-framework-common.mjs +3 -1793
  6. package/fesm2022/yuuvis-client-framework-common.mjs.map +1 -1
  7. package/fesm2022/yuuvis-client-framework-list.mjs +3 -667
  8. package/fesm2022/yuuvis-client-framework-list.mjs.map +1 -1
  9. package/fesm2022/yuuvis-client-framework-master-details.mjs +3 -136
  10. package/fesm2022/yuuvis-client-framework-master-details.mjs.map +1 -1
  11. package/fesm2022/yuuvis-client-framework-overflow-hidden.mjs +3 -62
  12. package/fesm2022/yuuvis-client-framework-overflow-hidden.mjs.map +1 -1
  13. package/fesm2022/yuuvis-client-framework-overflow-menu.mjs +3 -129
  14. package/fesm2022/yuuvis-client-framework-overflow-menu.mjs.map +1 -1
  15. package/fesm2022/yuuvis-client-framework-popout.mjs +3 -239
  16. package/fesm2022/yuuvis-client-framework-popout.mjs.map +1 -1
  17. package/fesm2022/yuuvis-client-framework-split-view.mjs +3 -318
  18. package/fesm2022/yuuvis-client-framework-split-view.mjs.map +1 -1
  19. package/fesm2022/yuuvis-client-framework-widget-grid.mjs +3 -942
  20. package/fesm2022/yuuvis-client-framework-widget-grid.mjs.map +1 -1
  21. package/lib/assets/i18n/de.json +1 -55
  22. package/lib/assets/i18n/en.json +1 -55
  23. package/list/README.md +1 -1
  24. package/master-details/README.md +1 -1
  25. package/overflow-hidden/README.md +1 -1
  26. package/overflow-menu/README.md +1 -1
  27. package/package.json +6 -5
  28. package/popout/README.md +1 -1
  29. package/split-view/README.md +1 -1
  30. package/types/yuuvis-client-framework-autocomplete.d.ts +1 -89
  31. package/types/yuuvis-client-framework-common.d.ts +1 -536
  32. package/types/yuuvis-client-framework-list.d.ts +1 -380
  33. package/types/yuuvis-client-framework-master-details.d.ts +1 -69
  34. package/types/yuuvis-client-framework-overflow-hidden.d.ts +1 -28
  35. package/types/yuuvis-client-framework-overflow-menu.d.ts +1 -52
  36. package/types/yuuvis-client-framework-popout.d.ts +1 -106
  37. package/types/yuuvis-client-framework-split-view.d.ts +1 -197
  38. package/types/yuuvis-client-framework-widget-grid.d.ts +1 -299
  39. package/widget-grid/README.md +1 -46
@@ -1,675 +1,11 @@
1
- import * as i0 from '@angular/core';
2
- import { inject, ElementRef, input, linkedSignal, Input, Directive, contentChildren, output, HostAttributeToken, untracked, effect, ChangeDetectionStrategy, ViewEncapsulation, Component, contentChild, NgModule } from '@angular/core';
3
- import { Utils } from '@yuuvis/client-core';
4
- import { ActiveDescendantKeyManager, A11yModule } from '@angular/cdk/a11y';
5
- import { Directionality } from '@angular/cdk/bidi';
6
- import { coerceBooleanProperty } from '@angular/cdk/coercion';
7
- import * as i1 from '@angular/common';
8
- import { CommonModule } from '@angular/common';
1
+ export { ListComponent, ListItemDirective, ListTileComponent, YuvListModule } from '@yuuvis/client-components/list';
9
2
 
10
3
  /**
11
- * Directive for list items. It is used in the `yuvList` component
12
- * to keep track of active and selected items. Every element with this
13
- * directive will be treated as a list item and can be selected and focused.
14
- *
15
- *```html
16
- * <yuv-list (itemSelect)="itemSelected($event)">
17
- * <div yuvListItem>Entry #1</div>
18
- * <div yuvListItem>Entry #2</div>
19
- * </yuv-list>
20
- * ```
4
+ * @deprecated Import from `@yuuvis/client-components/list` instead.
5
+ * This entry point is a backward-compatibility shim and will be removed in a future release.
21
6
  */
22
- class ListItemDirective {
23
- constructor() {
24
- this.#elRef = inject(ElementRef);
25
- /**
26
- * Whether the item is active or not.
27
- */
28
- this.active = input(false, ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
29
- /**
30
- * Whether the item is selected or not.
31
- */
32
- this.selected = input(false, ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
33
- this.selectedInput = linkedSignal({ ...(ngDevMode ? { debugName: "selectedInput" } : /* istanbul ignore next */ {}), source: this.selected,
34
- computation: (newOptions, previous) => (newOptions !== previous ? newOptions : previous) });
35
- this.activeInput = linkedSignal({ ...(ngDevMode ? { debugName: "activeInput" } : /* istanbul ignore next */ {}), source: this.active,
36
- computation: (newOptions, previous) => (newOptions !== previous ? newOptions : previous) });
37
- this.focusableChildren = [];
38
- this.focusedIndex = -1;
39
- }
40
- #elRef;
41
- onHostClick(evt) {
42
- if (!this.disabled && this.onClick) {
43
- this.#elRef.nativeElement.parentElement.focus();
44
- this.onClick(evt);
45
- }
46
- }
47
- setActiveStyles() {
48
- this.activeInput.set(true);
49
- this.#scrollIntoView();
50
- }
51
- setInactiveStyles() {
52
- this.activeInput.set(false);
53
- }
54
- focusNext() { }
55
- focusPrevious() { }
56
- #scrollIntoView() {
57
- const el = this.#elRef.nativeElement;
58
- const { bottom, top, left, right } = el.getBoundingClientRect();
59
- const containerRect = this.#elRef.nativeElement.parentElement.getBoundingClientRect();
60
- const offsetY = top <= containerRect.top
61
- ? containerRect.top - top > 0
62
- ? (containerRect.top - top) * -1
63
- : 0
64
- : bottom - containerRect.bottom > 0
65
- ? bottom - containerRect.bottom
66
- : 0;
67
- const offsetX = left <= containerRect.left
68
- ? containerRect.left - left > 0
69
- ? (containerRect.left - left) * -1
70
- : 0
71
- : right - containerRect.right > 0
72
- ? right - containerRect.right
73
- : 0;
74
- if (offsetX || offsetY)
75
- this.#elRef.nativeElement.parentElement.scrollBy(offsetX, offsetY);
76
- }
77
- ngAfterViewInit() {
78
- // get all focusable elements and set tabindex to -1
79
- this.focusableChildren = Utils.getFocusableChildren(this.#elRef.nativeElement);
80
- this.focusableChildren.forEach((el) => el.setAttribute('tabindex', '-1'));
81
- }
82
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ListItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
83
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: ListItemDirective, isStandalone: true, selector: "[yuvListItem]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onHostClick($event)" }, properties: { "attr.aria-current": "activeInput()", "attr.aria-selected": "selectedInput()" } }, ngImport: i0 }); }
84
- }
85
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ListItemDirective, decorators: [{
86
- type: Directive,
87
- args: [{
88
- selector: '[yuvListItem]',
89
- standalone: true,
90
- host: {
91
- '[attr.aria-current]': 'activeInput()',
92
- '[attr.aria-selected]': 'selectedInput()',
93
- '(click)': 'onHostClick($event)'
94
- }
95
- }]
96
- }], propDecorators: { disabled: [{
97
- type: Input
98
- }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }] } });
99
-
100
- /**
101
- * Accessible list component with keyboard navigation, single- and multi-selection,
102
- * and flexible delegation of click- and selection-handling to the parent.
103
- *
104
- * The component renders as an ARIA `listbox` and delegates keyboard focus tracking
105
- * to Angular CDK's `ActiveDescendantKeyManager`. Content is projected via
106
- * `[yuvListItem]`-attributed children (see `ListItemDirective`).
107
- *
108
- * **Key Features:**
109
- * - Single and multi-selection (with Shift / Ctrl modifier support)
110
- * - Full keyboard navigation (Arrow keys, Space, Enter, Escape)
111
- * - Horizontal and vertical layout via the `horizontal` host attribute
112
- * - Auto-selection on initialization via the `autoSelect` input
113
- * - Selection guarding via `preventChangeUntil` callback
114
- * - Optional delegation of click and selection handling to the parent component
115
- * - Accessible: `role="listbox"`, active-descendant focus management, `aria-selected` on items
116
- *
117
- * **Basic usage:**
118
- * ```html
119
- * <yuv-list (itemSelect)="onItemSelect($event)">
120
- * <div yuvListItem>Entry #1</div>
121
- * <div yuvListItem>Entry #2</div>
122
- * </yuv-list>
123
- * ```
124
- *
125
- * **Multi-selection with Shift/Ctrl:**
126
- * ```html
127
- * <yuv-list [multiselect]="true" (itemSelect)="onSelect($event)">
128
- * @for (item of items; track item.id) {
129
- * <div yuvListItem>{{ item.label }}</div>
130
- * }
131
- * </yuv-list>
132
- * ```
133
- *
134
- * **Host Attributes (set declaratively in the template):**
135
- * - `selectOnEnter` — treat the Enter key as a selection trigger (in addition to Space)
136
- * - `horizontal` — switch key navigation to left/right arrows instead of up/down
137
- *
138
- * @example
139
- * ```html
140
- * <!-- Horizontal list, Enter key selects -->
141
- * <yuv-list horizontal selectOnEnter (itemSelect)="onSelect($event)">
142
- * <button yuvListItem>A</button>
143
- * <button yuvListItem>B</button>
144
- * </yuv-list>
145
- * ```
146
- */
147
- class ListComponent {
148
- //#region Dependencies
149
- #dir;
150
- #elRef;
151
- #keyManager;
152
- #selection;
153
- #lastSelection;
154
- //#endregion
155
- //#region Lifecycle Hooks
156
- constructor() {
157
- //#region Dependencies
158
- this.#dir = inject(Directionality);
159
- this.#elRef = inject(ElementRef);
160
- //#endregion
161
- //#region Angular Stuff
162
- /**
163
- * All `[yuvListItem]` children projected into this list.
164
- *
165
- * Queried reactively via `contentChildren` — every time the projected content
166
- * changes (items added, removed, or reordered), the `#itemsEffect` re-runs,
167
- * rebuilds the key manager, and re-attaches click handlers.
168
- */
169
- this.items = contentChildren(ListItemDirective, ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
170
- /**
171
- * Guard function that temporarily blocks all selection changes.
172
- *
173
- * Provide a factory that returns a predicate; as long as that predicate
174
- * returns `true`, any attempt to change the selection (via click, keyboard,
175
- * or programmatic API) is silently ignored. Useful when the parent has
176
- * unsaved changes tied to the current selection and needs to prevent the user
177
- * from accidentally navigating away.
178
- *
179
- * @example
180
- * ```ts
181
- * // Block selection while a save is in progress
182
- * preventChangeUntil = () => () => this.isSaving();
183
- * ```
184
- *
185
- * @default () => false (never prevents)
186
- */
187
- this.preventChangeUntil = input(() => false, ...(ngDevMode ? [{ debugName: "preventChangeUntil" }] : /* istanbul ignore next */ []));
188
- /**
189
- * Enables multi-selection mode.
190
- *
191
- * When `true`, the user can hold **Shift** to range-select items between the last
192
- * selected item and the clicked one, or hold **Ctrl** to toggle individual items
193
- * in and out of the selection. The programmatic `multiSelect()` method is also
194
- * only effective when this input is `true`.
195
- *
196
- * @default false
197
- */
198
- this.multiselect = input(false, ...(ngDevMode ? [{ debugName: "multiselect" }] : /* istanbul ignore next */ []));
199
- /**
200
- * Delegates visual selection and focus state rendering to the parent component.
201
- *
202
- * When `false` (default), `yuv-list` applies `.selected` and `.active` CSS classes
203
- * to items via `ListItemDirective` signals, so the list stylesheet controls the look.
204
- * When `true`, those signals are still updated but the host gets the
205
- * `self-handle-selection` CSS class, which the parent can use to opt into its own
206
- * visual treatment — useful when item templates have custom selected/focused styling.
207
- *
208
- * @default false
209
- */
210
- this.selfHandleSelection = input(false, ...(ngDevMode ? [{ debugName: "selfHandleSelection" }] : /* istanbul ignore next */ []));
211
- /**
212
- * Disables the built-in click-to-select behavior, letting the parent component
213
- * decide when `select()` is called.
214
- *
215
- * By default the list attaches an `onClick` handler to every `ListItemDirective`
216
- * that calls `select()` with the correct Shift/Ctrl modifier flags. Set this
217
- * input to `true` to suppress that wiring — the parent must then call `select()`
218
- * imperatively in response to whatever interaction it chooses (e.g. a single-click
219
- * that is distinguished from a double-click by `ClickDoubleDirective`).
220
- *
221
- * @default false
222
- */
223
- this.selfHandleClick = input(false, ...(ngDevMode ? [{ debugName: "selfHandleClick" }] : /* istanbul ignore next */ []));
224
- /**
225
- * Automatically selects an item when the list is first rendered.
226
- *
227
- * The selection logic runs once per content-children change (see `#itemsEffect`)
228
- * and follows this priority order:
229
- * 1. The first non-disabled item that already carries the `selected` attribute.
230
- * 2. If no such item exists and `autoSelect` is `true`, the item at index 0.
231
- *
232
- * Accepts any truthy string value in addition to a real boolean because the
233
- * input is also consumable as a plain HTML attribute (`<yuv-list autoSelect>`).
234
- *
235
- * @default false
236
- */
237
- this.autoSelect = input(false, { ...(ngDevMode ? { debugName: "autoSelect" } : /* istanbul ignore next */ {}), transform: (value) => coerceBooleanProperty(value) });
238
- /**
239
- * Emits the current selection as an array of zero-based item indices whenever
240
- * the selection changes — via click, keyboard, or programmatic API calls.
241
- *
242
- * An empty array signals that the selection has been cleared.
243
- *
244
- * @example
245
- * ```ts
246
- * onItemSelect(indices: number[]): void {
247
- * this.selectedItems = indices.map(i => this.items[i]);
248
- * }
249
- * ```
250
- */
251
- this.itemSelect = output();
252
- /**
253
- * Emits the zero-based index of the item that received keyboard focus
254
- * (i.e. the active descendant managed by `ActiveDescendantKeyManager`).
255
- *
256
- * Note that focus and selection are independent: navigating with arrow keys
257
- * moves focus without changing the selection until Space (or Enter when
258
- * `selectOnEnter` is set) is pressed.
259
- */
260
- this.itemFocus = output();
261
- /**
262
- * Puts the list into a display-only mode where no item can be selected.
263
- *
264
- * When `true`, all selection paths are blocked: clicks, keyboard shortcuts
265
- * (`Space`, `Enter`, `Escape`), and programmatic calls to `select()`,
266
- * `multiSelect()`, and `clear()` are all no-ops. The list still renders
267
- * normally and keyboard navigation still moves the focus indicator.
268
- *
269
- * @default false
270
- */
271
- this.disableSelection = input(false, ...(ngDevMode ? [{ debugName: "disableSelection" }] : /* istanbul ignore next */ []));
272
- //#endregion
273
- //#region Properties
274
- /**
275
- * When `true`, pressing **Enter** triggers item selection in addition to **Space**.
276
- *
277
- * Resolved once at construction time from the static `selectOnEnter` host attribute.
278
- * Useful in contexts where Enter has a conventional "confirm" meaning (e.g. search
279
- * result lists, command palettes).
280
- *
281
- * Set declaratively in the template: `<yuv-list selectOnEnter>`.
282
- */
283
- this.selectOnEnter = (inject(new HostAttributeToken('selectOnEnter'), { optional: true }) || 'false') === 'true';
284
- /**
285
- * When `true`, switches the `ActiveDescendantKeyManager` to horizontal mode so that
286
- * the **Left** / **Right** arrow keys navigate between items instead of **Up** / **Down**.
287
- *
288
- * Resolved once at construction time from the static `horizontal` host attribute.
289
- * The text direction of the document is respected automatically (RTL-aware via CDK
290
- * `Directionality`).
291
- *
292
- * Set declaratively in the template: `<yuv-list horizontal>`.
293
- */
294
- this.horizontal = (inject(new HostAttributeToken('horizontal'), { optional: true }) || 'false') === 'true';
295
- this.#selection = [];
296
- //#endregion
297
- //#region Effects
298
- this.#itemsEffect = () => {
299
- const items = this.items();
300
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
301
- if (this.#keyManager)
302
- this.#keyManager.destroy();
303
- untracked(() => {
304
- this.#keyManager = this.horizontal
305
- ? new ActiveDescendantKeyManager(items).withWrap().withHorizontalOrientation(this.#dir.value)
306
- : new ActiveDescendantKeyManager(items).withWrap();
307
- this.#keyManager.change.subscribe((activeIndex) => {
308
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
309
- if (activeIndex !== null) {
310
- this.#updateActiveItemState();
311
- this.itemFocus.emit(activeIndex);
312
- }
313
- });
314
- if (!this.selfHandleClick()) {
315
- items.forEach((item, index) => {
316
- item.onClick = (evt) => {
317
- this.select(index, evt.shiftKey, evt.ctrlKey);
318
- };
319
- item.activeInput.set(false);
320
- });
321
- }
322
- if (this.#lastSelection !== undefined && this.#lastSelection <= items.length) {
323
- this.select(this.#lastSelection);
324
- }
325
- this.#preselectItem();
326
- });
327
- };
328
- effect(this.#itemsEffect);
329
- }
330
- ngOnDestroy() {
331
- this.#keyManager.destroy();
332
- }
333
- //#endregion
334
- //#region Public
335
- /**
336
- * Moves keyboard focus to the item at the given index and selects it.
337
- *
338
- * Combines three operations in one call: updating the CDK key manager's active
339
- * descendant (which drives the ARIA active-descendant attribute and the visual focus ring),
340
- * selecting the item, and transferring DOM focus to the list host element so that
341
- * subsequent keyboard events are processed correctly.
342
- *
343
- * Safe to call before the key manager is initialized — the guard at the top of
344
- * the method prevents errors during early lifecycle phases.
345
- *
346
- * @param index Zero-based index of the item to activate.
347
- */
348
- setActiveItem(index) {
349
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
350
- if (this.#keyManager) {
351
- this.#keyManager.setActiveItem(index);
352
- this.#select(index);
353
- this.focus();
354
- }
355
- }
356
- /**
357
- * Transfers DOM focus to the list host element.
358
- *
359
- * Calling this ensures that subsequent keyboard events (arrow keys, Space, etc.)
360
- * are routed to the list's `(keydown)` handler. Called internally by
361
- * `setActiveItem()`, but also useful from the parent when programmatic focus
362
- * management is needed (e.g. after closing a dialog that was triggered from a
363
- * list item).
364
- */
365
- focus() {
366
- this.#elRef.nativeElement.focus();
367
- }
368
- /**
369
- * Smoothly scrolls the list container back to the top.
370
- *
371
- * Useful after programmatically refreshing the list contents when the user may
372
- * have scrolled far down and the new result set should be shown from the beginning.
373
- */
374
- scrollToTop() {
375
- this.#elRef.nativeElement.scrollTo({ top: 0, behavior: 'smooth' });
376
- }
377
- /**
378
- * Shifts all selected and focused item indices by the given offset.
379
- *
380
- * Use this when items are prepended or inserted at the beginning of the list so
381
- * that the existing selection and keyboard-focus position stay attached to the
382
- * same logical items after the index space shifts. A positive offset moves
383
- * indices forward (items were inserted before the selection); a negative offset
384
- * moves them backward (items were removed before the selection).
385
- *
386
- * Does **not** emit `itemSelect` — the selection indices change structurally,
387
- * not because the user chose different items.
388
- *
389
- * @param offset Number of positions to shift every selected index by.
390
- */
391
- shiftSelectionBy(offset) {
392
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
393
- if (this.#keyManager?.activeItemIndex !== null && this.#keyManager?.activeItemIndex !== undefined) {
394
- this.#keyManager.setActiveItem(this.#keyManager.activeItemIndex + offset);
395
- }
396
- this.#selection = this.#selection.map((i) => i + offset);
397
- if (this.#lastSelection !== undefined)
398
- this.#lastSelection += offset;
399
- this.items().forEach((item, i) => item.selectedInput.set(this.#selection.includes(i)));
400
- }
401
- /**
402
- * Programmatically replaces the entire selection with the given indices.
403
- *
404
- * Only effective when `multiselect` is `true` and `disableSelection` is `false`.
405
- * Out-of-range indices are silently discarded. The resulting selection is sorted
406
- * ascending before being applied and emitted.
407
- *
408
- * Use this when the parent needs to restore a previously saved multi-selection
409
- * state, e.g. after navigation or on component re-initialization.
410
- *
411
- * @param index Array of zero-based item indices to select.
412
- */
413
- multiSelect(index) {
414
- if (this.#preventEmit())
415
- return;
416
- if (!this.multiselect() || this.disableSelection())
417
- return;
418
- this.#selection = index.filter((i) => i >= 0 && i < this.items().length);
419
- this.#selection.sort();
420
- this.items().forEach((item, i) => item.selectedInput.set(this.#selection.includes(i)));
421
- this.#emitSelection();
422
- }
423
- /**
424
- * Selects the item at the given index, optionally extending or toggling
425
- * the existing selection using modifier-key semantics.
426
- *
427
- * - **No modifiers** (default): replaces the current selection with the single item.
428
- * - **`shiftKey = true`** (`multiselect` only): range-selects all items between the
429
- * last selected index and `index` (inclusive of neither endpoint, matching typical
430
- * OS list behavior).
431
- * - **`ctrlKey = true`** (`multiselect` only): toggles `index` in the selection
432
- * without affecting the rest.
433
- *
434
- * Index is clamped to `[0, items.length - 1]`. Negative values and calls while
435
- * `disableSelection` is `true` are ignored. The `preventChangeUntil` guard is
436
- * also respected.
437
- *
438
- * Emits `itemSelect` after updating the visual state.
439
- *
440
- * @param index Zero-based index of the item to select.
441
- * @param shiftKey Extend the selection from the last selected item to `index`.
442
- * @param ctrlKey Toggle `index` in or out of the current selection.
443
- */
444
- select(index, shiftKey = false, ctrlKey = false) {
445
- if (this.#preventEmit())
446
- return;
447
- if (this.disableSelection() || index < 0)
448
- return;
449
- if (index >= this.items().length)
450
- index = this.items().length - 1;
451
- this.#select(index, shiftKey, ctrlKey);
452
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
453
- if (this.#keyManager)
454
- this.#keyManager.setActiveItem(index);
455
- this.#emitSelection();
456
- }
457
- /**
458
- * Clears the current selection and resets the active keyboard-focus index.
459
- *
460
- * If the selection is already empty, the method is a no-op (no event emitted,
461
- * no state update). The `preventChangeUntil` guard is respected — if the guard
462
- * returns `true`, the clear is blocked entirely.
463
- *
464
- * Also triggered internally when the user presses **Escape**.
465
- *
466
- * @param silent When `true`, skips emitting `itemSelect` after clearing. Use this
467
- * when the parent needs to reset state programmatically without
468
- * triggering downstream reactions.
469
- */
470
- clear(silent = false) {
471
- if (this.#preventEmit())
472
- return;
473
- if (this.#selection.length !== 0) {
474
- this.#select(-1);
475
- this.#keyManager.setActiveItem(-1);
476
- if (!silent)
477
- this.#emitSelection();
478
- }
479
- }
480
- //#endregion
481
- //#region UI Methods
482
- /**
483
- * Host `keydown` handler — routes keyboard events to selection or navigation logic.
484
- *
485
- * Handled keys:
486
- * - **Escape**: clears the selection.
487
- * - **Space** (always) / **Enter** (when `selectOnEnter` is set): selects the
488
- * currently focused item. `preventDefault()` is called to stop the browser
489
- * from scrolling the container when Space is pressed.
490
- * - **All other keys**: forwarded to `ActiveDescendantKeyManager` so arrow keys,
491
- * Home, End, etc. move the focus indicator without changing the selection.
492
- *
493
- * When `disableSelection` is `true`, only navigation keys are forwarded to the
494
- * key manager — selection keys (Space, Enter, Escape) are suppressed.
495
- *
496
- * Bound via the `host` metadata as `(keydown)`.
497
- *
498
- * @param event The keyboard event originating from the list host element.
499
- */
500
- onKeydown(event) {
501
- if (this.disableSelection()) {
502
- this.#keyManager?.onKeydown(event);
503
- return;
504
- }
505
- if (event.code === 'Escape') {
506
- this.clear();
507
- }
508
- if (event.code === 'Space' || (this.selectOnEnter && event.code === 'Enter')) {
509
- // prevent default behavior of space in scroll environments
510
- if (this.#preventEmit())
511
- return;
512
- event.preventDefault();
513
- const aii = this.#keyManager.activeItemIndex !== null ? this.#keyManager.activeItemIndex : -1;
514
- if (aii >= 0) {
515
- this.#select(aii);
516
- this.#emitSelection();
517
- }
518
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
519
- }
520
- else
521
- this.#keyManager?.onKeydown(event);
522
- }
523
- /**
524
- * Host `focus` handler — restores a sensible focus position when the list
525
- * host element receives DOM focus without an item already being active.
526
- *
527
- * The logic runs inside a 300 ms timeout so that focus events triggered by
528
- * an item being clicked (which also bubbles a focus event up to the host)
529
- * have already resolved their own active-item state before this handler acts.
530
- * If an active item already exists when the timeout fires, nothing happens.
531
- *
532
- * Focus target priority:
533
- * 1. The first index in the current selection (so the user lands back on the
534
- * previously selected item when tabbing into the list).
535
- * 2. Index 0 as the fallback when there is no selection.
536
- *
537
- * Bound via the `host` metadata as `(focus)`.
538
- */
539
- onFocus() {
540
- // set timeout to check if the focus is coming from an item being clicked
541
- setTimeout(() => {
542
- // if there already is an active item, we do not want to set the focus again
543
- if (this.#keyManager.activeItemIndex === -1 && this.items().length > 0) {
544
- const indexToFocus = this.#selection.length > 0 ? this.#selection[0] : 0;
545
- this.#keyManager.setActiveItem(indexToFocus);
546
- this.itemFocus.emit(indexToFocus);
547
- this.#updateActiveItemState();
548
- }
549
- // eslint-disable-next-line @typescript-eslint/no-magic-numbers
550
- }, 300);
551
- }
552
- //#endregion
553
- //#region Utilities
554
- #preventEmit() {
555
- const preventUntilIsTrue = this.preventChangeUntil();
556
- return preventUntilIsTrue();
557
- }
558
- #select(index, shiftKey = false, ctrlKey = false) {
559
- if (index === -1)
560
- this.#selection = [];
561
- else {
562
- if (this.multiselect()) {
563
- this.#selection = this.#selection.filter((i) => i !== index);
564
- if (ctrlKey) {
565
- this.#selection.push(index);
566
- }
567
- else if (shiftKey) {
568
- if (this.#lastSelection) {
569
- for (let i = this.#lastSelection < index ? this.#lastSelection : index; i < (this.#lastSelection > index ? this.#lastSelection : index); i++) {
570
- this.#selection.push(i);
571
- }
572
- }
573
- else {
574
- this.#selection = [index];
575
- }
576
- }
577
- else {
578
- this.#selection = [index];
579
- }
580
- }
581
- else
582
- this.#selection = [index];
583
- }
584
- this.#lastSelection = this.#selection.length === 0 ? undefined : index;
585
- this.#selection.sort();
586
- this.items().forEach((item, i) => item.selectedInput.set(this.#selection.includes(i)));
587
- }
588
- #updateActiveItemState() {
589
- const activeIndex = this.#keyManager.activeItemIndex;
590
- this.items().forEach((item, i) => {
591
- item.activeInput.set(i === activeIndex);
592
- });
593
- }
594
- #emitSelection() {
595
- this.itemSelect.emit(this.#selection);
596
- }
597
- #preselectItem() {
598
- if (this.#selection.length > 0)
599
- return; // if there is already a selection, do not preselect
600
- const items = this.items();
601
- const autoSelect = this.autoSelect();
602
- let itemIndexToSelect = -1;
603
- // If the list has no items, do nothing.
604
- if (items.length < 1)
605
- return;
606
- // Find the first item that has the "selected"-attribute and is not disabled
607
- itemIndexToSelect = items.findIndex((item) => item.selected() && !item.disabled);
608
- // If no valid item index is given, but autoSelect is true, select the first item
609
- if (itemIndexToSelect === -1 && autoSelect) {
610
- itemIndexToSelect = 0;
611
- }
612
- // If there is a valid item index, select that item, otherwise do nothing
613
- if (itemIndexToSelect !== -1) {
614
- this.select(itemIndexToSelect);
615
- }
616
- }
617
- //#endregion
618
- //#region Effects
619
- #itemsEffect;
620
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
621
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.9", type: ListComponent, isStandalone: true, selector: "yuv-list", inputs: { preventChangeUntil: { classPropertyName: "preventChangeUntil", publicName: "preventChangeUntil", isSignal: true, isRequired: false, transformFunction: null }, multiselect: { classPropertyName: "multiselect", publicName: "multiselect", isSignal: true, isRequired: false, transformFunction: null }, selfHandleSelection: { classPropertyName: "selfHandleSelection", publicName: "selfHandleSelection", isSignal: true, isRequired: false, transformFunction: null }, selfHandleClick: { classPropertyName: "selfHandleClick", publicName: "selfHandleClick", isSignal: true, isRequired: false, transformFunction: null }, autoSelect: { classPropertyName: "autoSelect", publicName: "autoSelect", isSignal: true, isRequired: false, transformFunction: null }, disableSelection: { classPropertyName: "disableSelection", publicName: "disableSelection", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect", itemFocus: "itemFocus" }, host: { attributes: { "role": "listbox", "tabindex": "0" }, listeners: { "focus": "onFocus()", "keydown": "onKeydown($event)" }, properties: { "class.self-handle-selection": "selfHandleSelection()" } }, queries: [{ propertyName: "items", predicate: ListItemDirective, isSignal: true }], ngImport: i0, template: '<ng-content />', isInline: true, styles: ["yuv-list{display:block;max-height:100%;overflow-y:auto;outline:none}yuv-list:not(.self-handle-selection) [yuvListItem]:not(:has(yuv-list-tile)){position:relative;cursor:pointer;transition:background-color .2s ease,color .2s ease,border-color .2s ease}yuv-list:not(.self-handle-selection) [yuvListItem]:not(:has(yuv-list-tile)):hover,yuv-list:not(.self-handle-selection) [yuvListItem]:not(:has(yuv-list-tile))[aria-current=true]{background-color:var(--ymt-focus-background);color:var(--ymt-on-focus-background)}yuv-list:not(.self-handle-selection) [yuvListItem]:not(:has(yuv-list-tile))[aria-selected=true]{background-color:var(--ymt-selection-background);color:var(--ymt-on-selection-background);font-weight:500}yuv-list:not(.self-handle-selection) [yuvListItem]:has(yuv-list-tile):hover:not([aria-selected=true]) .tile{--_tile-background: var(--ymt-hover-background)}yuv-list:not(.self-handle-selection) [yuvListItem]:has(yuv-list-tile)[aria-selected=true] .tile{--_tile-background: var(--ymt-selection-background)}yuv-list:not(.self-handle-selection) [yuvListItem]:has(yuv-list-tile)[aria-current=true] .tile{--_tile-background: var(--ymt-focus-background)}\n"], dependencies: [{ kind: "ngmodule", type: A11yModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
622
- }
623
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ListComponent, decorators: [{
624
- type: Component,
625
- args: [{ selector: 'yuv-list', standalone: true, imports: [A11yModule], template: '<ng-content />', encapsulation: ViewEncapsulation.None, host: {
626
- role: 'listbox',
627
- tabindex: '0',
628
- '[class.self-handle-selection]': 'selfHandleSelection()',
629
- '(focus)': 'onFocus()',
630
- '(keydown)': 'onKeydown($event)'
631
- }, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["yuv-list{display:block;max-height:100%;overflow-y:auto;outline:none}yuv-list:not(.self-handle-selection) [yuvListItem]:not(:has(yuv-list-tile)){position:relative;cursor:pointer;transition:background-color .2s ease,color .2s ease,border-color .2s ease}yuv-list:not(.self-handle-selection) [yuvListItem]:not(:has(yuv-list-tile)):hover,yuv-list:not(.self-handle-selection) [yuvListItem]:not(:has(yuv-list-tile))[aria-current=true]{background-color:var(--ymt-focus-background);color:var(--ymt-on-focus-background)}yuv-list:not(.self-handle-selection) [yuvListItem]:not(:has(yuv-list-tile))[aria-selected=true]{background-color:var(--ymt-selection-background);color:var(--ymt-on-selection-background);font-weight:500}yuv-list:not(.self-handle-selection) [yuvListItem]:has(yuv-list-tile):hover:not([aria-selected=true]) .tile{--_tile-background: var(--ymt-hover-background)}yuv-list:not(.self-handle-selection) [yuvListItem]:has(yuv-list-tile)[aria-selected=true] .tile{--_tile-background: var(--ymt-selection-background)}yuv-list:not(.self-handle-selection) [yuvListItem]:has(yuv-list-tile)[aria-current=true] .tile{--_tile-background: var(--ymt-focus-background)}\n"] }]
632
- }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => ListItemDirective), { isSignal: true }] }], preventChangeUntil: [{ type: i0.Input, args: [{ isSignal: true, alias: "preventChangeUntil", required: false }] }], multiselect: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiselect", required: false }] }], selfHandleSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selfHandleSelection", required: false }] }], selfHandleClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "selfHandleClick", required: false }] }], autoSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoSelect", required: false }] }], itemSelect: [{ type: i0.Output, args: ["itemSelect"] }], itemFocus: [{ type: i0.Output, args: ["itemFocus"] }], disableSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableSelection", required: false }] }] } });
633
-
634
- class ListTileComponent {
635
- constructor() {
636
- this.iconSlot = contentChild('iconSlot', { ...(ngDevMode ? { debugName: "iconSlot" } : /* istanbul ignore next */ {}), descendants: true });
637
- this.titleSlot = contentChild('titleSlot', ...(ngDevMode ? [{ debugName: "titleSlot" }] : /* istanbul ignore next */ []));
638
- this.descriptionSlot = contentChild('descriptionSlot', ...(ngDevMode ? [{ debugName: "descriptionSlot" }] : /* istanbul ignore next */ []));
639
- this.asideSlot = contentChild('asideSlot', ...(ngDevMode ? [{ debugName: "asideSlot" }] : /* istanbul ignore next */ []));
640
- this.actionsSlot = contentChild('actionsSlot', { ...(ngDevMode ? { debugName: "actionsSlot" } : /* istanbul ignore next */ {}), descendants: true });
641
- this.badgesSlot = contentChild('badgesSlot', ...(ngDevMode ? [{ debugName: "badgesSlot" }] : /* istanbul ignore next */ []));
642
- this.metaSlot = contentChild('metaSlot', ...(ngDevMode ? [{ debugName: "metaSlot" }] : /* istanbul ignore next */ []));
643
- this.extensionSlot = contentChild('extensionSlot', ...(ngDevMode ? [{ debugName: "extensionSlot" }] : /* istanbul ignore next */ []));
644
- }
645
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ListTileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
646
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.9", type: ListTileComponent, isStandalone: true, selector: "yuv-list-tile", queries: [{ propertyName: "iconSlot", first: true, predicate: ["iconSlot"], descendants: true, isSignal: true }, { propertyName: "titleSlot", first: true, predicate: ["titleSlot"], descendants: true, isSignal: true }, { propertyName: "descriptionSlot", first: true, predicate: ["descriptionSlot"], descendants: true, isSignal: true }, { propertyName: "asideSlot", first: true, predicate: ["asideSlot"], descendants: true, isSignal: true }, { propertyName: "actionsSlot", first: true, predicate: ["actionsSlot"], descendants: true, isSignal: true }, { propertyName: "badgesSlot", first: true, predicate: ["badgesSlot"], descendants: true, isSignal: true }, { propertyName: "metaSlot", first: true, predicate: ["metaSlot"], descendants: true, isSignal: true }, { propertyName: "extensionSlot", first: true, predicate: ["extensionSlot"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-content></ng-content>\n<div class=\"tile\">\n <div data-slot=\"icon\">\n <ng-container *ngTemplateOutlet=\"iconSlot() || null\"></ng-container>\n </div>\n <div class=\"slots\"> \n <div data-slot=\"title-description\">\n <div data-slot=\"title\">\n <ng-container *ngTemplateOutlet=\"titleSlot() || null\"></ng-container>\n </div>\n <div data-slot=\"description\">\n <ng-container *ngTemplateOutlet=\"descriptionSlot() || null\"></ng-container>\n </div>\n </div>\n <div data-slot=\"actions\">\n <ng-container *ngTemplateOutlet=\"actionsSlot() || null\"></ng-container>\n </div>\n <div data-slot=\"aside\">\n <ng-container *ngTemplateOutlet=\"asideSlot() || null\"></ng-container>\n </div>\n <div data-slot=\"meta\">\n <ng-container *ngTemplateOutlet=\"metaSlot() || null\"></ng-container>\n </div>\n <div data-slot=\"badges\">\n <ng-container *ngTemplateOutlet=\"badgesSlot() || null\"></ng-container>\n </div>\n <div class=\"extension\">\n <ng-container *ngTemplateOutlet=\"extensionSlot() || null\"></ng-container>\n </div>\n </div>\n</div>\n", styles: [":host{--_tile-background: var(--tile-background, transparent);--_tile-margin: var(--tile-margin, var(--ymt-spacing-xs));--_tile-padding-inline: var(--tile-padding-inline, var(--ymt-spacing-2xl));--_tile-padding-block: var(--tile-padding-block, var(--ymt-spacing-l));--_transition-duration: var(--transition-duration, .1s);--_tile-icon-size: var(--tile-icon-size, initial);--_tile-font-title: var(--tile-font-title, var(--ymt-font-title-smallest));--_tile-font-description: var(--tile-font-description, var(--ymt-font-body));--_tile-font-meta: var(--tile-font-meta, var(--ymt-font-body-subtle));--_tile-font-aside: var(--tile-font-aside, var(--ymt-font-body-subtle));display:block;cursor:pointer}:host.dense .tile{--_tile-padding-inline: var(--ymt-spacing-m);--_tile-padding-block: var(--ymt-spacing-s);--_tile-margin: var(--ymt-spacing-xs);gap:var(--ymt-spacing-s)}:host.dense .tile .extension,:host.dense .tile [data-slot=aside],:host.dense .tile [data-slot=meta],:host.dense .tile [data-slot=actions]{display:none}:host.dense .tile [data-slot=icon]{--icon-renderer-icon-size: 18px}:host .tile{display:flex;align-items:center;background-color:var(--_tile-background);padding:calc(var(--_tile-padding-block) - var(--_tile-margin)) calc(var(--_tile-padding-inline) - var(--_tile-margin));transition:background-color var(--_transition-duration);position:relative;color:var(--ymt-text-color);border-radius:var(--ymt-corner-s);margin:var(--_tile-margin);gap:var(--ymt-spacing-m)}:host .tile .slots{display:grid;grid-template-rows:repeat(4,auto);grid-template-columns:auto;grid-template-areas:\"title-description title-description actions\" \"meta meta aside\" \"badges badges badges\" \"ext ext ext\";flex:1}:host .tile [data-slot]{-webkit-user-select:none;user-select:none;display:grid;align-self:baseline;word-break:break-word}:host .tile [data-slot=icon]{--icon-renderer-icon-size: var(--_tile-icon-size);grid-area:icon;display:flex;align-self:flex-start}:host .tile [data-slot=title-description]{grid-area:title-description;display:grid;grid-template-areas:\"title\" \"description\";align-self:flex-start}:host .tile [data-slot=title]{font:var(--_tile-font-title);grid-area:title;align-self:flex-start;--tile-slot-padding: 0}:host .tile [data-slot=description]{grid-area:description;font:var(--_tile-font-description);color:var(--ymt-text-color-subtle);--tile-slot-padding: 0}:host .tile [data-slot=meta]{grid-area:meta;font:var(--_tile-font-meta);color:var(--ymt-text-color-subtle);--tile-slot-padding: var(--ymt-spacing-2xs) var(--ymt-spacing-2xs) var(--ymt-spacing-2xs) 0}:host .tile [data-slot=aside]{flex:0 0 auto;grid-area:aside;font:var(--_tile-font-aside);color:var(--ymt-text-color-subtle);justify-content:flex-end;text-align:right;--tile-slot-padding: var(--ymt-spacing-2xs)}:host .tile [data-slot=actions]{opacity:.2;transition:opacity var(--_transition-duration);pointer-events:none;display:flex;justify-content:flex-end;padding-block-end:var(--ymt-spacing-2xs);gap:var(--ymt-spacing-3xs)}:host .tile:hover [data-slot=actions]{opacity:1;pointer-events:all}:host .tile [data-slot=actions]{grid-area:actions;flex:0 0 auto;display:flex;align-items:start}:host .tile [data-slot=actions] button{gap:2px}:host .tile [data-slot=badges]{grid-area:badges;justify-self:end;flex:0 0 auto}:host .tile .extension{grid-area:ext}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
647
- }
648
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ListTileComponent, decorators: [{
649
- type: Component,
650
- args: [{ selector: 'yuv-list-tile', imports: [CommonModule], template: "<ng-content></ng-content>\n<div class=\"tile\">\n <div data-slot=\"icon\">\n <ng-container *ngTemplateOutlet=\"iconSlot() || null\"></ng-container>\n </div>\n <div class=\"slots\"> \n <div data-slot=\"title-description\">\n <div data-slot=\"title\">\n <ng-container *ngTemplateOutlet=\"titleSlot() || null\"></ng-container>\n </div>\n <div data-slot=\"description\">\n <ng-container *ngTemplateOutlet=\"descriptionSlot() || null\"></ng-container>\n </div>\n </div>\n <div data-slot=\"actions\">\n <ng-container *ngTemplateOutlet=\"actionsSlot() || null\"></ng-container>\n </div>\n <div data-slot=\"aside\">\n <ng-container *ngTemplateOutlet=\"asideSlot() || null\"></ng-container>\n </div>\n <div data-slot=\"meta\">\n <ng-container *ngTemplateOutlet=\"metaSlot() || null\"></ng-container>\n </div>\n <div data-slot=\"badges\">\n <ng-container *ngTemplateOutlet=\"badgesSlot() || null\"></ng-container>\n </div>\n <div class=\"extension\">\n <ng-container *ngTemplateOutlet=\"extensionSlot() || null\"></ng-container>\n </div>\n </div>\n</div>\n", styles: [":host{--_tile-background: var(--tile-background, transparent);--_tile-margin: var(--tile-margin, var(--ymt-spacing-xs));--_tile-padding-inline: var(--tile-padding-inline, var(--ymt-spacing-2xl));--_tile-padding-block: var(--tile-padding-block, var(--ymt-spacing-l));--_transition-duration: var(--transition-duration, .1s);--_tile-icon-size: var(--tile-icon-size, initial);--_tile-font-title: var(--tile-font-title, var(--ymt-font-title-smallest));--_tile-font-description: var(--tile-font-description, var(--ymt-font-body));--_tile-font-meta: var(--tile-font-meta, var(--ymt-font-body-subtle));--_tile-font-aside: var(--tile-font-aside, var(--ymt-font-body-subtle));display:block;cursor:pointer}:host.dense .tile{--_tile-padding-inline: var(--ymt-spacing-m);--_tile-padding-block: var(--ymt-spacing-s);--_tile-margin: var(--ymt-spacing-xs);gap:var(--ymt-spacing-s)}:host.dense .tile .extension,:host.dense .tile [data-slot=aside],:host.dense .tile [data-slot=meta],:host.dense .tile [data-slot=actions]{display:none}:host.dense .tile [data-slot=icon]{--icon-renderer-icon-size: 18px}:host .tile{display:flex;align-items:center;background-color:var(--_tile-background);padding:calc(var(--_tile-padding-block) - var(--_tile-margin)) calc(var(--_tile-padding-inline) - var(--_tile-margin));transition:background-color var(--_transition-duration);position:relative;color:var(--ymt-text-color);border-radius:var(--ymt-corner-s);margin:var(--_tile-margin);gap:var(--ymt-spacing-m)}:host .tile .slots{display:grid;grid-template-rows:repeat(4,auto);grid-template-columns:auto;grid-template-areas:\"title-description title-description actions\" \"meta meta aside\" \"badges badges badges\" \"ext ext ext\";flex:1}:host .tile [data-slot]{-webkit-user-select:none;user-select:none;display:grid;align-self:baseline;word-break:break-word}:host .tile [data-slot=icon]{--icon-renderer-icon-size: var(--_tile-icon-size);grid-area:icon;display:flex;align-self:flex-start}:host .tile [data-slot=title-description]{grid-area:title-description;display:grid;grid-template-areas:\"title\" \"description\";align-self:flex-start}:host .tile [data-slot=title]{font:var(--_tile-font-title);grid-area:title;align-self:flex-start;--tile-slot-padding: 0}:host .tile [data-slot=description]{grid-area:description;font:var(--_tile-font-description);color:var(--ymt-text-color-subtle);--tile-slot-padding: 0}:host .tile [data-slot=meta]{grid-area:meta;font:var(--_tile-font-meta);color:var(--ymt-text-color-subtle);--tile-slot-padding: var(--ymt-spacing-2xs) var(--ymt-spacing-2xs) var(--ymt-spacing-2xs) 0}:host .tile [data-slot=aside]{flex:0 0 auto;grid-area:aside;font:var(--_tile-font-aside);color:var(--ymt-text-color-subtle);justify-content:flex-end;text-align:right;--tile-slot-padding: var(--ymt-spacing-2xs)}:host .tile [data-slot=actions]{opacity:.2;transition:opacity var(--_transition-duration);pointer-events:none;display:flex;justify-content:flex-end;padding-block-end:var(--ymt-spacing-2xs);gap:var(--ymt-spacing-3xs)}:host .tile:hover [data-slot=actions]{opacity:1;pointer-events:all}:host .tile [data-slot=actions]{grid-area:actions;flex:0 0 auto;display:flex;align-items:start}:host .tile [data-slot=actions] button{gap:2px}:host .tile [data-slot=badges]{grid-area:badges;justify-self:end;flex:0 0 auto}:host .tile .extension{grid-area:ext}\n"] }]
651
- }], propDecorators: { iconSlot: [{ type: i0.ContentChild, args: ['iconSlot', { ...{
652
- descendants: true
653
- }, isSignal: true }] }], titleSlot: [{ type: i0.ContentChild, args: ['titleSlot', { isSignal: true }] }], descriptionSlot: [{ type: i0.ContentChild, args: ['descriptionSlot', { isSignal: true }] }], asideSlot: [{ type: i0.ContentChild, args: ['asideSlot', { isSignal: true }] }], actionsSlot: [{ type: i0.ContentChild, args: ['actionsSlot', { ...{
654
- descendants: true
655
- }, isSignal: true }] }], badgesSlot: [{ type: i0.ContentChild, args: ['badgesSlot', { isSignal: true }] }], metaSlot: [{ type: i0.ContentChild, args: ['metaSlot', { isSignal: true }] }], extensionSlot: [{ type: i0.ContentChild, args: ['extensionSlot', { isSignal: true }] }] } });
656
-
657
- class YuvListModule {
658
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: YuvListModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
659
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: YuvListModule, imports: [ListComponent, ListItemDirective, ListTileComponent], exports: [ListComponent, ListItemDirective, ListTileComponent] }); }
660
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: YuvListModule, imports: [ListComponent, ListTileComponent] }); }
661
- }
662
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: YuvListModule, decorators: [{
663
- type: NgModule,
664
- args: [{
665
- imports: [ListComponent, ListItemDirective, ListTileComponent],
666
- exports: [ListComponent, ListItemDirective, ListTileComponent]
667
- }]
668
- }] });
669
7
 
670
8
  /**
671
9
  * Generated bundle index. Do not edit.
672
10
  */
673
-
674
- export { ListComponent, ListItemDirective, ListTileComponent, YuvListModule };
675
11
  //# sourceMappingURL=yuuvis-client-framework-list.mjs.map