@yuuvis/client-framework 2.6.3 → 2.8.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 (45) hide show
  1. package/common/lib/components/busy-overlay/busy-overlay.component.d.ts +0 -1
  2. package/datepicker/lib/calendar/calendar.component.d.ts +1 -2
  3. package/datepicker/lib/date-input/date-input.component.d.ts +1 -1
  4. package/fesm2022/yuuvis-client-framework-common.mjs +1 -4
  5. package/fesm2022/yuuvis-client-framework-common.mjs.map +1 -1
  6. package/fesm2022/yuuvis-client-framework-datepicker.mjs +32 -29
  7. package/fesm2022/yuuvis-client-framework-datepicker.mjs.map +1 -1
  8. package/fesm2022/yuuvis-client-framework-forms.mjs +7 -4
  9. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
  10. package/fesm2022/yuuvis-client-framework-list.mjs +96 -62
  11. package/fesm2022/yuuvis-client-framework-list.mjs.map +1 -1
  12. package/fesm2022/yuuvis-client-framework-object-flavor.mjs +2 -2
  13. package/fesm2022/yuuvis-client-framework-object-flavor.mjs.map +1 -1
  14. package/fesm2022/yuuvis-client-framework-object-versions.mjs +1 -1
  15. package/fesm2022/yuuvis-client-framework-object-versions.mjs.map +1 -1
  16. package/fesm2022/yuuvis-client-framework-query-list.mjs +284 -0
  17. package/fesm2022/yuuvis-client-framework-query-list.mjs.map +1 -0
  18. package/fesm2022/yuuvis-client-framework-tile-list.mjs +92 -203
  19. package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
  20. package/fesm2022/yuuvis-client-framework-tree.mjs +8 -5
  21. package/fesm2022/yuuvis-client-framework-tree.mjs.map +1 -1
  22. package/fesm2022/yuuvis-client-framework.mjs +716 -160
  23. package/fesm2022/yuuvis-client-framework.mjs.map +1 -1
  24. package/lib/config/halo-focus-defaults/halo-excluded-elements.const.d.ts +26 -0
  25. package/lib/config/halo-focus-defaults/halo-focus-navigation-keys.const.d.ts +25 -0
  26. package/lib/config/halo-focus-defaults/halo-focus-offset.const.d.ts +25 -0
  27. package/lib/config/halo-focus-defaults/halo-focus-styles.const.d.ts +26 -0
  28. package/lib/config/halo-focus-defaults/index.d.ts +4 -0
  29. package/lib/config/index.d.ts +1 -0
  30. package/lib/models/halo-focus-config/halo-focus-config.model.d.ts +48 -0
  31. package/lib/models/halo-focus-config/index.d.ts +1 -0
  32. package/lib/models/index.d.ts +1 -0
  33. package/lib/providers/halo-focus/index.d.ts +1 -0
  34. package/lib/providers/halo-focus/provide-halo-focus.d.ts +58 -6
  35. package/lib/providers/index.d.ts +1 -1
  36. package/lib/services/halo-focus/halo-focus.service.d.ts +80 -17
  37. package/lib/services/halo-utility/halo-utility.service.d.ts +230 -0
  38. package/lib/services/index.d.ts +1 -0
  39. package/list/lib/list.component.d.ts +35 -6
  40. package/package.json +19 -15
  41. package/query-list/README.md +3 -0
  42. package/query-list/index.d.ts +2 -0
  43. package/query-list/lib/query-list.component.d.ts +152 -0
  44. package/query-list/lib/query-list.module.d.ts +7 -0
  45. package/tile-list/lib/tile-list/tile-list.component.d.ts +60 -34
@@ -0,0 +1,230 @@
1
+ import { HaloFocusConfig } from '../../models';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Utility service providing helper methods for the Halo Focus feature.
5
+ *
6
+ * This service contains pure utility functions for:
7
+ * - Element validation (focusability, visibility, focus-visible state)
8
+ * - Material form field detection and exclusion logic
9
+ * - Style calculations (colors, offsets, positioning)
10
+ * - DOM traversal (finding halo containers, checking parent visibility)
11
+ * - Halo element manipulation (size, color, position)
12
+ *
13
+ * **Scope & Performance:**
14
+ * This service is intentionally NOT provided in root (`providedIn: 'root'` is omitted).
15
+ * Instead, it's provided locally via `provideHaloFocus()`, ensuring it's only instantiated
16
+ * when the Halo Focus feature is actually used. This optimization prevents unnecessary
17
+ * service creation in applications that don't use halo focus.
18
+ *
19
+ * **Note:** This service is used exclusively by `HaloFocusService` and should not be
20
+ * injected or used elsewhere in the application.
21
+ *
22
+ * @internal
23
+ */
24
+ export declare class HaloUtilityService {
25
+ /**
26
+ * Checks if an element is focusable (can receive keyboard focus).
27
+ *
28
+ * An element is considered focusable if:
29
+ * - It has a non-negative tabIndex (>= 0), OR
30
+ * - It's a natively focusable element (A, BUTTON, INPUT, SELECT, TEXTAREA), OR
31
+ * - It has contentEditable enabled
32
+ *
33
+ * @param element - Element to check
34
+ * @returns true if element can receive focus, false otherwise
35
+ */
36
+ isFocusable(element: Element | null): element is HTMLElement;
37
+ /**
38
+ * Checks if an element is inside a Material form field (mat-form-field).
39
+ *
40
+ * Traverses up the DOM tree from the element to check if any parent
41
+ * has the `mat-form-field` tag name. This is used to determine if
42
+ * certain elements should skip halo focus because they're already
43
+ * styled by Angular Material.
44
+ *
45
+ * **Search Scope:**
46
+ * - Starts from element itself
47
+ * - Stops at document.body
48
+ * - Returns true on first mat-form-field match
49
+ *
50
+ * @param element - The element to check
51
+ * @returns true if element is inside a mat-form-field, false otherwise
52
+ */
53
+ isElementInsideMatFormField(element: HTMLElement): boolean;
54
+ /**
55
+ * Determines if an element should be excluded from halo focus when inside mat-form-field.
56
+ *
57
+ * Checks two conditions:
58
+ * 1. Element tag name matches one of the excluded selectors (input, mat-select, etc.)
59
+ * 2. Element is inside a mat-form-field component
60
+ *
61
+ * If both conditions are true, the element should skip halo focus because
62
+ * Angular Material already provides adequate focus styling.
63
+ *
64
+ * **Excluded Elements (configurable via haloExcludedElementsInMatFormField):**
65
+ * - `input` elements inside mat-form-field
66
+ * - `textarea` elements inside mat-form-field
67
+ * - `mat-select` elements inside mat-form-field
68
+ *
69
+ * **Note:** Elements outside mat-form-field will NOT be skipped, even if
70
+ * their tag matches the exclusion list.
71
+ *
72
+ * @param element - The focused element to check
73
+ * @returns true if element should be skipped (no halo), false if halo should be shown
74
+ */
75
+ shouldSkipElementInMatFormField(element: HTMLElement): boolean;
76
+ /**
77
+ * Determines if an element should display the halo based on :focus-visible state.
78
+ *
79
+ * This method respects the CSS :focus-visible pseudo-class, which indicates that
80
+ * focus was triggered by keyboard navigation (not mouse clicks). The halo only appears
81
+ * when both conditions are met:
82
+ * 1. Element matches :focus-visible (browser determines this)
83
+ * 2. Last user interaction was via keyboard (tracked by service)
84
+ *
85
+ * **Fallback:** If browser doesn't support :focus-visible, falls back to checking
86
+ * lastInteractionWasKeyboard only.
87
+ *
88
+ * @param element - The currently focused element
89
+ * @param lastInteractionWasKeyboard - Whether the last interaction was a keyboard event
90
+ * @returns true if halo should be visible, false otherwise
91
+ */
92
+ matchesFocusVisible(element: HTMLElement, lastInteractionWasKeyboard: boolean): boolean;
93
+ /**
94
+ * Checks if an element is actually visible on the page.
95
+ *
96
+ * Performs comprehensive visibility checks including:
97
+ * - Element has non-zero dimensions (width and height > 0)
98
+ * - Element is not hidden via CSS (display: none, visibility: hidden, opacity: 0)
99
+ * - Element is not clipped by parent containers with overflow: hidden/clip
100
+ * - All parent elements in the hierarchy are visible
101
+ *
102
+ * This prevents the halo from appearing around technically focused but visually
103
+ * hidden elements (e.g., elements in collapsed sections, off-screen elements).
104
+ *
105
+ * @param element - Element to check for visibility
106
+ * @returns true if element is visible to the user, false otherwise
107
+ */
108
+ isElementVisible(element: HTMLElement): boolean;
109
+ /**
110
+ * Recursively checks if all parent elements are visible and not clipping the target element.
111
+ *
112
+ * Traverses up the DOM tree from the element to document.body, checking each parent for:
113
+ * - Hidden state (display: none, visibility: hidden, opacity: 0)
114
+ * - Overflow clipping (overflow: hidden/clip) that completely hides the element
115
+ *
116
+ * If any parent has overflow clipping, calculates the visible intersection area.
117
+ * Returns false if element is completely clipped (no visible area).
118
+ *
119
+ * @param element - The element whose parents should be checked
120
+ * @param rect - The bounding rectangle of the element
121
+ * @returns true if element has visible area within all parent containers, false otherwise
122
+ */
123
+ isParentVisible(element: HTMLElement, rect: DOMRect): boolean;
124
+ /**
125
+ * Generates the complete CSS styles for the halo element, merging defaults with custom config.
126
+ *
127
+ * Takes the base styles from `haloFocusStyles` constant and overrides specific properties
128
+ * if custom configuration is provided. This allows global style customization while
129
+ * maintaining all required base styles.
130
+ *
131
+ * **Configurable Properties:**
132
+ * - Inner color (via config.innerColor)
133
+ * - Outer color (via config.outerColor)
134
+ *
135
+ * **Non-configurable Properties:**
136
+ * - position, pointerEvents, zIndex, opacity, transform (always use defaults)
137
+ *
138
+ * @param config - Optional global configuration object
139
+ * @returns Complete CSS style declaration object for the halo element
140
+ */
141
+ getHaloFocusStyles(config?: HaloFocusConfig): Partial<CSSStyleDeclaration>;
142
+ /**
143
+ * Finds the nearest parent element marked as a halo container.
144
+ *
145
+ * Traverses up the DOM tree looking for an element with the `halo-container` attribute.
146
+ * Container elements can define default halo styles (color, offset) that apply to all
147
+ * their focused children, unless overridden by child-specific halo-* attributes.
148
+ *
149
+ * **Search Scope:**
150
+ * - Starts from element's immediate parent
151
+ * - Stops at document.body (does not check body itself)
152
+ * - Returns first matching ancestor
153
+ *
154
+ * @param element - The focused element to search from
155
+ * @returns The nearest halo container element, or null if none found
156
+ */
157
+ getHaloContainer(element: HTMLElement): HTMLElement | null;
158
+ /**
159
+ * Converts any CSS color format to rgba with specified alpha transparency.
160
+ *
161
+ * Handles multiple color formats:
162
+ * - **rgba**: Replaces existing alpha value
163
+ * - **rgb**: Converts to rgba by appending alpha
164
+ * - **Hex** (#RRGGBB): Converts to rgba format
165
+ * - **Named colors**: Uses modern CSS `color-mix` function with alpha
166
+ *
167
+ * Used internally to create outer colors with reduced opacity from inner colors.
168
+ *
169
+ * @param color - CSS color in any valid format (rgba, rgb, hex, named)
170
+ * @param alpha - Alpha transparency value (0-1)
171
+ * @returns Color in rgba format with specified alpha
172
+ */
173
+ getColorWithAlpha(color: string, alpha: number): string;
174
+ /**
175
+ * Calculates the offset (distance) between the halo border and element edges.
176
+ *
177
+ * Determines offset using the following priority order:
178
+ * 1. **Element's own attributes** (highest priority):
179
+ * - `halo-offset="value"` - Custom numeric value
180
+ * 2. **Parent container attributes** (if element has no offset):
181
+ * - `halo-container-offset="value"`
182
+ * 3. **Default offset** (if nothing specified): 3px
183
+ *
184
+ * @param element - The focused element to calculate offset for
185
+ * @returns Offset value in pixels
186
+ */
187
+ getTargetOffset(element: HTMLElement | null): number;
188
+ /**
189
+ * Applies custom color styling to the halo element based on element or container attributes.
190
+ *
191
+ * Color resolution priority:
192
+ * 1. **Element's own color**: `halo-color="color"` attribute (highest priority)
193
+ * 2. **Container's color**: `halo-container-color="color"` from nearest halo container
194
+ * 3. **Default color**: From global config or base styles (if no custom color found)
195
+ *
196
+ * When custom color is found:
197
+ * - Sets inner color (2px solid border) with the custom color
198
+ * - Sets outer color (shadow) to match, with 20% alpha transparency for subtle depth
199
+ *
200
+ * When no custom color:
201
+ * - Resets to default styles from config or haloFocusStyles constant
202
+ *
203
+ * @param element - The focused element (checked for halo-color attribute)
204
+ * @param haloElement - The halo DIV element to apply styles to
205
+ * @param config - Optional global config for default colors
206
+ */
207
+ setCustomColor(element: HTMLElement, haloElement: HTMLDivElement, config?: HaloFocusConfig): void;
208
+ /**
209
+ * Positions and sizes the halo element to surround the focused element.
210
+ *
211
+ * Calculates halo dimensions and position based on:
212
+ * - Element's bounding rectangle (viewport-relative position)
213
+ * - Calculated offset from getTargetOffset() (custom or default)
214
+ * - Element's border-radius for matching rounded corners
215
+ *
216
+ * **Calculation Details:**
217
+ * - Position: Element's top/left minus offset (for outside positioning)
218
+ * - Size: Element's width/height plus 2× offset (to extend on all sides)
219
+ * - Border radius: Inherited from focused element's computed style
220
+ *
221
+ * Uses Math.floor for position and Math.ceil for dimensions to prevent
222
+ * subpixel rendering issues and ensure full element coverage.
223
+ *
224
+ * @param currentElement - The currently focused element to surround
225
+ * @param haloElement - The halo DIV element to position and size
226
+ */
227
+ setHaloElementSize(currentElement: HTMLElement, haloElement: HTMLDivElement): void;
228
+ static ɵfac: i0.ɵɵFactoryDeclaration<HaloUtilityService, never>;
229
+ static ɵprov: i0.ɵɵInjectableDeclaration<HaloUtilityService>;
230
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './halo-focus/halo-focus.service';
2
2
  export * from './snack-bar/snack-bar.interface';
3
3
  export * from './snack-bar/snack-bar.service';
4
+ export * from './halo-utility/halo-utility.service';
@@ -4,7 +4,7 @@ import { BooleanInput } from '@angular/cdk/coercion';
4
4
  import * as i0 from "@angular/core";
5
5
  /**
6
6
  * Component rendering a simple list of items. It supports keyboard
7
- * navigation as well as accessibility. To create a list just wrap
7
+ * navigation and takes care of accessibility. To create a list just wrap
8
8
  * `yuvListItem` elements into this component:
9
9
  *
10
10
  * ```html
@@ -19,12 +19,16 @@ export declare class ListComponent implements AfterContentInit, OnDestroy {
19
19
  onKeydown(event: KeyboardEvent): void;
20
20
  onFocus(): void;
21
21
  items: import("@angular/core").Signal<readonly ListItemDirective[]>;
22
- private _keyManager;
23
- private _selection;
24
- private _lastSelection?;
22
+ /**
23
+ * Function that returns `true` if selection changes should be prevented.
24
+ * This can be used to temporarily block selection changes, e.g. while
25
+ * there is a pending change inside another component that refers to the
26
+ * current selection.
27
+ */
25
28
  preventChangeUntil: import("@angular/core").InputSignal<() => boolean>;
26
29
  /**
27
30
  * If `true`, multiple items can be selected at once.
31
+ * @default false
28
32
  */
29
33
  multiselect: import("@angular/core").InputSignal<boolean>;
30
34
  /**
@@ -35,10 +39,26 @@ export declare class ListComponent implements AfterContentInit, OnDestroy {
35
39
  * @default false
36
40
  */
37
41
  selfHandleSelection: import("@angular/core").InputSignal<boolean>;
42
+ /**
43
+ * By default the list handles click events on its items to select them.
44
+ * If this input is set to `true`, the parent component has to handle
45
+ * click events itself and call the `select()` method accordingly.
46
+ *
47
+ * If you for example use the `ClickDoubleDirective` on the list items,
48
+ * you have to set this input to `true` to prevent the list from
49
+ * selecting items on single click.
50
+ * @default false
51
+ */
52
+ selfHandleClick: import("@angular/core").InputSignal<boolean>;
53
+ /**
54
+ * If `true`, the list will select an item automatically on initialization.
55
+ * First, list will search for an item item that has the "selected"-attribute
56
+ * and is not disabled. If no such item exists, the first item will be selected.
57
+ * @default false
58
+ */
38
59
  autoSelect: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
39
60
  /**
40
61
  * Emits the selected items indices.
41
- * @type {output<number[]>}
42
62
  */
43
63
  itemSelect: import("@angular/core").OutputEmitterRef<number[]>;
44
64
  /**
@@ -54,7 +74,16 @@ export declare class ListComponent implements AfterContentInit, OnDestroy {
54
74
  */
55
75
  disableSelection: import("@angular/core").InputSignal<boolean>;
56
76
  focus(): void;
77
+ /**
78
+ * Select multiple items by their indices.
79
+ */
57
80
  multiSelect(index: number[]): void;
81
+ /**
82
+ * Selects a single item by its index.
83
+ * @param index Index of the item to select.
84
+ * @param shiftKey If `true`, selection will be extended from the last selected item to the given index.
85
+ * @param ctrlKey If `true`, the item at the given index will be toggled in the selection.
86
+ */
58
87
  select(index: number, shiftKey?: boolean, ctrlKey?: boolean): void;
59
88
  /**
60
89
  * Clear the current selection.
@@ -64,5 +93,5 @@ export declare class ListComponent implements AfterContentInit, OnDestroy {
64
93
  ngAfterContentInit(): void;
65
94
  ngOnDestroy(): void;
66
95
  static ɵfac: i0.ɵɵFactoryDeclaration<ListComponent, never>;
67
- static ɵcmp: i0.ɵɵComponentDeclaration<ListComponent, "yuv-list", never, { "preventChangeUntil": { "alias": "preventChangeUntil"; "required": false; "isSignal": true; }; "multiselect": { "alias": "multiselect"; "required": false; "isSignal": true; }; "selfHandleSelection": { "alias": "selfHandleSelection"; "required": false; "isSignal": true; }; "autoSelect": { "alias": "autoSelect"; "required": false; "isSignal": true; }; "disableSelection": { "alias": "disableSelection"; "required": false; "isSignal": true; }; }, { "itemSelect": "itemSelect"; "itemFocus": "itemFocus"; }, ["items"], ["*"], true, never>;
96
+ static ɵcmp: i0.ɵɵComponentDeclaration<ListComponent, "yuv-list", never, { "preventChangeUntil": { "alias": "preventChangeUntil"; "required": false; "isSignal": true; }; "multiselect": { "alias": "multiselect"; "required": false; "isSignal": true; }; "selfHandleSelection": { "alias": "selfHandleSelection"; "required": false; "isSignal": true; }; "selfHandleClick": { "alias": "selfHandleClick"; "required": false; "isSignal": true; }; "autoSelect": { "alias": "autoSelect"; "required": false; "isSignal": true; }; "disableSelection": { "alias": "disableSelection"; "required": false; "isSignal": true; }; }, { "itemSelect": "itemSelect"; "itemFocus": "itemFocus"; }, ["items"], ["*"], true, never>;
68
97
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuuvis/client-framework",
3
- "version": "2.6.3",
3
+ "version": "2.8.0",
4
4
  "author": "OPTIMAL SYSTEMS GmbH <npm@optimal-systems.de>",
5
5
  "license": "MIT",
6
6
  "peerDependencies": {
@@ -8,15 +8,15 @@
8
8
  "@angular/common": "^19.2.1",
9
9
  "@angular/core": "^19.2.1",
10
10
  "angular-gridster2": "^19.0.0",
11
- "@yuuvis/client-core": "^2.6.3",
12
- "@yuuvis/client-shell-core": "^2.6.3",
11
+ "@yuuvis/client-core": "^2.8.0",
12
+ "@yuuvis/client-shell-core": "^2.8.0",
13
13
  "ng-dynamic-component": "^10.8.2",
14
14
  "modern-normalize": "^3.0.1"
15
15
  },
16
16
  "dependencies": {
17
17
  "@angular/material": "^19.2.15",
18
18
  "@ngrx/signals": "^19.2.0",
19
- "@yuuvis/material": "2.6.3",
19
+ "@yuuvis/material": "2.8.0",
20
20
  "@yuuvis/media-viewer": "^2.0.12",
21
21
  "angular-split": "^19.0.0",
22
22
  "vis-network": "^10.0.2",
@@ -108,14 +108,14 @@
108
108
  "types": "./object-versions/index.d.ts",
109
109
  "default": "./fesm2022/yuuvis-client-framework-object-versions.mjs"
110
110
  },
111
- "./overflow-menu": {
112
- "types": "./overflow-menu/index.d.ts",
113
- "default": "./fesm2022/yuuvis-client-framework-overflow-menu.mjs"
114
- },
115
111
  "./overflow-hidden": {
116
112
  "types": "./overflow-hidden/index.d.ts",
117
113
  "default": "./fesm2022/yuuvis-client-framework-overflow-hidden.mjs"
118
114
  },
115
+ "./overflow-menu": {
116
+ "types": "./overflow-menu/index.d.ts",
117
+ "default": "./fesm2022/yuuvis-client-framework-overflow-menu.mjs"
118
+ },
119
119
  "./pagination": {
120
120
  "types": "./pagination/index.d.ts",
121
121
  "default": "./fesm2022/yuuvis-client-framework-pagination.mjs"
@@ -124,6 +124,10 @@
124
124
  "types": "./popout/index.d.ts",
125
125
  "default": "./fesm2022/yuuvis-client-framework-popout.mjs"
126
126
  },
127
+ "./query-list": {
128
+ "types": "./query-list/index.d.ts",
129
+ "default": "./fesm2022/yuuvis-client-framework-query-list.mjs"
130
+ },
127
131
  "./renderer": {
128
132
  "types": "./renderer/index.d.ts",
129
133
  "default": "./fesm2022/yuuvis-client-framework-renderer.mjs"
@@ -140,22 +144,22 @@
140
144
  "types": "./sort/index.d.ts",
141
145
  "default": "./fesm2022/yuuvis-client-framework-sort.mjs"
142
146
  },
143
- "./tile-list": {
144
- "types": "./tile-list/index.d.ts",
145
- "default": "./fesm2022/yuuvis-client-framework-tile-list.mjs"
146
- },
147
147
  "./split-view": {
148
148
  "types": "./split-view/index.d.ts",
149
149
  "default": "./fesm2022/yuuvis-client-framework-split-view.mjs"
150
150
  },
151
- "./upload-progress": {
152
- "types": "./upload-progress/index.d.ts",
153
- "default": "./fesm2022/yuuvis-client-framework-upload-progress.mjs"
151
+ "./tile-list": {
152
+ "types": "./tile-list/index.d.ts",
153
+ "default": "./fesm2022/yuuvis-client-framework-tile-list.mjs"
154
154
  },
155
155
  "./tree": {
156
156
  "types": "./tree/index.d.ts",
157
157
  "default": "./fesm2022/yuuvis-client-framework-tree.mjs"
158
158
  },
159
+ "./upload-progress": {
160
+ "types": "./upload-progress/index.d.ts",
161
+ "default": "./fesm2022/yuuvis-client-framework-upload-progress.mjs"
162
+ },
159
163
  "./widget-grid": {
160
164
  "types": "./widget-grid/index.d.ts",
161
165
  "default": "./fesm2022/yuuvis-client-framework-widget-grid.mjs"
@@ -0,0 +1,3 @@
1
+ # @yuuvis/client-framework/query-list
2
+
3
+ Secondary entry point of `@yuuvis/client-framework`. It can be used by importing from `@yuuvis/client-framework/query-list`.
@@ -0,0 +1,2 @@
1
+ export * from './lib/query-list.module';
2
+ export * from './lib/query-list.component';
@@ -0,0 +1,152 @@
1
+ import { BooleanInput } from '@angular/cdk/coercion';
2
+ import { TemplateRef } from '@angular/core';
3
+ import { PageEvent } from '@angular/material/paginator';
4
+ import { SearchQuery, SearchResultItem } from '@yuuvis/client-core';
5
+ import { ListComponent } from '@yuuvis/client-framework/list';
6
+ import { Pagination } from '@yuuvis/client-framework/pagination';
7
+ import * as i0 from "@angular/core";
8
+ /**
9
+ * Component to display a list of items based on a search query.
10
+ * It will execute the query and render the results using the provided item template.
11
+ *
12
+ * The component supports pagination, multi-selection, and drag selection.
13
+ *
14
+ * If you don't provide a transformer function, the raw SearchResultItem objects will be
15
+ * used as items and passed to the template. The transformer function allows you to map
16
+ * the SearchResultItem objects to a custom format before rendering.
17
+ *
18
+ * Example usage:
19
+ * ```html
20
+ * <yuv-query-list [transformer]="transformResult" [query]="query" (itemSelect)="onItemSelect($event)">
21
+
22
+ <!-- template used to render result item -->
23
+ <ng-template #yuvQueryListItem let-item>
24
+ <yuv-list-tile>
25
+ <ng-template #titleSlot>{{ item.id }}</ng-template>
26
+ <ng-template #descriptionSlot>{{ item.modified }}</ng-template>
27
+ </yuv-list-tile>
28
+ </ng-template>
29
+
30
+ <!-- Content to display when the list is empty -->
31
+ <ng-template #yuvQueryListEmpty>
32
+ <div>No documents found.</div>
33
+ </ng-template>
34
+
35
+ </yuv-query-list>
36
+ * ```
37
+ *
38
+ * ```ts
39
+ * @Component({...})
40
+ * export class TestQueryListComponent {
41
+ * query = 'SELECT * FROM system:document';
42
+ *
43
+ * transformResult = (items: SearchResultItem[]) =>
44
+ * items.map((item) => ({
45
+ * id: item.fields.get(BaseObjectTypeField.OBJECT_ID),
46
+ * modified: item.fields.get(BaseObjectTypeField.MODIFICATION_DATE)
47
+ * }));
48
+ * } *
49
+ * ```
50
+ */
51
+ export declare class QueryListComponent {
52
+ #private;
53
+ list: import("@angular/core").Signal<ListComponent>;
54
+ itemTemplate: import("@angular/core").Signal<TemplateRef<any> | undefined>;
55
+ emptyTemplate: import("@angular/core").Signal<TemplateRef<any> | undefined>;
56
+ isTouchDevice: boolean;
57
+ /**
58
+ * The query to execute (SearchQuery object or CMIS query string).
59
+ */
60
+ query: import("@angular/core").InputSignal<string | SearchQuery | null | undefined>;
61
+ /**
62
+ * Optional transformer function to map SearchResultItem to a custom format.
63
+ */
64
+ transformer: import("@angular/core").InputSignal<((items: SearchResultItem[]) => unknown[]) | null | undefined>;
65
+ /**
66
+ * Function that returns `true` if selection changes should be prevented.
67
+ * This can be used to temporarily block selection changes, e.g. while
68
+ * there is a pending change inside another component that refers to the
69
+ * current selection.
70
+ */
71
+ preventChangeUntil: import("@angular/core").InputSignal<() => boolean>;
72
+ /**
73
+ * If `true`, the list will select an item automatically on initialization.
74
+ * First, list will search for an item item that has the "selected"-attribute
75
+ * and is not disabled. If no such item exists, the first item will be selected.
76
+ * @default false
77
+ */
78
+ autoSelect: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
79
+ /**
80
+ * Event emitted when items are selected. Emits an array of selected item indices.
81
+ *
82
+ */
83
+ itemSelect: import("@angular/core").OutputEmitterRef<number[]>;
84
+ /**
85
+ * Event emitted during drag selection, providing the current selection of item indices.
86
+ */
87
+ dragSelectChange: import("@angular/core").OutputEmitterRef<number[]>;
88
+ /**
89
+ * Event emitted when an item is double-clicked, providing the index of the item.
90
+ */
91
+ itemDoubleClick: import("@angular/core").OutputEmitterRef<number>;
92
+ /**
93
+ * Event emitted when the query result is available, providing total count of items.
94
+ */
95
+ queryResult: import("@angular/core").OutputEmitterRef<{
96
+ totalCount: number;
97
+ }>;
98
+ /**
99
+ * The list of result items after applying the optional transformer.
100
+ */
101
+ resultItems: import("@angular/core").Signal<unknown[]>;
102
+ /**
103
+ * Number of items to fetch per page when executing the query.
104
+ * @default SearchService.DEFAULT_QUERY_SIZE
105
+ */
106
+ pageSize: import("@angular/core").InputSignal<number>;
107
+ /**
108
+ * Enables or disables drag selection of items. If `true`, users can select multiple items by dragging the mouse.
109
+ * @default true
110
+ */
111
+ enableDragSelect: import("@angular/core").InputSignal<boolean>;
112
+ /**
113
+ * Sets up the ability to select multiple tiles
114
+ * @default false
115
+ */
116
+ multiselect: import("@angular/core").InputSignal<boolean>;
117
+ /**
118
+ * If `true`, the component will handle selection itself. This means that
119
+ * the parent component will be responsible for styling the selected and
120
+ * focused items. If `false`, the component will take care of visualizing
121
+ * the selection and focus states.
122
+ * @default false
123
+ */
124
+ selfHandleSelection: import("@angular/core").InputSignal<boolean>;
125
+ /**
126
+ * Indicator signal whether a query is currently being executed.
127
+ * You could use this to show a loading indicator in the UI.
128
+ */
129
+ busy: import("@angular/core").WritableSignal<boolean>;
130
+ pagination?: Pagination;
131
+ onItemClick(idx: number, event: MouseEvent): void;
132
+ onItemDoubleClick(idx: number, event: MouseEvent): void;
133
+ onDragSelectChange(sel: number[]): void;
134
+ onDragSelect(sel: number[]): void;
135
+ /**
136
+ * Selects multiple items in the list.
137
+ */
138
+ multiSelect(index: number[]): void;
139
+ /**
140
+ * Clear the current selection.
141
+ * @param silent If `true`, the `itemSelect` event will not be emitted.
142
+ */
143
+ clear(silent?: boolean): void;
144
+ /**
145
+ * Refreshes the list by re-executing the current query/page.
146
+ */
147
+ refresh(): void;
148
+ changePage(pe: PageEvent): void;
149
+ goToPage(page: number): void;
150
+ static ɵfac: i0.ɵɵFactoryDeclaration<QueryListComponent, never>;
151
+ static ɵcmp: i0.ɵɵComponentDeclaration<QueryListComponent, "yuv-query-list", never, { "query": { "alias": "query"; "required": false; "isSignal": true; }; "transformer": { "alias": "transformer"; "required": false; "isSignal": true; }; "preventChangeUntil": { "alias": "preventChangeUntil"; "required": false; "isSignal": true; }; "autoSelect": { "alias": "autoSelect"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "enableDragSelect": { "alias": "enableDragSelect"; "required": false; "isSignal": true; }; "multiselect": { "alias": "multiselect"; "required": false; "isSignal": true; }; "selfHandleSelection": { "alias": "selfHandleSelection"; "required": false; "isSignal": true; }; }, { "itemSelect": "itemSelect"; "dragSelectChange": "dragSelectChange"; "itemDoubleClick": "itemDoubleClick"; "queryResult": "queryResult"; }, ["itemTemplate", "emptyTemplate"], never, true, never>;
152
+ }
@@ -0,0 +1,7 @@
1
+ import * as i0 from "@angular/core";
2
+ import * as i1 from "./query-list.component";
3
+ export declare class YuvQueryListModule {
4
+ static ɵfac: i0.ɵɵFactoryDeclaration<YuvQueryListModule, never>;
5
+ static ɵmod: i0.ɵɵNgModuleDeclaration<YuvQueryListModule, never, [typeof i1.QueryListComponent], [typeof i1.QueryListComponent]>;
6
+ static ɵinj: i0.ɵɵInjectorDeclaration<YuvQueryListModule>;
7
+ }