@yuuvis/client-framework 2.1.11 → 2.1.13

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 (26) hide show
  1. package/fesm2022/yuuvis-client-framework-forms.mjs +56 -12
  2. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
  3. package/fesm2022/yuuvis-client-framework-master-details.mjs +0 -4
  4. package/fesm2022/yuuvis-client-framework-master-details.mjs.map +1 -1
  5. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs +2 -2
  6. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs.map +1 -1
  7. package/fesm2022/yuuvis-client-framework-metadata-form.mjs +19 -10
  8. package/fesm2022/yuuvis-client-framework-metadata-form.mjs.map +1 -1
  9. package/fesm2022/yuuvis-client-framework-object-form.mjs +12 -4
  10. package/fesm2022/yuuvis-client-framework-object-form.mjs.map +1 -1
  11. package/fesm2022/yuuvis-client-framework-sort.mjs +120 -0
  12. package/fesm2022/yuuvis-client-framework-sort.mjs.map +1 -0
  13. package/forms/lib/elements/datetime/datetime.component.d.ts +1 -1
  14. package/lib/assets/i18n/de.json +3 -0
  15. package/lib/assets/i18n/en.json +3 -0
  16. package/metadata-form/lib/metadata-form-field/metadata-form-field.component.d.ts +3 -1
  17. package/metadata-form/lib/metadata-form-field/metadata-form-field.interface.d.ts +2 -0
  18. package/metadata-form/lib/object-metadata-element-label.directive.d.ts +2 -2
  19. package/object-form/lib/object-form-element/object-form-element.component.d.ts +1 -0
  20. package/object-form/lib/object-form.service.d.ts +2 -0
  21. package/package.json +12 -8
  22. package/sort/README.md +3 -0
  23. package/sort/index.d.ts +2 -0
  24. package/sort/lib/sort/models/index.d.ts +1 -0
  25. package/sort/lib/sort/models/sort.interface.d.ts +7 -0
  26. package/sort/lib/sort/sort.component.d.ts +19 -0
@@ -0,0 +1,120 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, input, output, signal, effect, linkedSignal, Component } from '@angular/core';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
+ import * as i4 from '@angular/material/button';
5
+ import { MatButtonModule } from '@angular/material/button';
6
+ import { MatDivider } from '@angular/material/divider';
7
+ import * as i2 from '@angular/material/icon';
8
+ import { MatIconModule } from '@angular/material/icon';
9
+ import * as i3 from '@angular/material/menu';
10
+ import { MatMenuModule } from '@angular/material/menu';
11
+ import * as i1 from '@yuuvis/client-core';
12
+ import { SystemService, TranslateService, TranslateModule } from '@yuuvis/client-core';
13
+
14
+ const MATERIAL_MODULES = [MatIconModule, MatMenuModule, MatButtonModule, MatDivider];
15
+ class SortComponent {
16
+ #systemService;
17
+ #rememberSort;
18
+ #reEvaluate;
19
+ constructor() {
20
+ this.#systemService = inject(SystemService);
21
+ this.translate = inject(TranslateService);
22
+ this.sortOptions = input([]);
23
+ this.storageKey = input();
24
+ this.sortChanged = output();
25
+ this.orderOptions = signal([
26
+ { label: this.translate.instant('yuv.sort.ascending'), value: 'asc', type: 'order', selected: true },
27
+ { label: this.translate.instant('yuv.sort.descending'), value: 'desc', type: 'order', selected: false }
28
+ ]);
29
+ this.#rememberSort = effect(() => {
30
+ const storageKey = this.storageKey();
31
+ if (storageKey) {
32
+ const storage = localStorage.getItem(storageKey);
33
+ if (storage) {
34
+ try {
35
+ const data = JSON.parse(storage);
36
+ this.sortFields.update((fields) => fields.map((field) => field.type === 'sort' && field.value === data.field
37
+ ? { ...field, selected: true }
38
+ : field.type === 'order' && field.value === data.order
39
+ ? { ...field, selected: true }
40
+ : { ...field, selected: false }));
41
+ }
42
+ catch (error) {
43
+ console.error('Error parsing sort data from localStorage:', error);
44
+ }
45
+ }
46
+ }
47
+ });
48
+ this.#reEvaluate = signal(null);
49
+ this.sortFields = linkedSignal({
50
+ source: () => ({ sortOptions: this.sortOptions(), orderOptions: this.orderOptions(), evaluate: this.#reEvaluate() }),
51
+ computation: ({ sortOptions, orderOptions }) => [
52
+ ...sortOptions.map((f) => ({
53
+ label: this.#systemService.getLocalizedLabel(f) || f,
54
+ value: f,
55
+ type: 'sort',
56
+ selected: false
57
+ })),
58
+ ...orderOptions
59
+ ]
60
+ });
61
+ this.translate.onLangChange.pipe(takeUntilDestroyed()).subscribe({ next: () => this.#reEvaluate.set(new Date()) });
62
+ }
63
+ selectSort(option) {
64
+ this.sortFields.update((fields) => fields.map((field) => (field.type === option.type ? { ...field, selected: field.value === option.value } : field)));
65
+ const selectedFields = this.sortFields().filter((field) => field.selected);
66
+ const fields = selectedFields.reduce((acc, field) => {
67
+ if (field.type === 'sort')
68
+ acc.field = field.value;
69
+ if (field.type === 'order')
70
+ acc.order = field.value;
71
+ return acc;
72
+ }, { field: '', order: 'asc' });
73
+ const storageKey = this.storageKey();
74
+ storageKey && localStorage.setItem(storageKey, JSON.stringify(fields));
75
+ this.sortChanged.emit(fields);
76
+ }
77
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.12", ngImport: i0, type: SortComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
78
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.12", type: SortComponent, isStandalone: true, selector: "yuv-sort", inputs: { sortOptions: { classPropertyName: "sortOptions", publicName: "sortOptions", isSignal: true, isRequired: false, transformFunction: null }, storageKey: { classPropertyName: "storageKey", publicName: "storageKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortChanged: "sortChanged" }, ngImport: i0, template: `<button mat-icon-button [matMenuTriggerFor]="menu" title="{{ 'yuv.sort.tooltip' | translate }}">
79
+ <mat-icon>swap_vert</mat-icon>
80
+ </button>
81
+
82
+ <mat-menu #menu="matMenu" class="sort-menu" [ariaLabel]="'yuv.sort.tooltip' | translate">
83
+ @for (option of sortFields(); track $index) {
84
+ <button mat-menu-item class="sort-menu-item" [class.selected]="option.selected" (click)="selectSort(option)" [attr.aria-label]="option.label">
85
+ <mat-icon>{{ option.selected ? 'radio_button_checked' : '' }}</mat-icon>
86
+
87
+ <span>{{ option.label }}</span>
88
+ </button>
89
+ @if (sortFields().length - 3 === $index) {
90
+ <mat-divider></mat-divider>
91
+ }
92
+ }
93
+ </mat-menu>`, isInline: true, styles: [":host{display:block}.mat-mdc-menu-item.sort-menu-item.selected .mat-icon{scale:.5}\n"], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i3.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i3.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i3.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }] }); }
94
+ }
95
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.12", ngImport: i0, type: SortComponent, decorators: [{
96
+ type: Component,
97
+ args: [{ selector: 'yuv-sort', imports: [TranslateModule, ...MATERIAL_MODULES], template: `<button mat-icon-button [matMenuTriggerFor]="menu" title="{{ 'yuv.sort.tooltip' | translate }}">
98
+ <mat-icon>swap_vert</mat-icon>
99
+ </button>
100
+
101
+ <mat-menu #menu="matMenu" class="sort-menu" [ariaLabel]="'yuv.sort.tooltip' | translate">
102
+ @for (option of sortFields(); track $index) {
103
+ <button mat-menu-item class="sort-menu-item" [class.selected]="option.selected" (click)="selectSort(option)" [attr.aria-label]="option.label">
104
+ <mat-icon>{{ option.selected ? 'radio_button_checked' : '' }}</mat-icon>
105
+
106
+ <span>{{ option.label }}</span>
107
+ </button>
108
+ @if (sortFields().length - 3 === $index) {
109
+ <mat-divider></mat-divider>
110
+ }
111
+ }
112
+ </mat-menu>`, styles: [":host{display:block}.mat-mdc-menu-item.sort-menu-item.selected .mat-icon{scale:.5}\n"] }]
113
+ }], ctorParameters: () => [] });
114
+
115
+ /**
116
+ * Generated bundle index. Do not edit.
117
+ */
118
+
119
+ export { SortComponent };
120
+ //# sourceMappingURL=yuuvis-client-framework-sort.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yuuvis-client-framework-sort.mjs","sources":["../../../../../libs/yuuvis/client-framework/sort/src/lib/sort/sort.component.ts","../../../../../libs/yuuvis/client-framework/sort/src/yuuvis-client-framework-sort.ts"],"sourcesContent":["import { Component, effect, inject, input, linkedSignal, output, signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatDivider } from '@angular/material/divider';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatMenuModule } from '@angular/material/menu';\nimport { SystemService, TranslateModule, TranslateService } from '@yuuvis/client-core';\nimport { SortMenuOption, SortType } from './models';\n\nconst MATERIAL_MODULES = [MatIconModule, MatMenuModule, MatButtonModule, MatDivider];\n\n@Component({\n selector: 'yuv-sort',\n imports: [TranslateModule, ...MATERIAL_MODULES],\n template: `<button mat-icon-button [matMenuTriggerFor]=\"menu\" title=\"{{ 'yuv.sort.tooltip' | translate }}\">\n <mat-icon>swap_vert</mat-icon>\n </button>\n\n <mat-menu #menu=\"matMenu\" class=\"sort-menu\" [ariaLabel]=\"'yuv.sort.tooltip' | translate\">\n @for (option of sortFields(); track $index) {\n <button mat-menu-item class=\"sort-menu-item\" [class.selected]=\"option.selected\" (click)=\"selectSort(option)\" [attr.aria-label]=\"option.label\">\n <mat-icon>{{ option.selected ? 'radio_button_checked' : '' }}</mat-icon>\n\n <span>{{ option.label }}</span>\n </button>\n @if (sortFields().length - 3 === $index) {\n <mat-divider></mat-divider>\n }\n }\n </mat-menu>`,\n styleUrl: './sort.component.scss'\n})\nexport class SortComponent {\n readonly #systemService = inject(SystemService);\n readonly translate = inject(TranslateService);\n\n sortOptions = input<string[]>([]);\n storageKey = input<string>();\n sortChanged = output<{ field: string; order: SortType }>();\n\n orderOptions = signal<SortMenuOption[]>([\n { label: this.translate.instant('yuv.sort.ascending'), value: 'asc', type: 'order', selected: true },\n { label: this.translate.instant('yuv.sort.descending'), value: 'desc', type: 'order', selected: false }\n ]);\n\n #rememberSort = effect(() => {\n const storageKey = this.storageKey();\n if (storageKey) {\n const storage = localStorage.getItem(storageKey);\n if (storage) {\n try {\n const data = JSON.parse(storage);\n this.sortFields.update((fields) =>\n fields.map((field) =>\n field.type === 'sort' && field.value === data.field\n ? { ...field, selected: true }\n : field.type === 'order' && field.value === data.order\n ? { ...field, selected: true }\n : { ...field, selected: false }\n )\n );\n } catch (error) {\n console.error('Error parsing sort data from localStorage:', error);\n }\n }\n }\n });\n\n #reEvaluate = signal<Date | null>(null);\n sortFields = linkedSignal({\n source: () => ({ sortOptions: this.sortOptions(), orderOptions: this.orderOptions(), evaluate: this.#reEvaluate() }),\n computation: ({ sortOptions, orderOptions }) => [\n ...sortOptions.map((f) => ({\n label: this.#systemService.getLocalizedLabel(f) || f,\n value: f,\n type: 'sort' as const,\n selected: false\n })),\n ...orderOptions\n ]\n });\n\n constructor() {\n this.translate.onLangChange.pipe(takeUntilDestroyed()).subscribe({ next: () => this.#reEvaluate.set(new Date()) });\n }\n\n selectSort(option: SortMenuOption) {\n this.sortFields.update((fields) => fields.map((field) => (field.type === option.type ? { ...field, selected: field.value === option.value } : field)));\n const selectedFields = this.sortFields().filter((field) => field.selected);\n const fields = selectedFields.reduce(\n (acc, field) => {\n if (field.type === 'sort') acc.field = field.value;\n if (field.type === 'order') acc.order = field.value as SortType;\n return acc;\n },\n { field: '', order: 'asc' as SortType }\n );\n\n const storageKey = this.storageKey();\n storageKey && localStorage.setItem(storageKey, JSON.stringify(fields));\n this.sortChanged.emit(fields);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -28,7 +28,7 @@ export declare class DatetimeComponent extends AbstractMatFormField<Date | null>
28
28
  */
29
29
  withTime: import("@angular/core").InputSignal<boolean>;
30
30
  openCalendar(): void;
31
- propagateChange: (fn: () => void) => void;
31
+ propagateChange: (_: any) => void;
32
32
  validationChange: () => void;
33
33
  writeValue(value: any): void;
34
34
  registerOnChange(fn: () => void): void;
@@ -109,6 +109,9 @@
109
109
  "yuv.sequence-list.form.task": "Aufgabe",
110
110
  "yuv.simple-search.label": "Suchen",
111
111
  "yuv.simple-search.submit": "Suche starten",
112
+ "yuv.sort.tooltip": "Sortieren",
113
+ "yuv.sort.ascending": "Aufsteigend",
114
+ "yuv.sort.descending": "Absteigend",
112
115
  "yuv.tile-config.button.close": "Schließen",
113
116
  "yuv.tile-config.button.reset": "Zurücksetzen",
114
117
  "yuv.tile-config.button.save": "Änderungen speichern",
@@ -109,6 +109,9 @@
109
109
  "yuv.sequence-list.form.task": "Task",
110
110
  "yuv.simple-search.label": "Search",
111
111
  "yuv.simple-search.submit": "Submit search",
112
+ "yuv.sort.tooltip": "Sort",
113
+ "yuv.sort.ascending": "Ascending",
114
+ "yuv.sort.descending": "Descending",
112
115
  "yuv.tile-config.button.close": "Close",
113
116
  "yuv.tile-config.button.reset": "Reset",
114
117
  "yuv.tile-config.button.save": "Save changes",
@@ -1,6 +1,7 @@
1
1
  import { TemplateRef } from '@angular/core';
2
2
  import { ObjectTypeField } from '@yuuvis/client-core';
3
3
  import { MetadataFormFieldContext } from './metadata-form-field.interface';
4
+ import { Subject } from 'rxjs';
4
5
  import * as i0 from "@angular/core";
5
6
  import * as i1 from "@yuuvis/client-framework/common";
6
7
  /**
@@ -12,6 +13,7 @@ export declare class MetadataFormFieldComponent {
12
13
  #private;
13
14
  elementTemplate: import("@angular/core").WritableSignal<TemplateRef<any> | undefined>;
14
15
  readonly: boolean;
16
+ formChangedSubject: import("@angular/core").InputSignal<Subject<void> | undefined>;
15
17
  formField: import("@angular/core").InputSignal<ObjectTypeField>;
16
18
  context: import("@angular/core").Signal<MetadataFormFieldContext>;
17
19
  /**
@@ -19,5 +21,5 @@ export declare class MetadataFormFieldComponent {
19
21
  */
20
22
  situation: import("@angular/core").InputSignal<string | undefined>;
21
23
  static ɵfac: i0.ɵɵFactoryDeclaration<MetadataFormFieldComponent, never>;
22
- static ɵcmp: i0.ɵɵComponentDeclaration<MetadataFormFieldComponent, "yuv-metadata-form-field", never, { "formField": { "alias": "field"; "required": true; "isSignal": true; }; "situation": { "alias": "situation"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NoopValueAccessorDirective; inputs: {}; outputs: {}; }]>;
24
+ static ɵcmp: i0.ɵɵComponentDeclaration<MetadataFormFieldComponent, "yuv-metadata-form-field", never, { "formChangedSubject": { "alias": "formChangedSubject"; "required": false; "isSignal": true; }; "formField": { "alias": "field"; "required": true; "isSignal": true; }; "situation": { "alias": "situation"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.NoopValueAccessorDirective; inputs: {}; outputs: {}; }]>;
23
25
  }
@@ -1,5 +1,6 @@
1
1
  import { AbstractControl } from '@angular/forms';
2
2
  import { ObjectTypeField } from '@yuuvis/client-core';
3
+ import { Subject } from 'rxjs';
3
4
  /**
4
5
  * Context provided to each metadata form field.
5
6
  */
@@ -8,4 +9,5 @@ export interface MetadataFormFieldContext {
8
9
  situation: string;
9
10
  field: ObjectTypeField;
10
11
  ctrl?: AbstractControl<any, any>;
12
+ formChangedSubject?: Subject<void>;
11
13
  }
@@ -1,5 +1,5 @@
1
1
  import { OnInit } from '@angular/core';
2
- import { AbstractControl } from '@angular/forms';
2
+ import { MetadataFormFieldContext } from './metadata-form-field/metadata-form-field.interface';
3
3
  import * as i0 from "@angular/core";
4
4
  /**
5
5
  * Directive to apply styles to an object metadata element label based on its control status.
@@ -11,7 +11,7 @@ import * as i0 from "@angular/core";
11
11
  */
12
12
  export declare class ObjectMetadataElementLabelDirective implements OnInit {
13
13
  #private;
14
- yuvObjectMetadataElementLabel: import("@angular/core").InputSignal<AbstractControl<any, any> | undefined>;
14
+ yuvObjectMetadataElementLabel: import("@angular/core").InputSignal<MetadataFormFieldContext | undefined>;
15
15
  ngOnInit(): void;
16
16
  static ɵfac: i0.ɵɵFactoryDeclaration<ObjectMetadataElementLabelDirective, never>;
17
17
  static ɵdir: i0.ɵɵDirectiveDeclaration<ObjectMetadataElementLabelDirective, "[yuvObjectMetadataElementLabel]", never, { "yuvObjectMetadataElementLabel": { "alias": "yuvObjectMetadataElementLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
@@ -7,6 +7,7 @@ import * as i0 from "@angular/core";
7
7
  export declare class ObjectFormElementComponent {
8
8
  #private;
9
9
  createForm: import("@angular/core").WritableSignal<boolean>;
10
+ formChangedSubject: import("rxjs").Subject<void>;
10
11
  formControlName?: string;
11
12
  formElementRef: any;
12
13
  errors?: string[];
@@ -1,12 +1,14 @@
1
1
  import { Type } from '@angular/core';
2
2
  import { ObjectFormControlWrapper, ObjectFormGroup } from '@yuuvis/client-core';
3
3
  import { IObjectFormElementExtension, ObjectFormElementExtension } from './object-form-extension.interface';
4
+ import { Subject } from 'rxjs';
4
5
  import * as i0 from "@angular/core";
5
6
  /**
6
7
  * @ignore
7
8
  */
8
9
  export declare class ObjectFormService {
9
10
  #private;
11
+ formStatusChanged: Subject<void>;
10
12
  setElementExtensions(formExtensions: IObjectFormElementExtension[]): void;
11
13
  getElementExtensions(propertyName: string): Type<ObjectFormElementExtension>[];
12
14
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuuvis/client-framework",
3
- "version": "2.1.11",
3
+ "version": "2.1.13",
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.1.11",
12
- "@yuuvis/client-shell-core": "^2.1.11",
11
+ "@yuuvis/client-core": "^2.1.13",
12
+ "@yuuvis/client-shell-core": "^2.1.13",
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.1.11",
19
+ "@yuuvis/material": "2.1.13",
20
20
  "@yuuvis/media-viewer": "^2.0.4",
21
21
  "angular-split": "^19.0.0",
22
22
  "tslib": "^2.3.0"
@@ -55,14 +55,14 @@
55
55
  "types": "./datepicker/index.d.ts",
56
56
  "default": "./fesm2022/yuuvis-client-framework-datepicker.mjs"
57
57
  },
58
- "./icons": {
59
- "types": "./icons/index.d.ts",
60
- "default": "./fesm2022/yuuvis-client-framework-icons.mjs"
61
- },
62
58
  "./forms": {
63
59
  "types": "./forms/index.d.ts",
64
60
  "default": "./fesm2022/yuuvis-client-framework-forms.mjs"
65
61
  },
62
+ "./icons": {
63
+ "types": "./icons/index.d.ts",
64
+ "default": "./fesm2022/yuuvis-client-framework-icons.mjs"
65
+ },
66
66
  "./list": {
67
67
  "types": "./list/index.d.ts",
68
68
  "default": "./fesm2022/yuuvis-client-framework-list.mjs"
@@ -135,6 +135,10 @@
135
135
  "types": "./simple-search/index.d.ts",
136
136
  "default": "./fesm2022/yuuvis-client-framework-simple-search.mjs"
137
137
  },
138
+ "./sort": {
139
+ "types": "./sort/index.d.ts",
140
+ "default": "./fesm2022/yuuvis-client-framework-sort.mjs"
141
+ },
138
142
  "./split-view": {
139
143
  "types": "./split-view/index.d.ts",
140
144
  "default": "./fesm2022/yuuvis-client-framework-split-view.mjs"
package/sort/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @yuuvis/client-framework/sort
2
+
3
+ Secondary entry point of `@yuuvis/client-framework`. It can be used by importing from `@yuuvis/client-framework/sort`.
@@ -0,0 +1,2 @@
1
+ export * from './lib/sort/models';
2
+ export * from './lib/sort/sort.component';
@@ -0,0 +1 @@
1
+ export * from './sort.interface';
@@ -0,0 +1,7 @@
1
+ export interface SortMenuOption {
2
+ label: string;
3
+ value: string;
4
+ type: 'sort' | 'order';
5
+ selected: boolean;
6
+ }
7
+ export type SortType = 'asc' | 'desc';
@@ -0,0 +1,19 @@
1
+ import { TranslateService } from '@yuuvis/client-core';
2
+ import { SortMenuOption, SortType } from './models';
3
+ import * as i0 from "@angular/core";
4
+ export declare class SortComponent {
5
+ #private;
6
+ readonly translate: TranslateService;
7
+ sortOptions: import("@angular/core").InputSignal<string[]>;
8
+ storageKey: import("@angular/core").InputSignal<string | undefined>;
9
+ sortChanged: import("@angular/core").OutputEmitterRef<{
10
+ field: string;
11
+ order: SortType;
12
+ }>;
13
+ orderOptions: import("@angular/core").WritableSignal<SortMenuOption[]>;
14
+ sortFields: import("@angular/core").WritableSignal<SortMenuOption[]>;
15
+ constructor();
16
+ selectSort(option: SortMenuOption): void;
17
+ static ɵfac: i0.ɵɵFactoryDeclaration<SortComponent, never>;
18
+ static ɵcmp: i0.ɵɵComponentDeclaration<SortComponent, "yuv-sort", never, { "sortOptions": { "alias": "sortOptions"; "required": false; "isSignal": true; }; "storageKey": { "alias": "storageKey"; "required": false; "isSignal": true; }; }, { "sortChanged": "sortChanged"; }, never, never, true, never>;
19
+ }