@byuhbll/components 4.0.0-alpha.18 → 4.0.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/animations/animations.mjs +1 -19
- package/esm2022/lib/hbll-checkbox/hbll-checkbox.component.mjs +17 -0
- package/esm2022/lib/hbll-header/hbll-header.component.mjs +31 -81
- package/esm2022/lib/hbll-multi-select/hbll-multi-select.component.mjs +115 -0
- package/esm2022/lib/ss-search-bar/advanced-search/advanced-search.component.mjs +5 -5
- package/esm2022/lib/ss-search-bar/ss-search-bar.component.mjs +3 -3
- package/esm2022/public-api.mjs +1 -4
- package/fesm2022/byuhbll-components.mjs +65 -913
- package/fesm2022/byuhbll-components.mjs.map +1 -1
- package/lib/animations/animations.d.ts +0 -1
- package/lib/{checkbox/checkbox.component.d.ts → hbll-checkbox/hbll-checkbox.component.d.ts} +2 -2
- package/lib/hbll-header/hbll-header.component.d.ts +28 -23
- package/lib/{multi-select/multi-select.component.d.ts → hbll-multi-select/hbll-multi-select.component.d.ts} +1 -1
- package/lib/ss-search-bar/advanced-search/advanced-search.component.d.ts +1 -4
- package/package.json +1 -4
- package/public-api.d.ts +0 -3
- package/styles/scss/_mixins.scss +1 -1
- package/styles/scss/_vars.scss +0 -7
- package/styles/scss/base.scss +5 -38
- package/styles/scss/cta-btn.scss +2 -2
- package/styles/scss/pill-btn.scss +2 -2
- package/esm2022/lib/checkbox/checkbox.component.mjs +0 -15
- package/esm2022/lib/copy-tooltip/copy-tooltip.component.mjs +0 -49
- package/esm2022/lib/expand-collapse/expand-collapse.component.mjs +0 -31
- package/esm2022/lib/hbll-header/models/library-hours.mjs +0 -2
- package/esm2022/lib/hbll-header/nav-bar/nav-bar.component.mjs +0 -333
- package/esm2022/lib/hbll-header/nav-bar-dropdown/nav-bar-dropdown.component.mjs +0 -29
- package/esm2022/lib/hbll-header/pipes/library-hours.pipe.mjs +0 -31
- package/esm2022/lib/header-with-impersonation/header-with-impersonation.component.mjs +0 -38
- package/esm2022/lib/impersonate-modal/impersonate-modal.component.mjs +0 -190
- package/esm2022/lib/impersonation-banner/impersonation-banner.component.mjs +0 -128
- package/esm2022/lib/impersonation-banner/models/application-access.mjs +0 -7
- package/esm2022/lib/impersonation-banner/models/person-summary.mjs +0 -15
- package/esm2022/lib/models/token-payload.mjs +0 -2
- package/esm2022/lib/multi-select/multi-select.component.mjs +0 -115
- package/esm2022/lib/utils.mjs +0 -7
- package/lib/copy-tooltip/copy-tooltip.component.d.ts +0 -12
- package/lib/expand-collapse/expand-collapse.component.d.ts +0 -10
- package/lib/hbll-header/models/library-hours.d.ts +0 -10
- package/lib/hbll-header/nav-bar/nav-bar.component.d.ts +0 -30
- package/lib/hbll-header/nav-bar-dropdown/nav-bar-dropdown.component.d.ts +0 -12
- package/lib/hbll-header/pipes/library-hours.pipe.d.ts +0 -7
- package/lib/header-with-impersonation/header-with-impersonation.component.d.ts +0 -19
- package/lib/impersonate-modal/impersonate-modal.component.d.ts +0 -60
- package/lib/impersonation-banner/impersonation-banner.component.d.ts +0 -31
- package/lib/impersonation-banner/models/application-access.d.ts +0 -15
- package/lib/impersonation-banner/models/person-summary.d.ts +0 -33
- package/lib/models/token-payload.d.ts +0 -3
- package/lib/utils.d.ts +0 -5
- package/styles/scss/shared.scss +0 -7
- package/styles/scss/spinner.scss +0 -20
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, ViewChild, ViewEncapsulation, } from '@angular/core';
|
|
2
|
-
import { CommonModule } from '@angular/common';
|
|
3
|
-
import { MatAutocompleteModule, } from '@angular/material/autocomplete';
|
|
4
|
-
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
5
|
-
import { MatChipsModule } from '@angular/material/chips';
|
|
6
|
-
import { COMMA, ENTER } from '@angular/cdk/keycodes';
|
|
7
|
-
import { MatIconModule } from '@angular/material/icon';
|
|
8
|
-
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
9
|
-
import { combineLatest } from 'rxjs';
|
|
10
|
-
import { map, startWith } from 'rxjs/operators';
|
|
11
|
-
import * as i0 from "@angular/core";
|
|
12
|
-
import * as i1 from "@angular/common";
|
|
13
|
-
import * as i2 from "@angular/material/chips";
|
|
14
|
-
import * as i3 from "@angular/material/form-field";
|
|
15
|
-
import * as i4 from "@angular/material/autocomplete";
|
|
16
|
-
import * as i5 from "@angular/material/core";
|
|
17
|
-
import * as i6 from "@angular/forms";
|
|
18
|
-
export class HbllMultiSelectComponent {
|
|
19
|
-
constructor() {
|
|
20
|
-
this.allOptions = {};
|
|
21
|
-
this.label = '';
|
|
22
|
-
/**
|
|
23
|
-
* An array that indicates which keys are selected.
|
|
24
|
-
*/
|
|
25
|
-
this.selectedKeys = [];
|
|
26
|
-
/**
|
|
27
|
-
* An EventEmitter that emits an array of keys indicating which options are currently selected.
|
|
28
|
-
*/
|
|
29
|
-
this.selectedKeysChange = new EventEmitter();
|
|
30
|
-
this.inputControl = new FormControl('');
|
|
31
|
-
this.filteredOptions$ = combineLatest([
|
|
32
|
-
this.inputControl.valueChanges.pipe(startWith('')),
|
|
33
|
-
this.selectedKeysChange.asObservable().pipe(startWith([])),
|
|
34
|
-
]).pipe(map(([key]) =>
|
|
35
|
-
// Display filtered options if there is a value, else display all options currently not selected.
|
|
36
|
-
key
|
|
37
|
-
? this.filterOptions(key)
|
|
38
|
-
: Object.keys(this.allOptions).filter((key) => !this.selectedKeys.find((selectedOption) => key === selectedOption))));
|
|
39
|
-
this.separatorKeysCodes = [ENTER, COMMA];
|
|
40
|
-
/**
|
|
41
|
-
* Adds an option to the array of selected keys when a user selects from the autocomplete.
|
|
42
|
-
* @param {MatAutocompleteSelectedEvent} event MatAutocompleteSelectedEvent
|
|
43
|
-
*/
|
|
44
|
-
this.selectOption = (event) => {
|
|
45
|
-
this.addOptionToSelectedOptions(event.option.value);
|
|
46
|
-
};
|
|
47
|
-
/**
|
|
48
|
-
* Filters the options by the supplied value as well as the currently selected values.
|
|
49
|
-
* @param {string} value value to filter by.
|
|
50
|
-
* @returns {string[]} the filtered keys
|
|
51
|
-
*/
|
|
52
|
-
this.filterOptions = (value) => {
|
|
53
|
-
return Object.keys(this.allOptions).filter((key) => this.allOptions[key].toLowerCase().includes(value.toLowerCase()) &&
|
|
54
|
-
!this.selectedKeys.includes(key));
|
|
55
|
-
};
|
|
56
|
-
/**
|
|
57
|
-
* Adds a key to the selected keys array if the option is truthy and not already in the array.
|
|
58
|
-
* The input is also cleared (if available), and the new selected keys are emitted.
|
|
59
|
-
* @param {key} option key to add
|
|
60
|
-
*/
|
|
61
|
-
this.addOptionToSelectedOptions = (key) => {
|
|
62
|
-
if (key && !this.selectedKeys.includes(key) && this.allOptions[key]) {
|
|
63
|
-
this.selectedKeys.push(key);
|
|
64
|
-
this.inputControl.setValue('');
|
|
65
|
-
this.selectedKeysChange.emit(this.selectedKeys);
|
|
66
|
-
if (this.inputRef)
|
|
67
|
-
this.inputRef.nativeElement.value = '';
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Adds a key from the input to the array of selected key.
|
|
73
|
-
* The value from the input must match a key from the record of all options.
|
|
74
|
-
* @param {MatChipInputEvent} event MatChipInputEvent
|
|
75
|
-
*/
|
|
76
|
-
addOption(event) {
|
|
77
|
-
this.addOptionToSelectedOptions(event.value);
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Removes a key from the array of selected options and emits the new selected keys.
|
|
81
|
-
* @param {MultiSelectKeyValPair} key key to remove
|
|
82
|
-
*/
|
|
83
|
-
removeOption(key) {
|
|
84
|
-
const index = this.selectedKeys.indexOf(key);
|
|
85
|
-
if (index >= 0) {
|
|
86
|
-
this.selectedKeys.splice(index, 1);
|
|
87
|
-
this.selectedKeysChange.emit(this.selectedKeys);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.0", ngImport: i0, type: HbllMultiSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
91
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.0", type: HbllMultiSelectComponent, isStandalone: true, selector: "lib-multi-select", inputs: { allOptions: "allOptions", label: "label", selectedKeys: "selectedKeys" }, outputs: { selectedKeysChange: "selectedKeysChange" }, viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["input"], descendants: true }], ngImport: i0, template: "<div class=\"components-multi-select\">\n <mat-form-field appearance=\"outline\">\n <mat-chip-grid #chipGrid [attr.aria-label]=\"label + ' selection'\">\n @for (key of selectedKeys; track key) {\n @if (allOptions[key]) {\n <mat-chip-row (removed)=\"removeOption(key)\" data-testid=\"matChipRow\">\n {{ allOptions[key] }}\n <button\n matChipRemove\n [attr.aria-label]=\"'remove ' + allOptions[key]\"\n [attr.data-testid]=\"'remove' + key\"\n >\n <span class=\"material-symbols-outlined components-icon\"> cancel </span>\n </button>\n </mat-chip-row>\n }\n }\n </mat-chip-grid>\n <label class=\"components-hidden\" for=\"input\">{{ label }}</label>\n <input\n [placeholder]=\"label | titlecase\"\n #input\n id=\"input\"\n [formControl]=\"inputControl\"\n [matChipInputFor]=\"chipGrid\"\n [matAutocomplete]=\"auto\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"addOption($event)\"\n data-testid=\"input\"\n />\n <mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"selectOption($event)\"\n data-testid=\"autocomplete\"\n >\n @for (key of filteredOptions$ | async; track key) {\n <mat-option [value]=\"key\" data-testid=\"autocompleteOption\">\n {{ allOptions[key] }}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-form-field>\n</div>\n", styles: [".components-multi-select{font:inherit}.components-multi-select mat-form-field{font:inherit;background-color:#fff;width:100%}.components-multi-select mat-form-field .mat-mdc-form-field-infix{padding:.35em 0;min-height:0}.components-multi-select mat-form-field .mat-mdc-chip-input{font:inherit;margin-left:0}.components-multi-select mat-form-field .mat-mdc-chip-input::placeholder{opacity:.75}.components-multi-select mat-form-field .mat-mdc-text-field-wrapper{padding:0 .5em}.components-multi-select .components-icon{font-size:1em}.components-multi-select .mat-mdc-chip.mdc-evolution-chip--with-trailing-action .mat-mdc-chip-action-label{font:inherit}.components-multi-select .components-hidden{display:none}.mat-mdc-option.mdc-list-item{background-color:#fff;font:inherit}.mat-mdc-autocomplete-panel{background-color:#fff!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.TitleCasePipe, name: "titlecase" }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i2.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i2.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i2.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i2.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i4.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i4.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i6.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatIconModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
92
|
-
}
|
|
93
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.0", ngImport: i0, type: HbllMultiSelectComponent, decorators: [{
|
|
94
|
-
type: Component,
|
|
95
|
-
args: [{ selector: 'lib-multi-select', standalone: true, imports: [
|
|
96
|
-
CommonModule,
|
|
97
|
-
MatChipsModule,
|
|
98
|
-
MatFormFieldModule,
|
|
99
|
-
MatAutocompleteModule,
|
|
100
|
-
ReactiveFormsModule,
|
|
101
|
-
MatIconModule,
|
|
102
|
-
], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"components-multi-select\">\n <mat-form-field appearance=\"outline\">\n <mat-chip-grid #chipGrid [attr.aria-label]=\"label + ' selection'\">\n @for (key of selectedKeys; track key) {\n @if (allOptions[key]) {\n <mat-chip-row (removed)=\"removeOption(key)\" data-testid=\"matChipRow\">\n {{ allOptions[key] }}\n <button\n matChipRemove\n [attr.aria-label]=\"'remove ' + allOptions[key]\"\n [attr.data-testid]=\"'remove' + key\"\n >\n <span class=\"material-symbols-outlined components-icon\"> cancel </span>\n </button>\n </mat-chip-row>\n }\n }\n </mat-chip-grid>\n <label class=\"components-hidden\" for=\"input\">{{ label }}</label>\n <input\n [placeholder]=\"label | titlecase\"\n #input\n id=\"input\"\n [formControl]=\"inputControl\"\n [matChipInputFor]=\"chipGrid\"\n [matAutocomplete]=\"auto\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n (matChipInputTokenEnd)=\"addOption($event)\"\n data-testid=\"input\"\n />\n <mat-autocomplete\n #auto=\"matAutocomplete\"\n (optionSelected)=\"selectOption($event)\"\n data-testid=\"autocomplete\"\n >\n @for (key of filteredOptions$ | async; track key) {\n <mat-option [value]=\"key\" data-testid=\"autocompleteOption\">\n {{ allOptions[key] }}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-form-field>\n</div>\n", styles: [".components-multi-select{font:inherit}.components-multi-select mat-form-field{font:inherit;background-color:#fff;width:100%}.components-multi-select mat-form-field .mat-mdc-form-field-infix{padding:.35em 0;min-height:0}.components-multi-select mat-form-field .mat-mdc-chip-input{font:inherit;margin-left:0}.components-multi-select mat-form-field .mat-mdc-chip-input::placeholder{opacity:.75}.components-multi-select mat-form-field .mat-mdc-text-field-wrapper{padding:0 .5em}.components-multi-select .components-icon{font-size:1em}.components-multi-select .mat-mdc-chip.mdc-evolution-chip--with-trailing-action .mat-mdc-chip-action-label{font:inherit}.components-multi-select .components-hidden{display:none}.mat-mdc-option.mdc-list-item{background-color:#fff;font:inherit}.mat-mdc-autocomplete-panel{background-color:#fff!important}\n"] }]
|
|
103
|
-
}], propDecorators: { inputRef: [{
|
|
104
|
-
type: ViewChild,
|
|
105
|
-
args: ['input']
|
|
106
|
-
}], allOptions: [{
|
|
107
|
-
type: Input
|
|
108
|
-
}], label: [{
|
|
109
|
-
type: Input
|
|
110
|
-
}], selectedKeys: [{
|
|
111
|
-
type: Input
|
|
112
|
-
}], selectedKeysChange: [{
|
|
113
|
-
type: Output
|
|
114
|
-
}] } });
|
|
115
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXVsdGktc2VsZWN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudHMvc3JjL2xpYi9tdWx0aS1zZWxlY3QvbXVsdGktc2VsZWN0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudHMvc3JjL2xpYi9tdWx0aS1zZWxlY3QvbXVsdGktc2VsZWN0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDSCx1QkFBdUIsRUFDdkIsU0FBUyxFQUVULFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLFNBQVMsRUFDVCxpQkFBaUIsR0FDcEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFDSCxxQkFBcUIsR0FFeEIsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN4QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNsRSxPQUFPLEVBQXFCLGNBQWMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzVFLE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDckQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxXQUFXLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNsRSxPQUFPLEVBQWMsYUFBYSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ2pELE9BQU8sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7O0FBb0JoRCxNQUFNLE9BQU8sd0JBQXdCO0lBbEJyQztRQW9CYSxlQUFVLEdBQTJCLEVBQUUsQ0FBQztRQUN4QyxVQUFLLEdBQUcsRUFBRSxDQUFDO1FBQ3BCOztXQUVH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SSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ25DLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3BELENBQUM7SUFDTCxDQUFDOzhHQWhEUSx3QkFBd0I7a0dBQXhCLHdCQUF3QiwwVEN6Q3JDLHF6REEyQ0EsMjNCRGhCUSxZQUFZLGdKQUNaLGNBQWMsNHVCQUNkLGtCQUFrQix5T0FDbEIscUJBQXFCLHcxQkFDckIsbUJBQW1CLHlrQkFDbkIsYUFBYTs7MkZBU1Isd0JBQXdCO2tCQWxCcEMsU0FBUzsrQkFDSSxrQkFBa0IsY0FDaEIsSUFBSSxXQUNQO3dCQUNMLFlBQVk7d0JBQ1osY0FBYzt3QkFDZCxrQkFBa0I7d0JBQ2xCLHFCQUFxQjt3QkFDckIsbUJBQW1CO3dCQUNuQixhQUFhO3FCQUNoQixpQkFHYyxpQkFBaUIsQ0FBQyxJQUFJLG1CQUNwQix1QkFBdUIsQ0FBQyxNQUFNOzhCQUtuQixRQUFRO3NCQUFuQyxTQUFTO3VCQUFDLE9BQU87Z0JBQ1QsVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBSUcsWUFBWTtzQkFBcEIsS0FBSztnQkFJSSxrQkFBa0I7c0JBQTNCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICAgIENvbXBvbmVudCxcbiAgICBFbGVtZW50UmVmLFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBJbnB1dCxcbiAgICBPdXRwdXQsXG4gICAgVmlld0NoaWxkLFxuICAgIFZpZXdFbmNhcHN1bGF0aW9uLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICAgIE1hdEF1dG9jb21wbGV0ZU1vZHVsZSxcbiAgICBNYXRBdXRvY29tcGxldGVTZWxlY3RlZEV2ZW50LFxufSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9hdXRvY29tcGxldGUnO1xuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XG5pbXBvcnQgeyBNYXRDaGlwSW5wdXRFdmVudCwgTWF0Q2hpcHNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jaGlwcyc7XG5pbXBvcnQgeyBDT01NQSwgRU5URVIgfSBmcm9tICdAYW5ndWxhci9jZGsva2V5Y29kZXMnO1xuaW1wb3J0IHsgTWF0SWNvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2ljb24nO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBjb21iaW5lTGF0ZXN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAsIHN0YXJ0V2l0aCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdsaWItbXVsdGktc2VsZWN0JyxcbiAgICBzdGFuZGFsb25lOiB0cnVlLFxuICAgIGltcG9ydHM6IFtcbiAgICAgICAgQ29tbW9uTW9kdWxlLFxuICAgICAgICBNYXRDaGlwc01vZHVsZSxcbiAgICAgICAgTWF0Rm9ybUZpZWxkTW9kdWxlLFxuICAgICAgICBNYXRBdXRvY29tcGxldGVNb2R1bGUsXG4gICAgICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG4gICAgICAgIE1hdEljb25Nb2R1bGUsXG4gICAgXSxcbiAgICAvLyBOZWNlc3NhcnkgdG8gb3ZlcnJpZGUgbWF0ZXJpYWwgZGVzaWduIHN0eWxlcy5cbiAgICAvLyBJTVBPUlRBTlQ6IFRpZ2h0bHkgc2NvcGUgY2xhc3NlcyBhbmQgaWRzIHRvIHRoaXMgY29tcG9uZW50IGlmIHRoZXkgYXJlIG5lY2Vzc2FyeS5cbiAgICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9tdWx0aS1zZWxlY3QuY29tcG9uZW50Lmh0bWwnLFxuICAgIHN0eWxlVXJsczogWycuL211bHRpLXNlbGVjdC5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBIYmxsTXVsdGlTZWxlY3RDb21wb25lbnQge1xuICAgIEBWaWV3Q2hpbGQoJ2lucHV0JykgcHJpdmF0ZSBpbnB1dFJlZiE6IEVsZW1lbnRSZWY8SFRNTElucHV0RWxlbWVudD47XG4gICAgQElucHV0KCkgYWxsT3B0aW9uczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgIEBJbnB1dCgpIGxhYmVsID0gJyc7XG4gICAgLyoqXG4gICAgICogQW4gYXJyYXkgdGhhdCBpbmRpY2F0ZXMgd2hpY2gga2V5cyBhcmUgc2VsZWN0ZWQuXG4gICAgICovXG4gICAgQElucHV0KCkgc2VsZWN0ZWRLZXlzOiBzdHJpbmdbXSA9IFtdO1xuICAgIC8qKlxuICAgICAqIEFuIEV2ZW50RW1pdHRlciB0aGF0IGVtaXRzIGFuIGFycmF5IG9mIGtleXMgaW5kaWNhdGluZyB3aGljaCBvcHRpb25zIGFyZSBjdXJyZW50bHkgc2VsZWN0ZWQuXG4gICAgICovXG4gICAgQE91dHB1dCgpIHNlbGVjdGVkS2V5c0NoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nW10+KCk7XG5cbiAgICBwcm90ZWN0ZWQgaW5wdXRDb250cm9sID0gbmV3IEZvcm1Db250cm9sKCcnKTtcbiAgICBwcm90ZWN0ZWQgZmlsdGVyZWRPcHRpb25zJDogT2JzZXJ2YWJsZTxzdHJpbmdbXT4gPSBjb21iaW5lTGF0ZXN0KFtcbiAgICAgICAgdGhpcy5pbnB1dENvbnRyb2wudmFsdWVDaGFuZ2VzLnBpcGUoc3RhcnRXaXRoKCcnKSksXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRLZXlzQ2hhbmdlLmFzT2JzZXJ2YWJsZSgpLnBpcGUoc3RhcnRXaXRoKFtdKSksXG4gICAgXSkucGlwZShcbiAgICAgICAgbWFwKChba2V5XTogW3N0cmluZyB8IG51bGwsIHVua25vd25dKSA9PlxuICAgICAgICAgICAgLy8gRGlzcGxheSBmaWx0ZXJlZCBvcHRpb25zIGlmIHRoZXJlIGlzIGEgdmFsdWUsIGVsc2UgZGlzcGxheSBhbGwgb3B0aW9ucyBjdXJyZW50bHkgbm90IHNlbGVjdGVkLlxuICAgICAgICAgICAga2V5XG4gICAgICAgICAgICAgICAgPyB0aGlzLmZpbHRlck9wdGlvbnMoa2V5KVxuICAgICAgICAgICAgICAgIDogT2JqZWN0LmtleXModGhpcy5hbGxPcHRpb25zKS5maWx0ZXIoXG4gICAgICAgICAgICAgICAgICAgICAgKGtleSkgPT4gIXRoaXMuc2VsZWN0ZWRLZXlzLmZpbmQoKHNlbGVjdGVkT3B0aW9uKSA9PiBrZXkgPT09IHNlbGVjdGVkT3B0aW9uKSxcbiAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICksXG4gICAgKTtcbiAgICBwcm90ZWN0ZWQgc2VwYXJhdG9yS2V5c0NvZGVzOiBudW1iZXJbXSA9IFtFTlRFUiwgQ09NTUFdO1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGtleSBmcm9tIHRoZSBpbnB1dCB0byB0aGUgYXJyYXkgb2Ygc2VsZWN0ZWQga2V5LlxuICAgICAqIFRoZSB2YWx1ZSBmcm9tIHRoZSBpbnB1dCBtdXN0IG1hdGNoIGEga2V5IGZyb20gdGhlIHJlY29yZCBvZiBhbGwgb3B0aW9ucy5cbiAgICAgKiBAcGFyYW0ge01hdENoaXBJbnB1dEV2ZW50fSBldmVudCBNYXRDaGlwSW5wdXRFdmVudFxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhZGRPcHRpb24oZXZlbnQ6IE1hdENoaXBJbnB1dEV2ZW50KTogdm9pZCB7XG4gICAgICAgIHRoaXMuYWRkT3B0aW9uVG9TZWxlY3RlZE9wdGlvbnMoZXZlbnQudmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYSBrZXkgZnJvbSB0aGUgYXJyYXkgb2Ygc2VsZWN0ZWQgb3B0aW9ucyBhbmQgZW1pdHMgdGhlIG5ldyBzZWxlY3RlZCBrZXlzLlxuICAgICAqIEBwYXJhbSB7TXVsdGlTZWxlY3RLZXlWYWxQYWlyfSBrZXkga2V5IHRvIHJlbW92ZVxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZW1vdmVPcHRpb24oa2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnNlbGVjdGVkS2V5cy5pbmRleE9mKGtleSk7XG4gICAgICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkS2V5cy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEtleXNDaGFuZ2UuZW1pdCh0aGlzLnNlbGVjdGVkS2V5cyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGFuIG9wdGlvbiB0byB0aGUgYXJyYXkgb2Ygc2VsZWN0ZWQga2V5cyB3aGVuIGEgdXNlciBzZWxlY3RzIGZyb20gdGhlIGF1dG9jb21wbGV0ZS5cbiAgICAgKiBAcGFyYW0ge01hdEF1dG9jb21wbGV0ZVNlbGVjdGVkRXZlbnR9IGV2ZW50IE1hdEF1dG9jb21wbGV0ZVNlbGVjdGVkRXZlbnRcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgc2VsZWN0T3B0aW9uID0gKGV2ZW50OiBNYXRBdXRvY29tcGxldGVTZWxlY3RlZEV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuYWRkT3B0aW9uVG9TZWxlY3RlZE9wdGlvbnMoZXZlbnQub3B0aW9uLnZhbHVlKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmlsdGVycyB0aGUgb3B0aW9ucyBieSB0aGUgc3VwcGxpZWQgdmFsdWUgYXMgd2VsbCBhcyB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgdmFsdWUgdG8gZmlsdGVyIGJ5LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmdbXX0gdGhlIGZpbHRlcmVkIGtleXNcbiAgICAgKi9cbiAgICBwcml2YXRlIGZpbHRlck9wdGlvbnMgPSAodmFsdWU6IHN0cmluZyk6IHN0cmluZ1tdID0+IHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuYWxsT3B0aW9ucykuZmlsdGVyKFxuICAgICAgICAgICAgKGtleTogc3RyaW5nKSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuYWxsT3B0aW9uc1trZXldLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModmFsdWUudG9Mb3dlckNhc2UoKSkgJiZcbiAgICAgICAgICAgICAgICAhdGhpcy5zZWxlY3RlZEtleXMuaW5jbHVkZXMoa2V5KSxcbiAgICAgICAgKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWRkcyBhIGtleSB0byB0aGUgc2VsZWN0ZWQga2V5cyBhcnJheSBpZiB0aGUgb3B0aW9uIGlzIHRydXRoeSBhbmQgbm90IGFscmVhZHkgaW4gdGhlIGFycmF5LlxuICAgICAqIFRoZSBpbnB1dCBpcyBhbHNvIGNsZWFyZWQgKGlmIGF2YWlsYWJsZSksIGFuZCB0aGUgbmV3IHNlbGVjdGVkIGtleXMgYXJlIGVtaXR0ZWQuXG4gICAgICogQHBhcmFtIHtrZXl9IG9wdGlvbiBrZXkgdG8gYWRkXG4gICAgICovXG4gICAgcHJpdmF0ZSBhZGRPcHRpb25Ub1NlbGVjdGVkT3B0aW9ucyA9IChrZXk6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoa2V5ICYmICF0aGlzLnNlbGVjdGVkS2V5cy5pbmNsdWRlcyhrZXkpICYmIHRoaXMuYWxsT3B0aW9uc1trZXldKSB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkS2V5cy5wdXNoKGtleSk7XG4gICAgICAgICAgICB0aGlzLmlucHV0Q29udHJvbC5zZXRWYWx1ZSgnJyk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkS2V5c0NoYW5nZS5lbWl0KHRoaXMuc2VsZWN0ZWRLZXlzKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlucHV0UmVmKSB0aGlzLmlucHV0UmVmLm5hdGl2ZUVsZW1lbnQudmFsdWUgPSAnJztcbiAgICAgICAgfVxuICAgIH07XG59XG4iLCI8ZGl2IGNsYXNzPVwiY29tcG9uZW50cy1tdWx0aS1zZWxlY3RcIj5cbiAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIj5cbiAgICAgICAgPG1hdC1jaGlwLWdyaWQgI2NoaXBHcmlkIFthdHRyLmFyaWEtbGFiZWxdPVwibGFiZWwgKyAnIHNlbGVjdGlvbidcIj5cbiAgICAgICAgICAgIEBmb3IgKGtleSBvZiBzZWxlY3RlZEtleXM7IHRyYWNrIGtleSkge1xuICAgICAgICAgICAgICAgIEBpZiAoYWxsT3B0aW9uc1trZXldKSB7XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtY2hpcC1yb3cgKHJlbW92ZWQpPVwicmVtb3ZlT3B0aW9uKGtleSlcIiBkYXRhLXRlc3RpZD1cIm1hdENoaXBSb3dcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHt7IGFsbE9wdGlvbnNba2V5XSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdENoaXBSZW1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidyZW1vdmUgJyArIGFsbE9wdGlvbnNba2V5XVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ3JlbW92ZScgKyBrZXlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZCBjb21wb25lbnRzLWljb25cIj4gY2FuY2VsIDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICA8L21hdC1jaGlwLXJvdz5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIDwvbWF0LWNoaXAtZ3JpZD5cbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiY29tcG9uZW50cy1oaWRkZW5cIiBmb3I9XCJpbnB1dFwiPnt7IGxhYmVsIH19PC9sYWJlbD5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwibGFiZWwgfCB0aXRsZWNhc2VcIlxuICAgICAgICAgICAgI2lucHV0XG4gICAgICAgICAgICBpZD1cImlucHV0XCJcbiAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJpbnB1dENvbnRyb2xcIlxuICAgICAgICAgICAgW21hdENoaXBJbnB1dEZvcl09XCJjaGlwR3JpZFwiXG4gICAgICAgICAgICBbbWF0QXV0b2NvbXBsZXRlXT1cImF1dG9cIlxuICAgICAgICAgICAgW21hdENoaXBJbnB1dFNlcGFyYXRvcktleUNvZGVzXT1cInNlcGFyYXRvcktleXNDb2Rlc1wiXG4gICAgICAgICAgICAobWF0Q2hpcElucHV0VG9rZW5FbmQpPVwiYWRkT3B0aW9uKCRldmVudClcIlxuICAgICAgICAgICAgZGF0YS10ZXN0aWQ9XCJpbnB1dFwiXG4gICAgICAgIC8+XG4gICAgICAgIDxtYXQtYXV0b2NvbXBsZXRlXG4gICAgICAgICAgICAjYXV0bz1cIm1hdEF1dG9jb21wbGV0ZVwiXG4gICAgICAgICAgICAob3B0aW9uU2VsZWN0ZWQpPVwic2VsZWN0T3B0aW9uKCRldmVudClcIlxuICAgICAgICAgICAgZGF0YS10ZXN0aWQ9XCJhdXRvY29tcGxldGVcIlxuICAgICAgICA+XG4gICAgICAgICAgICBAZm9yIChrZXkgb2YgZmlsdGVyZWRPcHRpb25zJCB8IGFzeW5jOyB0cmFjayBrZXkpIHtcbiAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwia2V5XCIgZGF0YS10ZXN0aWQ9XCJhdXRvY29tcGxldGVPcHRpb25cIj5cbiAgICAgICAgICAgICAgICAgICAge3sgYWxsT3B0aW9uc1trZXldIH19XG4gICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgfVxuICAgICAgICA8L21hdC1hdXRvY29tcGxldGU+XG4gICAgPC9tYXQtZm9ybS1maWVsZD5cbjwvZGl2PlxuIl19
|
package/esm2022/lib/utils.mjs
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { toSignal } from '@angular/core/rxjs-interop';
|
|
2
|
-
import { map } from 'rxjs';
|
|
3
|
-
/**
|
|
4
|
-
* Signal that represents if the screen is small.
|
|
5
|
-
*/
|
|
6
|
-
export const isScreenSmallSignal = (bo) => toSignal(bo.observe(['(min-width: 1000px)']).pipe(map((r) => !r.matches)));
|
|
7
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL3NyYy9saWIvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFM0I7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLEVBQXNCLEVBQUUsRUFBRSxDQUMxRCxRQUFRLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCcmVha3BvaW50T2JzZXJ2ZXIgfSBmcm9tICdAYW5ndWxhci9jZGsvbGF5b3V0JztcbmltcG9ydCB7IHRvU2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcyc7XG5cbi8qKlxuICogU2lnbmFsIHRoYXQgcmVwcmVzZW50cyBpZiB0aGUgc2NyZWVuIGlzIHNtYWxsLlxuICovXG5leHBvcnQgY29uc3QgaXNTY3JlZW5TbWFsbFNpZ25hbCA9IChibzogQnJlYWtwb2ludE9ic2VydmVyKSA9PlxuICAgIHRvU2lnbmFsKGJvLm9ic2VydmUoWycobWluLXdpZHRoOiAxMDAwcHgpJ10pLnBpcGUobWFwKChyKSA9PiAhci5tYXRjaGVzKSkpO1xuIl19
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { MatTooltip, TooltipPosition } from '@angular/material/tooltip';
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
export declare class CopyTooltipComponent {
|
|
4
|
-
position: TooltipPosition;
|
|
5
|
-
copyText?: string;
|
|
6
|
-
tooltip: MatTooltip;
|
|
7
|
-
clipboardCopyMessage: string;
|
|
8
|
-
copyToClipboard: (text?: string) => Promise<void>;
|
|
9
|
-
handleMouseLeave: () => void;
|
|
10
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<CopyTooltipComponent, never>;
|
|
11
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<CopyTooltipComponent, "lib-copy-tooltip", never, { "position": { "alias": "position"; "required": false; }; "copyText": { "alias": "copyText"; "required": false; }; }, {}, never, ["*"], true, never>;
|
|
12
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import * as i0 from "@angular/core";
|
|
2
|
-
export declare class ExpandCollapseComponent {
|
|
3
|
-
private contentRef;
|
|
4
|
-
private _isExpanded;
|
|
5
|
-
set isExpanded(isExpanded: boolean);
|
|
6
|
-
get isExpanded(): boolean;
|
|
7
|
-
protected heightOfContent: number;
|
|
8
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<ExpandCollapseComponent, never>;
|
|
9
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<ExpandCollapseComponent, "lib-expand-collapse", never, { "isExpanded": { "alias": "isExpanded"; "required": true; }; }, {}, never, ["*"], true, never>;
|
|
10
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Signal } from '@angular/core';
|
|
2
|
-
import { NavBarDropdownComponent } from '../nav-bar-dropdown/nav-bar-dropdown.component';
|
|
3
|
-
import * as i0 from "@angular/core";
|
|
4
|
-
type NavInfo = {
|
|
5
|
-
title: string;
|
|
6
|
-
mainSection?: Section;
|
|
7
|
-
otherSections: Section[];
|
|
8
|
-
};
|
|
9
|
-
type Section = {
|
|
10
|
-
title: string;
|
|
11
|
-
links: Link[];
|
|
12
|
-
auxiliaryLink?: Link;
|
|
13
|
-
};
|
|
14
|
-
type Link = {
|
|
15
|
-
label: string;
|
|
16
|
-
url: string;
|
|
17
|
-
icon?: string;
|
|
18
|
-
};
|
|
19
|
-
export declare class NavBarComponent {
|
|
20
|
-
private bo;
|
|
21
|
-
mainSiteBaseUrl: import("@angular/core").InputSignal<string>;
|
|
22
|
-
height: import("@angular/core").InputSignal<number | null>;
|
|
23
|
-
dropdownComps: NavBarDropdownComponent[];
|
|
24
|
-
protected handleDropdownOpenEvent: (title: string) => void;
|
|
25
|
-
protected isScreenSmall: Signal<boolean | undefined>;
|
|
26
|
-
protected navInfos: Signal<NavInfo[]>;
|
|
27
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<NavBarComponent, never>;
|
|
28
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<NavBarComponent, "lib-nav-bar", never, { "mainSiteBaseUrl": { "alias": "mainSiteBaseUrl"; "required": true; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
29
|
-
}
|
|
30
|
-
export {};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from '@angular/core';
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
export declare class NavBarDropdownComponent {
|
|
4
|
-
title: import("@angular/core").InputSignal<string>;
|
|
5
|
-
isSmallScreen: import("@angular/core").InputSignal<boolean>;
|
|
6
|
-
openEvent: EventEmitter<string>;
|
|
7
|
-
closeDropdown: () => boolean;
|
|
8
|
-
protected isOpen: boolean;
|
|
9
|
-
protected handleClick: () => void;
|
|
10
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<NavBarDropdownComponent, never>;
|
|
11
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<NavBarDropdownComponent, "lib-nav-bar-dropdown", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "isSmallScreen": { "alias": "isSmallScreen"; "required": false; "isSignal": true; }; }, { "openEvent": "openEvent"; }, never, ["*"], true, never>;
|
|
12
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { PipeTransform } from '@angular/core';
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
export declare class LibraryHoursPipe implements PipeTransform {
|
|
4
|
-
transform(date: string, time: string): string | null;
|
|
5
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<LibraryHoursPipe, never>;
|
|
6
|
-
static ɵpipe: i0.ɵɵPipeDeclaration<LibraryHoursPipe, "libraryHours", true>;
|
|
7
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { EventEmitter, Signal } from '@angular/core';
|
|
2
|
-
import { TokenPayload } from '../models/token-payload';
|
|
3
|
-
import { JwtPayload } from 'jwt-decode';
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
export declare class HeaderWithImpersonationComponent {
|
|
6
|
-
accessTokenPayload: import("@angular/core").InputSignal<TokenPayload>;
|
|
7
|
-
oidcBaseUri: import("@angular/core").InputSignal<string>;
|
|
8
|
-
oidcDefaultIdp: import("@angular/core").InputSignal<string>;
|
|
9
|
-
login: EventEmitter<void>;
|
|
10
|
-
logout: EventEmitter<void>;
|
|
11
|
-
endImpersonation: EventEmitter<void>;
|
|
12
|
-
protected parsedToken: Signal<(JwtPayload & Record<string, any>) | null>;
|
|
13
|
-
protected name: Signal<any>;
|
|
14
|
-
protected showImpersonateButton: Signal<boolean>;
|
|
15
|
-
protected showImpersonationModal: boolean;
|
|
16
|
-
private isImpersonating;
|
|
17
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<HeaderWithImpersonationComponent, never>;
|
|
18
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<HeaderWithImpersonationComponent, "lib-header-with-impersonation", never, { "accessTokenPayload": { "alias": "accessTokenPayload"; "required": true; "isSignal": true; }; "oidcBaseUri": { "alias": "oidcBaseUri"; "required": false; "isSignal": true; }; "oidcDefaultIdp": { "alias": "oidcDefaultIdp"; "required": false; "isSignal": true; }; }, { "login": "login"; "logout": "logout"; "endImpersonation": "endImpersonation"; }, never, never, true, never>;
|
|
19
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { EventEmitter, OnDestroy, PipeTransform } from '@angular/core';
|
|
2
|
-
import { Subject } from 'rxjs';
|
|
3
|
-
import { TokenPayload } from '../models/token-payload';
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
export declare const defaultOidcBaseUri = "https://keycloak.lib.byu.edu/";
|
|
6
|
-
export declare const defaultOidcDefaultIdp = "byu-realm";
|
|
7
|
-
export declare class ImpersonateUserPipe implements PipeTransform {
|
|
8
|
-
transform(user: ImpersonateSearchResult): string;
|
|
9
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<ImpersonateUserPipe, never>;
|
|
10
|
-
static ɵpipe: i0.ɵɵPipeDeclaration<ImpersonateUserPipe, "impersonateUser", true>;
|
|
11
|
-
}
|
|
12
|
-
export interface ImpersonateSearchResult {
|
|
13
|
-
netId: string;
|
|
14
|
-
institution: string;
|
|
15
|
-
username: string;
|
|
16
|
-
name: string;
|
|
17
|
-
preferredName: string;
|
|
18
|
-
givenName: string;
|
|
19
|
-
surname: string;
|
|
20
|
-
restricted: boolean;
|
|
21
|
-
}
|
|
22
|
-
export declare class ImpersonateModalComponent implements OnDestroy {
|
|
23
|
-
private readonly http;
|
|
24
|
-
private readonly fb;
|
|
25
|
-
private readonly eref;
|
|
26
|
-
set showModal(open: boolean);
|
|
27
|
-
oidcBaseUri: import("@angular/core").InputSignal<string>;
|
|
28
|
-
oidcDefaultIdp: import("@angular/core").InputSignal<string>;
|
|
29
|
-
accessTokenPayload: import("@angular/core").InputSignal<TokenPayload>;
|
|
30
|
-
dismiss: EventEmitter<void>;
|
|
31
|
-
init: EventEmitter<void>;
|
|
32
|
-
protected isOpen: boolean;
|
|
33
|
-
protected hasError: boolean;
|
|
34
|
-
protected form: import("@angular/forms").FormGroup<{
|
|
35
|
-
search: import("@angular/forms").FormControl<string | null>;
|
|
36
|
-
}>;
|
|
37
|
-
protected selectedUsername?: string;
|
|
38
|
-
protected loading: boolean;
|
|
39
|
-
protected handleSearchSubject: Subject<boolean>;
|
|
40
|
-
protected results: import("@angular/core").Signal<ImpersonateSearchResult[] | null | undefined>;
|
|
41
|
-
private subs;
|
|
42
|
-
outsideClick(event: MouseEvent): void;
|
|
43
|
-
handleKeyDown: (event: KeyboardEvent) => void;
|
|
44
|
-
ngOnDestroy(): void;
|
|
45
|
-
/** Redirect to Keycloak impersonate page, which will redirect back
|
|
46
|
-
* after impersonation begins.
|
|
47
|
-
*/
|
|
48
|
-
protected startImpersonation: (username?: string) => void;
|
|
49
|
-
protected handleSelectUser: (event: Event) => void;
|
|
50
|
-
protected clearSearch: () => void;
|
|
51
|
-
protected close: () => void;
|
|
52
|
-
protected handleFormSubmit: (event: SubmitEvent) => void;
|
|
53
|
-
protected handleSearchKeyPress: (event: KeyboardEvent) => void;
|
|
54
|
-
protected handleResultKeyPress: (event: KeyboardEvent) => void;
|
|
55
|
-
/** Search Keycloak users using a generic search query. */
|
|
56
|
-
private searchUsers;
|
|
57
|
-
private replaceUrl;
|
|
58
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<ImpersonateModalComponent, never>;
|
|
59
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<ImpersonateModalComponent, "lib-impersonate-modal", never, { "showModal": { "alias": "showModal"; "required": false; }; "oidcBaseUri": { "alias": "oidcBaseUri"; "required": false; "isSignal": true; }; "oidcDefaultIdp": { "alias": "oidcDefaultIdp"; "required": false; "isSignal": true; }; "accessTokenPayload": { "alias": "accessTokenPayload"; "required": true; "isSignal": true; }; }, { "dismiss": "dismiss"; "init": "init"; }, never, never, true, never>;
|
|
60
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { EventEmitter, Signal } from '@angular/core';
|
|
2
|
-
import { type ApplicationAccess } from './models/application-access';
|
|
3
|
-
import { TokenPayload } from '../models/token-payload';
|
|
4
|
-
import { JwtPayload } from 'jwt-decode';
|
|
5
|
-
import { PersonSummary } from './models/person-summary';
|
|
6
|
-
import * as i0 from "@angular/core";
|
|
7
|
-
export declare class ImpersonationBannerComponent {
|
|
8
|
-
private http;
|
|
9
|
-
accessTokenPayload: import("@angular/core").InputSignal<TokenPayload>;
|
|
10
|
-
personBaseUri: import("@angular/core").InputSignal<string>;
|
|
11
|
-
libraryApiBaseUri: import("@angular/core").InputSignal<string>;
|
|
12
|
-
endImpersonation: EventEmitter<void>;
|
|
13
|
-
protected parsedToken: Signal<JwtPayload & Record<string, any>>;
|
|
14
|
-
protected isImpersonating: Signal<boolean>;
|
|
15
|
-
protected libraryId: Signal<any>;
|
|
16
|
-
protected user: Signal<PersonSummary | null | undefined>;
|
|
17
|
-
protected userFullName: Signal<string>;
|
|
18
|
-
protected isRestricted: Signal<boolean | undefined>;
|
|
19
|
-
protected userInfoTabs: Signal<Map<string, any>>;
|
|
20
|
-
protected userPhotoUrl: Signal<string>;
|
|
21
|
-
protected activityStatus: Signal<"retired" | "active" | "inactive" | null>;
|
|
22
|
-
protected employeeStatusDescription: Signal<string | null>;
|
|
23
|
-
protected independentStudyStatus: Signal<boolean | null | undefined>;
|
|
24
|
-
protected accountStatuses: Signal<{
|
|
25
|
-
ok: ApplicationAccess[];
|
|
26
|
-
blocked: ApplicationAccess[];
|
|
27
|
-
none: ApplicationAccess[];
|
|
28
|
-
} | null | undefined>;
|
|
29
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<ImpersonationBannerComponent, never>;
|
|
30
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<ImpersonationBannerComponent, "lib-impersonation-banner", never, { "accessTokenPayload": { "alias": "accessTokenPayload"; "required": true; "isSignal": true; }; "personBaseUri": { "alias": "personBaseUri"; "required": false; "isSignal": true; }; "libraryApiBaseUri": { "alias": "libraryApiBaseUri"; "required": false; "isSignal": true; }; }, { "endImpersonation": "endImpersonation"; }, never, never, true, never>;
|
|
31
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export declare enum AccessStatus {
|
|
2
|
-
OK = "ok",
|
|
3
|
-
BLOCKED = "blocked",
|
|
4
|
-
NONE = "none"
|
|
5
|
-
}
|
|
6
|
-
export interface ApplicationAccess {
|
|
7
|
-
label: string;
|
|
8
|
-
access: AccessStatus;
|
|
9
|
-
code?: string;
|
|
10
|
-
detail?: string;
|
|
11
|
-
}
|
|
12
|
-
export interface AccountsResponse {
|
|
13
|
-
netId: string;
|
|
14
|
-
applications: Record<string, ApplicationAccess>;
|
|
15
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export declare enum EmployeePositionType {
|
|
2
|
-
STD = "std",
|
|
3
|
-
SNL = "snl",
|
|
4
|
-
FAC = "fac",
|
|
5
|
-
STF = "stf",
|
|
6
|
-
TMP = "tmp",
|
|
7
|
-
FTC = "ftc"
|
|
8
|
-
}
|
|
9
|
-
export declare enum UndergradGraduateStatus {
|
|
10
|
-
UNDERGRAD = "undergrad",
|
|
11
|
-
GRADUATE = "graduate"
|
|
12
|
-
}
|
|
13
|
-
export interface IndependentStudyResponse {
|
|
14
|
-
library_id: string;
|
|
15
|
-
is_enrolled: boolean;
|
|
16
|
-
}
|
|
17
|
-
export interface PersonSummary {
|
|
18
|
-
byu_id?: string;
|
|
19
|
-
email_address?: string;
|
|
20
|
-
first_name: string;
|
|
21
|
-
is_affiliate: boolean;
|
|
22
|
-
is_employee: boolean;
|
|
23
|
-
is_retired?: boolean;
|
|
24
|
-
primary_position_type?: EmployeePositionType;
|
|
25
|
-
primary_position_type_display?: string;
|
|
26
|
-
is_student: boolean;
|
|
27
|
-
undergrad_graduate_status?: UndergradGraduateStatus;
|
|
28
|
-
last_name: string;
|
|
29
|
-
library_id: string;
|
|
30
|
-
preferred_first_name: string;
|
|
31
|
-
restricted: boolean;
|
|
32
|
-
worker_id?: string;
|
|
33
|
-
}
|
package/lib/utils.d.ts
DELETED
package/styles/scss/shared.scss
DELETED
package/styles/scss/spinner.scss
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
@use 'vars';
|
|
2
|
-
|
|
3
|
-
.lib-spinner {
|
|
4
|
-
border: 0.3em solid #dfe9f7;
|
|
5
|
-
border-top: 0.3em solid vars.$interactive-blue;
|
|
6
|
-
border-radius: 100%;
|
|
7
|
-
width: 30px;
|
|
8
|
-
height: 30px;
|
|
9
|
-
animation: loadingSpinnerAnimate 1s ease infinite;
|
|
10
|
-
position: relative;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
@keyframes loadingSpinnerAnimate {
|
|
14
|
-
0% {
|
|
15
|
-
transform: rotate(0deg);
|
|
16
|
-
}
|
|
17
|
-
100% {
|
|
18
|
-
transform: rotate(360deg);
|
|
19
|
-
}
|
|
20
|
-
}
|