@flywheel-io/vision 2.0.0-beta.11 → 2.0.0-beta.12

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 (25) hide show
  1. package/components/menu/menu-container/menu-container.component.d.ts +26 -11
  2. package/components/menu/menu-item/menu-item.component.d.ts +5 -6
  3. package/components/menu/menu-sub-item/menu-sub-item.component.d.ts +1 -5
  4. package/components/menu/menu.component.d.ts +3 -23
  5. package/components/select-menu/multi-select-menu/multi-select-menu.component.d.ts +38 -23
  6. package/components/select-menu/select-menu.module.d.ts +7 -6
  7. package/components/text-input/text-input.component.d.ts +4 -2
  8. package/esm2022/components/dialog/dialog.component.mjs +2 -2
  9. package/esm2022/components/menu/menu-container/menu-container.component.mjs +59 -23
  10. package/esm2022/components/menu/menu-item/menu-item.component.mjs +11 -13
  11. package/esm2022/components/menu/menu-sub-item/menu-sub-item.component.mjs +3 -9
  12. package/esm2022/components/menu/menu.component.mjs +6 -89
  13. package/esm2022/components/paginator/paginator-advanced/paginator-advanced.component.mjs +1 -1
  14. package/esm2022/components/phone-input/phone-input.component.mjs +1 -1
  15. package/esm2022/components/select-menu/multi-select-menu/multi-select-menu.component.mjs +160 -183
  16. package/esm2022/components/select-menu/select-menu.component.mjs +1 -1
  17. package/esm2022/components/select-menu/select-menu.module.mjs +5 -1
  18. package/esm2022/components/text-input/text-input.component.mjs +13 -6
  19. package/fesm2022/flywheel-io-vision.mjs +241 -311
  20. package/fesm2022/flywheel-io-vision.mjs.map +1 -1
  21. package/flywheel-io-vision-2.0.0-beta.12.tgz +0 -0
  22. package/global.scss +1 -0
  23. package/package.json +1 -1
  24. package/styles.css +5 -0
  25. package/flywheel-io-vision-2.0.0-beta.11.tgz +0 -0
@@ -1,28 +1,43 @@
1
- import { AfterContentInit, EventEmitter } from '@angular/core';
1
+ import { AfterViewInit } from '@angular/core';
2
2
  import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
3
+ import { FwTextInputComponent } from '../../text-input/text-input.component';
3
4
  import { FwMenuComponent } from '../menu.component';
5
+ import { FwMenuItemComponent } from '../menu-item/menu-item.component';
4
6
  import * as i0 from "@angular/core";
5
- export declare class FwMenuContainerComponent implements AfterContentInit {
7
+ import * as i1 from "@angular/cdk/coercion";
8
+ export declare class FwMenuContainerComponent implements AfterViewInit {
6
9
  private sanitizer;
7
10
  width?: string;
8
11
  maxHeight?: string;
9
12
  minHeight?: string;
10
13
  border?: 'none' | 'default';
11
14
  shadow?: 'none' | 'small' | 'medium' | 'large' | 'extra-large' | 'inner';
12
- showFilter?: boolean;
15
+ showFilter: boolean;
13
16
  filterText?: string;
17
+ focusFilterOnMount: boolean;
14
18
  offset?: string;
15
- /**
16
- * @deprecated please use fw-navbar instead
17
- */
18
- collapsed?: boolean;
19
- readonly filterChanged: EventEmitter<string>;
19
+ emptyText: import("@angular/core").InputSignal<string>;
20
+ filteredMenuItems: FwMenuItemComponent[];
21
+ filteredMenuItemChange: import("@angular/core").OutputEmitterRef<FwMenuItemComponent[]>;
22
+ private defaultFilterFn;
23
+ filterFn: import("@angular/core").InputSignal<(filter: string, menuItems: FwMenuItemComponent[]) => FwMenuItemComponent[]>;
24
+ filterChanged: import("@angular/core").OutputEmitterRef<string>;
25
+ filterRef: FwTextInputComponent;
20
26
  menu: FwMenuComponent;
27
+ additionalMenuItems: import("@angular/core").InputSignal<FwMenuItemComponent[]>;
28
+ childMenuItems: import("@angular/core").Signal<readonly FwMenuItemComponent[]>;
29
+ private combinedMenuItems;
30
+ keyHandler: (event: KeyboardEvent) => void;
21
31
  get classes(): string;
22
32
  get style(): SafeStyle;
23
33
  constructor(sanitizer: DomSanitizer);
24
- ngAfterContentInit(): void;
25
- filterTextChange(event: Event): void;
34
+ ngAfterViewInit(): void;
35
+ noResults: import("@angular/core").WritableSignal<boolean>;
36
+ handleFilterClick(event: Event): void;
37
+ handleFilterInput(event: Event): void;
38
+ onFilterChange(filter: string): void;
26
39
  static ɵfac: i0.ɵɵFactoryDeclaration<FwMenuContainerComponent, never>;
27
- static ɵcmp: i0.ɵɵComponentDeclaration<FwMenuContainerComponent, "fw-menu-container", never, { "width": { "alias": "width"; "required": false; }; "maxHeight": { "alias": "maxHeight"; "required": false; }; "minHeight": { "alias": "minHeight"; "required": false; }; "border": { "alias": "border"; "required": false; }; "shadow": { "alias": "shadow"; "required": false; }; "showFilter": { "alias": "showFilter"; "required": false; }; "filterText": { "alias": "filterText"; "required": false; }; "offset": { "alias": "offset"; "required": false; }; "collapsed": { "alias": "collapsed"; "required": false; }; }, { "filterChanged": "filterChanged"; }, ["menu"], ["*"], false, never>;
40
+ static ɵcmp: i0.ɵɵComponentDeclaration<FwMenuContainerComponent, "fw-menu-container, fw-menu-filter", never, { "width": { "alias": "width"; "required": false; }; "maxHeight": { "alias": "maxHeight"; "required": false; }; "minHeight": { "alias": "minHeight"; "required": false; }; "border": { "alias": "border"; "required": false; }; "shadow": { "alias": "shadow"; "required": false; }; "showFilter": { "alias": "showFilter"; "required": false; }; "filterText": { "alias": "filterText"; "required": false; }; "focusFilterOnMount": { "alias": "focusFilterOnMount"; "required": false; }; "offset": { "alias": "offset"; "required": false; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "filterFn": { "alias": "filterFn"; "required": false; "isSignal": true; }; "additionalMenuItems": { "alias": "additionalMenuItems"; "required": false; "isSignal": true; }; "keyHandler": { "alias": "keyHandler"; "required": false; }; }, { "filteredMenuItemChange": "filteredMenuItemChange"; "filterChanged": "filterChanged"; }, ["childMenuItems", "menu"], [".filter-content", "*", "custom-menu-items"], false, never>;
41
+ static ngAcceptInputType_showFilter: i1.BooleanInput;
42
+ static ngAcceptInputType_focusFilterOnMount: i1.BooleanInput;
28
43
  }
@@ -1,8 +1,9 @@
1
- import { AfterContentInit, EventEmitter, OnChanges, OnDestroy, QueryList, SimpleChanges } from '@angular/core';
1
+ import { AfterContentInit, ElementRef, EventEmitter, OnChanges, OnDestroy, QueryList, SimpleChanges } from '@angular/core';
2
2
  import { IconType } from '../../icon/icon.types';
3
3
  import { FwMenuSubItemComponent } from '../menu-sub-item/menu-sub-item.component';
4
4
  import * as i0 from "@angular/core";
5
5
  export declare class FwMenuItemComponent implements OnChanges, OnDestroy, AfterContentInit {
6
+ private elementRef;
6
7
  value?: string;
7
8
  size?: 'default' | 'compact';
8
9
  title: string;
@@ -23,10 +24,8 @@ export declare class FwMenuItemComponent implements OnChanges, OnDestroy, AfterC
23
24
  selected?: boolean;
24
25
  subItems: QueryList<FwMenuSubItemComponent>;
25
26
  private subscriptions;
26
- /**
27
- * @deprecated please use fw-navbar-item instead
28
- */
29
- variant?: 'default' | 'modern' | 'button';
27
+ constructor(elementRef: ElementRef<HTMLElement>);
28
+ scrollIntoView(): void;
30
29
  ngOnChanges(changes: SimpleChanges): void;
31
30
  ngOnDestroy(): void;
32
31
  ngAfterContentInit(): void;
@@ -34,5 +33,5 @@ export declare class FwMenuItemComponent implements OnChanges, OnDestroy, AfterC
34
33
  toggleSubItemsView(): void;
35
34
  handleClick(evt?: Event): void;
36
35
  static ɵfac: i0.ɵɵFactoryDeclaration<FwMenuItemComponent, never>;
37
- static ɵcmp: i0.ɵɵComponentDeclaration<FwMenuItemComponent, "fw-menu-item", never, { "value": { "alias": "value"; "required": false; }; "size": { "alias": "size"; "required": false; }; "title": { "alias": "title"; "required": false; }; "description": { "alias": "description"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "iconColor": { "alias": "iconColor"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "showCheckbox": { "alias": "showCheckbox"; "required": false; }; "checkboxColor": { "alias": "checkboxColor"; "required": false; }; "multiSelect": { "alias": "multiSelect"; "required": false; }; "hidden": { "alias": "hidden"; "required": false; }; "collapsed": { "alias": "collapsed"; "required": false; }; "href": { "alias": "href"; "required": false; }; "target": { "alias": "target"; "required": false; }; "subItemsOpen": { "alias": "subItemsOpen"; "required": false; }; "focused": { "alias": "focused"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; }, { "click": "click"; }, ["subItems"], ["fw-avatar", "p", "fw-badge", "fw-icon", "fw-icon-button", "fw-menu-sub-item"], false, never>;
36
+ static ɵcmp: i0.ɵɵComponentDeclaration<FwMenuItemComponent, "fw-menu-item", never, { "value": { "alias": "value"; "required": false; }; "size": { "alias": "size"; "required": false; }; "title": { "alias": "title"; "required": false; }; "description": { "alias": "description"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "iconColor": { "alias": "iconColor"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "showCheckbox": { "alias": "showCheckbox"; "required": false; }; "checkboxColor": { "alias": "checkboxColor"; "required": false; }; "multiSelect": { "alias": "multiSelect"; "required": false; }; "hidden": { "alias": "hidden"; "required": false; }; "collapsed": { "alias": "collapsed"; "required": false; }; "href": { "alias": "href"; "required": false; }; "target": { "alias": "target"; "required": false; }; "subItemsOpen": { "alias": "subItemsOpen"; "required": false; }; "focused": { "alias": "focused"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; }, { "click": "click"; }, ["subItems"], ["fw-avatar", "p", "fw-badge", "fw-icon", "fw-icon-button", "fw-menu-sub-item"], false, never>;
38
37
  }
@@ -15,11 +15,7 @@ export declare class FwMenuSubItemComponent {
15
15
  click: EventEmitter<string>;
16
16
  focused?: boolean;
17
17
  selected?: boolean;
18
- /**
19
- * @deprecated please use fw-navbar-sub-item instead
20
- */
21
- variant?: 'default' | 'modern' | 'button';
22
18
  handleClick(evt?: Event): void;
23
19
  static ɵfac: i0.ɵɵFactoryDeclaration<FwMenuSubItemComponent, never>;
24
- static ɵcmp: i0.ɵɵComponentDeclaration<FwMenuSubItemComponent, "fw-menu-sub-item", never, { "value": { "alias": "value"; "required": false; }; "size": { "alias": "size"; "required": false; }; "title": { "alias": "title"; "required": false; }; "description": { "alias": "description"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "hidden": { "alias": "hidden"; "required": false; }; "href": { "alias": "href"; "required": false; }; "target": { "alias": "target"; "required": false; }; "collapsed": { "alias": "collapsed"; "required": false; }; "focused": { "alias": "focused"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; }, { "click": "click"; }, never, ["p", "fw-badge", "fw-icon", "fw-icon-button"], false, never>;
20
+ static ɵcmp: i0.ɵɵComponentDeclaration<FwMenuSubItemComponent, "fw-menu-sub-item", never, { "value": { "alias": "value"; "required": false; }; "size": { "alias": "size"; "required": false; }; "title": { "alias": "title"; "required": false; }; "description": { "alias": "description"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "hidden": { "alias": "hidden"; "required": false; }; "href": { "alias": "href"; "required": false; }; "target": { "alias": "target"; "required": false; }; "collapsed": { "alias": "collapsed"; "required": false; }; "focused": { "alias": "focused"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; }, { "click": "click"; }, never, ["p", "fw-badge", "fw-icon", "fw-icon-button"], false, never>;
25
21
  }
@@ -1,4 +1,4 @@
1
- import { AfterContentInit, ElementRef, EventEmitter, OnChanges, OnDestroy, QueryList, SimpleChanges } from '@angular/core';
1
+ import { AfterContentInit, ElementRef, EventEmitter, OnChanges, OnDestroy, QueryList } from '@angular/core';
2
2
  import { ControlValueAccessor } from '@angular/forms';
3
3
  import { FwMenuItemComponent } from './menu-item/menu-item.component';
4
4
  import * as i0 from "@angular/core";
@@ -9,40 +9,20 @@ export declare class FwMenuComponent implements ControlValueAccessor, OnChanges,
9
9
  useCheckbox?: boolean;
10
10
  value?: string | string[];
11
11
  change: EventEmitter<string | string[]>;
12
- filteredItemsChange: EventEmitter<FwMenuItemComponent[]>;
13
12
  menuItems: QueryList<FwMenuItemComponent>;
14
13
  menuContentWrapper: ElementRef;
15
- private _filterText;
16
- /**
17
- * @deprecated please use fw-navbar instead
18
- */
19
- variant?: 'default' | 'modern' | 'button';
20
- /**
21
- * @deprecated please use fw-navbar instead
22
- */
23
- collapsed?: boolean;
24
- /**
25
- * @deprecated please use fw-navbar instead
26
- */
27
- collapsedWidth?: string;
28
- /**
29
- * @deprecated please use fw-navbar instead
30
- */
31
- openWidth?: string;
32
- noFilterResults: boolean;
33
14
  onChange: (value: string | string[]) => void;
34
15
  onTouched: () => void;
35
16
  private subscriptions;
36
- ngOnChanges(changes: SimpleChanges): void;
17
+ ngOnChanges(): void;
37
18
  ngOnDestroy(): void;
38
19
  ngAfterContentInit(): void;
39
20
  writeValue(value: string | string[]): void;
40
21
  registerOnChange(fn: (value: string | string[]) => void): void;
41
22
  registerOnTouched(fn: () => void): void;
42
23
  setDisabledState?(isDisabled: boolean): void;
43
- setFilter(filterText: string): void;
44
24
  handleSelect(value: string): void;
45
25
  updateLayout(): void;
46
26
  static ɵfac: i0.ɵɵFactoryDeclaration<FwMenuComponent, never>;
47
- static ɵcmp: i0.ɵɵComponentDeclaration<FwMenuComponent, "fw-menu", never, { "disabled": { "alias": "disabled"; "required": false; }; "size": { "alias": "size"; "required": false; }; "multiSelect": { "alias": "multiSelect"; "required": false; }; "useCheckbox": { "alias": "useCheckbox"; "required": false; }; "value": { "alias": "value"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "collapsed": { "alias": "collapsed"; "required": false; }; "collapsedWidth": { "alias": "collapsedWidth"; "required": false; }; "openWidth": { "alias": "openWidth"; "required": false; }; }, { "change": "change"; "filteredItemsChange": "filteredItemsChange"; }, ["menuContentWrapper", "menuItems"], ["*"], false, never>;
27
+ static ɵcmp: i0.ɵɵComponentDeclaration<FwMenuComponent, "fw-menu", never, { "disabled": { "alias": "disabled"; "required": false; }; "size": { "alias": "size"; "required": false; }; "multiSelect": { "alias": "multiSelect"; "required": false; }; "useCheckbox": { "alias": "useCheckbox"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, { "change": "change"; }, ["menuContentWrapper", "menuItems"], ["*"], false, never>;
48
28
  }
@@ -1,21 +1,33 @@
1
+ import { BooleanInput } from '@angular/cdk/coercion';
1
2
  import { CdkMenuTrigger } from '@angular/cdk/menu';
2
- import { AfterContentInit, ChangeDetectorRef, ElementRef, EventEmitter, OnChanges, OnDestroy, QueryList, SimpleChanges } from '@angular/core';
3
+ import { AfterContentInit, ChangeDetectorRef, ElementRef, EventEmitter, OnDestroy, QueryList, WritableSignal } from '@angular/core';
3
4
  import { ControlValueAccessor } from '@angular/forms';
4
5
  import { FwMenuComponent } from '../../menu/menu.component';
6
+ import { FwMenuContainerComponent } from '../../menu/menu-container/menu-container.component';
5
7
  import { FwMenuItemComponent } from '../../menu/menu-item/menu-item.component';
6
8
  import * as i0 from "@angular/core";
7
- export declare class FwMultiSelectMenuComponent implements ControlValueAccessor, AfterContentInit, OnChanges, OnDestroy {
9
+ /**
10
+ * FwMultiSelect a component for selecting multiple options
11
+ * @see [Storybook Docs](https://cdn.flywheel.io/docs/vision/master/?path=/docs/form-controls-multi-select--docs)
12
+ */
13
+ export declare class FwMultiSelectMenuComponent implements ControlValueAccessor, AfterContentInit, OnDestroy {
8
14
  protected _changeDetectorRef: ChangeDetectorRef;
15
+ private elementRef;
9
16
  outsideClick(): void;
10
17
  options: object[];
11
18
  valueProperty?: string;
12
19
  titleProperty?: string;
13
20
  iconProperty?: string;
21
+ emptyText: string;
22
+ placeholder: string;
14
23
  disabled?: boolean;
15
24
  useCheckbox?: boolean;
16
25
  closeOnSelect?: boolean;
17
- filterItemsOnSelect?: boolean;
18
26
  maxSelectedShown: number;
27
+ showClear: import("@angular/core").InputSignal<boolean>;
28
+ showFilter: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
29
+ showSelectionInfo: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
30
+ filterItemsOnSelect: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
19
31
  width: string;
20
32
  minHeight: string;
21
33
  maxHeight: string;
@@ -23,45 +35,48 @@ export declare class FwMultiSelectMenuComponent implements ControlValueAccessor,
23
35
  minOptionsHeight?: string;
24
36
  maxOptionsHeight?: string;
25
37
  size?: 'small' | 'medium' | 'large';
26
- placeholder: string;
27
- emptyText: string;
28
- showClear: import("@angular/core").InputSignal<boolean>;
29
38
  trigger: CdkMenuTrigger;
30
39
  menu: FwMenuComponent;
40
+ menuFilter: import("@angular/core").Signal<FwMenuContainerComponent>;
31
41
  renderedMenuItems: QueryList<FwMenuItemComponent>;
32
42
  customMenuItems: QueryList<FwMenuItemComponent>;
33
- selectedValues: string[];
43
+ createArray: (d: Iterable<unknown>) => unknown[];
44
+ selectedValues: Set<string>;
34
45
  selectedOptions: object[];
35
- filteredOptions: object[];
46
+ displayedOptions: WritableSignal<FwMenuItemComponent[]>;
47
+ focusedIndex: WritableSignal<number>;
48
+ touched: boolean;
36
49
  private subscriptions;
37
- textInput: ElementRef<HTMLInputElement>;
38
- textInitialInput: ElementRef<HTMLInputElement>;
39
- change: EventEmitter<any>;
40
- focused: number;
41
- private touched;
42
50
  private _isOpen;
51
+ change: EventEmitter<any>;
43
52
  get value(): any[];
44
53
  set value(newValue: any[]);
45
54
  private _value;
46
- constructor(_changeDetectorRef: ChangeDetectorRef);
55
+ constructor(_changeDetectorRef: ChangeDetectorRef, elementRef: ElementRef);
56
+ tabIndex: number;
57
+ pointerEvents: string;
47
58
  onChange: (value: any[]) => void;
48
59
  onTouched: () => void;
49
60
  registerOnChange(fn: (value: any[]) => void): void;
50
61
  registerOnTouched(fn: () => void): void;
51
62
  setDisabledState?(isDisabled: boolean): void;
52
63
  writeValue(value: any[]): void;
53
- ngOnChanges(changes: SimpleChanges): void;
54
64
  ngOnDestroy(): void;
55
65
  ngAfterContentInit(): void;
56
- registerCustomMenuItems(): void;
66
+ private registerCustomMenuItems;
57
67
  handleTouched(): void;
58
- handleClose(chip: object): void;
68
+ handleChipClose(chip: object): void;
59
69
  handleChange(e: string[]): void;
60
- updateFilteredItems(): void;
61
- updateValue(incomingValues: any[], additive?: boolean): void;
62
- moveFocused(direction: string): void;
63
- handleKeyDown(event: KeyboardEvent): void;
64
- handleFilterChange(event: Event): void;
70
+ addValue(incoming: string): void;
71
+ updateValue(incomingValues: any[]): void;
72
+ customFilter: (filter: string, menuItems: FwMenuItemComponent[]) => FwMenuItemComponent[];
73
+ private moveFocused;
74
+ setFocusedIndex(item: unknown): void;
75
+ displayFocusIndicator: import("@angular/core").EffectRef;
76
+ private keyboardActionMap;
77
+ private closedTriggerKeyboardActionsMap;
78
+ handleKeyDown: (event: KeyboardEvent) => void;
79
+ private postSelectSideEffects;
65
80
  static ɵfac: i0.ɵɵFactoryDeclaration<FwMultiSelectMenuComponent, never>;
66
- static ɵcmp: i0.ɵɵComponentDeclaration<FwMultiSelectMenuComponent, "fw-multi-select", never, { "options": { "alias": "options"; "required": false; }; "valueProperty": { "alias": "valueProperty"; "required": false; }; "titleProperty": { "alias": "titleProperty"; "required": false; }; "iconProperty": { "alias": "iconProperty"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "useCheckbox": { "alias": "useCheckbox"; "required": false; }; "closeOnSelect": { "alias": "closeOnSelect"; "required": false; }; "filterItemsOnSelect": { "alias": "filterItemsOnSelect"; "required": false; }; "maxSelectedShown": { "alias": "maxSelectedShown"; "required": false; }; "width": { "alias": "width"; "required": false; }; "minHeight": { "alias": "minHeight"; "required": false; }; "maxHeight": { "alias": "maxHeight"; "required": false; }; "optionsWidth": { "alias": "optionsWidth"; "required": false; }; "minOptionsHeight": { "alias": "minOptionsHeight"; "required": false; }; "maxOptionsHeight": { "alias": "maxOptionsHeight"; "required": false; }; "size": { "alias": "size"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "emptyText": { "alias": "emptyText"; "required": false; }; "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; }; }, { "change": "change"; }, ["customMenuItems"], ["[fw-menu-item, fw-menu-separator, fw-menu-item-group, fw-menu-header]"], false, never>;
81
+ static ɵcmp: i0.ɵɵComponentDeclaration<FwMultiSelectMenuComponent, "fw-multi-select", never, { "options": { "alias": "options"; "required": false; }; "valueProperty": { "alias": "valueProperty"; "required": false; }; "titleProperty": { "alias": "titleProperty"; "required": false; }; "iconProperty": { "alias": "iconProperty"; "required": false; }; "emptyText": { "alias": "emptyText"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "useCheckbox": { "alias": "useCheckbox"; "required": false; }; "closeOnSelect": { "alias": "closeOnSelect"; "required": false; }; "maxSelectedShown": { "alias": "maxSelectedShown"; "required": false; }; "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "showFilter": { "alias": "showFilter"; "required": false; "isSignal": true; }; "showSelectionInfo": { "alias": "showSelectionInfo"; "required": false; "isSignal": true; }; "filterItemsOnSelect": { "alias": "filterItemsOnSelect"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; }; "minHeight": { "alias": "minHeight"; "required": false; }; "maxHeight": { "alias": "maxHeight"; "required": false; }; "optionsWidth": { "alias": "optionsWidth"; "required": false; }; "minOptionsHeight": { "alias": "minOptionsHeight"; "required": false; }; "maxOptionsHeight": { "alias": "maxOptionsHeight"; "required": false; }; "size": { "alias": "size"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, { "change": "change"; }, ["customMenuItems"], ["[fw-menu-item, fw-menu-separator, fw-menu-item-group, fw-menu-header]"], false, never>;
67
82
  }
@@ -4,13 +4,14 @@ import * as i2 from "./select-menu.component";
4
4
  import * as i3 from "@angular/common";
5
5
  import * as i4 from "@angular/cdk/menu";
6
6
  import * as i5 from "@angular/forms";
7
- import * as i6 from "../chip/chip.module";
8
- import * as i7 from "../icon/icon.module";
9
- import * as i8 from "../menu/menu.module";
10
- import * as i9 from "../text-input/text-input.module";
11
- import * as i10 from "../../directives/menu-register.directive";
7
+ import * as i6 from "../button/button.module";
8
+ import * as i7 from "../chip/chip.module";
9
+ import * as i8 from "../icon/icon.module";
10
+ import * as i9 from "../menu/menu.module";
11
+ import * as i10 from "../text-input/text-input.module";
12
+ import * as i11 from "../../directives/menu-register.directive";
12
13
  export declare class FwSelectMenuModule {
13
14
  static ɵfac: i0.ɵɵFactoryDeclaration<FwSelectMenuModule, never>;
14
- static ɵmod: i0.ɵɵNgModuleDeclaration<FwSelectMenuModule, [typeof i1.FwMultiSelectMenuComponent, typeof i2.FwSelectMenuComponent], [typeof i3.CommonModule, typeof i4.CdkMenuModule, typeof i5.FormsModule, typeof i6.FwChipModule, typeof i7.FwIconModule, typeof i8.FwMenuModule, typeof i9.FwTextInputModule, typeof i10.MenuRegisterDirective], [typeof i1.FwMultiSelectMenuComponent, typeof i2.FwSelectMenuComponent]>;
15
+ static ɵmod: i0.ɵɵNgModuleDeclaration<FwSelectMenuModule, [typeof i1.FwMultiSelectMenuComponent, typeof i2.FwSelectMenuComponent], [typeof i3.CommonModule, typeof i4.CdkMenuModule, typeof i5.FormsModule, typeof i6.FwButtonModule, typeof i7.FwChipModule, typeof i8.FwIconModule, typeof i9.FwMenuModule, typeof i10.FwTextInputModule, typeof i11.MenuRegisterDirective], [typeof i1.FwMultiSelectMenuComponent, typeof i2.FwSelectMenuComponent]>;
15
16
  static ɵinj: i0.ɵɵInjectorDeclaration<FwSelectMenuModule>;
16
17
  }
@@ -1,4 +1,4 @@
1
- import { EventEmitter } from '@angular/core';
1
+ import { ElementRef, EventEmitter } from '@angular/core';
2
2
  import { ControlValueAccessor, FormControl } from '@angular/forms';
3
3
  import { IconType } from '../icon/icon.types';
4
4
  import * as i0 from "@angular/core";
@@ -22,9 +22,10 @@ export declare class FwTextInputComponent implements ControlValueAccessor {
22
22
  size?: 'small' | 'medium' | 'large';
23
23
  type?: string;
24
24
  maxLength?: number;
25
- autofocus?: string;
25
+ autofocus?: boolean;
26
26
  autocomplete?: string;
27
27
  value: string;
28
+ inputRef: ElementRef<HTMLInputElement>;
28
29
  error?: boolean;
29
30
  leftIconAction: EventEmitter<void>;
30
31
  rightIconAction: EventEmitter<void>;
@@ -41,6 +42,7 @@ export declare class FwTextInputComponent implements ControlValueAccessor {
41
42
  blurHandler(): void;
42
43
  onLeftIconClick(): void;
43
44
  onRightIconClick(): void;
45
+ focus(): void;
44
46
  static ɵfac: i0.ɵɵFactoryDeclaration<FwTextInputComponent, never>;
45
47
  static ɵcmp: i0.ɵɵComponentDeclaration<FwTextInputComponent, "fw-text-input", never, { "disabled": { "alias": "disabled"; "required": false; }; "useActionableIcons": { "alias": "useActionableIcons"; "required": false; }; "leftIcon": { "alias": "leftIcon"; "required": false; }; "rightIcon": { "alias": "rightIcon"; "required": false; }; "prefix": { "alias": "prefix"; "required": false; }; "context": { "alias": "context"; "required": false; }; "helperText": { "alias": "helperText"; "required": false; }; "errorText": { "alias": "errorText"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; "size": { "alias": "size"; "required": false; }; "type": { "alias": "type"; "required": false; }; "maxLength": { "alias": "maxLength"; "required": false; }; "autofocus": { "alias": "autofocus"; "required": false; }; "autocomplete": { "alias": "autocomplete"; "required": false; }; "value": { "alias": "value"; "required": false; }; "error": { "alias": "error"; "required": false; }; "width": { "alias": "width"; "required": false; }; }, { "leftIconAction": "leftIconAction"; "rightIconAction": "rightIconAction"; }, ["textInput"], ["input", "*"], false, never>;
46
48
  }
@@ -29,11 +29,11 @@ export class FwDialogComponent {
29
29
  this.close.emit();
30
30
  }
31
31
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FwDialogComponent, deps: [{ token: i1.DialogRef, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
32
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FwDialogComponent, selector: "fw-dialog", inputs: { width: "width", title: "title", icon: "icon", iconColor: "iconColor", showClose: "showClose" }, outputs: { close: "close" }, host: { properties: { "attr.class": "this.classes" } }, ngImport: i0, template: "<div class=\"dialog\">\n <fw-icon-button\n *ngIf=\"showClose\"\n tabindex=\"-1\" icon=\"close\" color=\"slate\"\n (click)=\"handleCloseButton()\">\n </fw-icon-button>\n <div class=\"dialog-header\">\n <ng-content select=\"fw-dialog-header\"></ng-content>\n <div class=\"dialog-title\" *ngIf=\"title\">\n <fw-icon *ngIf=\"icon\" [color]=\"iconColor\">{{ icon }}</fw-icon>\n <h3 class=\"vision-h3\">{{ title }}</h3>\n </div>\n </div>\n <div class=\"dialog-body\">\n <ng-content select=\"fw-dialog-content\"></ng-content>\n </div>\n <div class=\"dialog-actions\">\n <ng-content select=\"fw-dialog-actions\"></ng-content>\n </div>\n</div>\n", styles: [":host{box-sizing:border-box;background-color:var(--card-background);border:1px solid var(--separations-border);border-radius:8px;display:flex;flex-direction:column;overflow:hidden}:host.dialog-width-extra-small{width:444px}:host.dialog-width-small{width:600px}:host.dialog-width-medium{width:900px}:host.dialog-width-large{width:1200px}:host.dialog-width-extra-large{width:1536px}:host .dialog{position:relative}:host .dialog fw-icon-button{position:absolute;top:4px;right:4px}:host .dialog .dialog-header{background-color:var(--card-header)}:host .dialog .dialog-header .dialog-title{display:flex;gap:8px;box-sizing:border-box;border-bottom:1px solid var(--separations-base);padding:12px 16px;height:44px;overflow:hidden;align-items:center}:host .dialog .dialog-header .dialog-title fw-icon{font-size:22px}:host .dialog .dialog-header .dialog-title h3{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-right:30px;flex:1}:host .dialog .dialog-header h3{margin:0}:host .dialog .dialog-header:empty{display:none}:host .dialog .dialog-body{background-color:var(--card-background);border-bottom:1px solid var(--separations-base)}:host .dialog .dialog-body:empty{display:none}:host .dialog .dialog-actions{padding:16px}:host .dialog .dialog-actions:empty{display:none}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.FwIconButtonComponent, selector: "fw-icon-button", inputs: ["color", "icon", "size", "disabled", "selected"] }, { kind: "component", type: i4.FwIconComponent, selector: "fw-icon", inputs: ["size", "color"] }] }); }
32
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FwDialogComponent, selector: "fw-dialog", inputs: { width: "width", title: "title", icon: "icon", iconColor: "iconColor", showClose: "showClose" }, outputs: { close: "close" }, host: { properties: { "attr.class": "this.classes" } }, ngImport: i0, template: "<div class=\"dialog\">\n <fw-icon-button\n *ngIf=\"showClose\"\n tabindex=\"-1\" icon=\"close\" color=\"slate\"\n (click)=\"handleCloseButton()\">\n </fw-icon-button>\n <div class=\"dialog-header\">\n <ng-content select=\"fw-dialog-header\"></ng-content>\n <div class=\"dialog-title\" *ngIf=\"title\">\n <fw-icon *ngIf=\"icon\" [color]=\"iconColor\">{{ icon }}</fw-icon>\n <h3 class=\"vision-h3\">{{ title }}</h3>\n </div>\n </div>\n <div class=\"dialog-body\">\n <ng-content select=\"fw-dialog-content\"></ng-content>\n </div>\n <div class=\"dialog-actions\">\n <ng-content select=\"fw-dialog-actions\"></ng-content>\n </div>\n</div>\n", styles: [":host{box-sizing:border-box;background-color:var(--card-background);border:1px solid var(--separations-border);border-radius:8px;display:flex;flex-direction:column;overflow:hidden}:host.dialog-width-extra-small{width:444px}:host.dialog-width-small{width:600px}:host.dialog-width-medium{width:900px}:host.dialog-width-large{width:1200px}:host.dialog-width-extra-large{width:1536px}:host .dialog{position:relative}:host .dialog fw-icon-button{position:absolute;top:4px;right:4px}:host .dialog .dialog-header{background-color:var(--card-header)}:host .dialog .dialog-header .dialog-title{display:flex;gap:8px;box-sizing:border-box;border-bottom:1px solid var(--separations-base);padding:12px 16px;height:44px;overflow:hidden;align-items:center}:host .dialog .dialog-header .dialog-title fw-icon{font-size:22px}:host .dialog .dialog-header .dialog-title h3{overflow:clip visible;min-width:0;white-space:nowrap;text-overflow:ellipsis;margin-right:30px;flex:1}:host .dialog .dialog-header h3{margin:0}:host .dialog .dialog-header:empty{display:none}:host .dialog .dialog-body{background-color:var(--card-background);border-bottom:1px solid var(--separations-base)}:host .dialog .dialog-body:empty{display:none}:host .dialog .dialog-actions{padding:16px}:host .dialog .dialog-actions:empty{display:none}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.FwIconButtonComponent, selector: "fw-icon-button", inputs: ["color", "icon", "size", "disabled", "selected"] }, { kind: "component", type: i4.FwIconComponent, selector: "fw-icon", inputs: ["size", "color"] }] }); }
33
33
  }
34
34
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FwDialogComponent, decorators: [{
35
35
  type: Component,
36
- args: [{ selector: 'fw-dialog', template: "<div class=\"dialog\">\n <fw-icon-button\n *ngIf=\"showClose\"\n tabindex=\"-1\" icon=\"close\" color=\"slate\"\n (click)=\"handleCloseButton()\">\n </fw-icon-button>\n <div class=\"dialog-header\">\n <ng-content select=\"fw-dialog-header\"></ng-content>\n <div class=\"dialog-title\" *ngIf=\"title\">\n <fw-icon *ngIf=\"icon\" [color]=\"iconColor\">{{ icon }}</fw-icon>\n <h3 class=\"vision-h3\">{{ title }}</h3>\n </div>\n </div>\n <div class=\"dialog-body\">\n <ng-content select=\"fw-dialog-content\"></ng-content>\n </div>\n <div class=\"dialog-actions\">\n <ng-content select=\"fw-dialog-actions\"></ng-content>\n </div>\n</div>\n", styles: [":host{box-sizing:border-box;background-color:var(--card-background);border:1px solid var(--separations-border);border-radius:8px;display:flex;flex-direction:column;overflow:hidden}:host.dialog-width-extra-small{width:444px}:host.dialog-width-small{width:600px}:host.dialog-width-medium{width:900px}:host.dialog-width-large{width:1200px}:host.dialog-width-extra-large{width:1536px}:host .dialog{position:relative}:host .dialog fw-icon-button{position:absolute;top:4px;right:4px}:host .dialog .dialog-header{background-color:var(--card-header)}:host .dialog .dialog-header .dialog-title{display:flex;gap:8px;box-sizing:border-box;border-bottom:1px solid var(--separations-base);padding:12px 16px;height:44px;overflow:hidden;align-items:center}:host .dialog .dialog-header .dialog-title fw-icon{font-size:22px}:host .dialog .dialog-header .dialog-title h3{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;margin-right:30px;flex:1}:host .dialog .dialog-header h3{margin:0}:host .dialog .dialog-header:empty{display:none}:host .dialog .dialog-body{background-color:var(--card-background);border-bottom:1px solid var(--separations-base)}:host .dialog .dialog-body:empty{display:none}:host .dialog .dialog-actions{padding:16px}:host .dialog .dialog-actions:empty{display:none}\n"] }]
36
+ args: [{ selector: 'fw-dialog', template: "<div class=\"dialog\">\n <fw-icon-button\n *ngIf=\"showClose\"\n tabindex=\"-1\" icon=\"close\" color=\"slate\"\n (click)=\"handleCloseButton()\">\n </fw-icon-button>\n <div class=\"dialog-header\">\n <ng-content select=\"fw-dialog-header\"></ng-content>\n <div class=\"dialog-title\" *ngIf=\"title\">\n <fw-icon *ngIf=\"icon\" [color]=\"iconColor\">{{ icon }}</fw-icon>\n <h3 class=\"vision-h3\">{{ title }}</h3>\n </div>\n </div>\n <div class=\"dialog-body\">\n <ng-content select=\"fw-dialog-content\"></ng-content>\n </div>\n <div class=\"dialog-actions\">\n <ng-content select=\"fw-dialog-actions\"></ng-content>\n </div>\n</div>\n", styles: [":host{box-sizing:border-box;background-color:var(--card-background);border:1px solid var(--separations-border);border-radius:8px;display:flex;flex-direction:column;overflow:hidden}:host.dialog-width-extra-small{width:444px}:host.dialog-width-small{width:600px}:host.dialog-width-medium{width:900px}:host.dialog-width-large{width:1200px}:host.dialog-width-extra-large{width:1536px}:host .dialog{position:relative}:host .dialog fw-icon-button{position:absolute;top:4px;right:4px}:host .dialog .dialog-header{background-color:var(--card-header)}:host .dialog .dialog-header .dialog-title{display:flex;gap:8px;box-sizing:border-box;border-bottom:1px solid var(--separations-base);padding:12px 16px;height:44px;overflow:hidden;align-items:center}:host .dialog .dialog-header .dialog-title fw-icon{font-size:22px}:host .dialog .dialog-header .dialog-title h3{overflow:clip visible;min-width:0;white-space:nowrap;text-overflow:ellipsis;margin-right:30px;flex:1}:host .dialog .dialog-header h3{margin:0}:host .dialog .dialog-header:empty{display:none}:host .dialog .dialog-body{background-color:var(--card-background);border-bottom:1px solid var(--separations-base)}:host .dialog .dialog-body:empty{display:none}:host .dialog .dialog-actions{padding:16px}:host .dialog .dialog-actions:empty{display:none}\n"] }]
37
37
  }], ctorParameters: () => [{ type: i1.DialogRef, decorators: [{
38
38
  type: Optional
39
39
  }] }], propDecorators: { width: [{
@@ -1,10 +1,13 @@
1
- import { Component, ContentChild, EventEmitter, HostBinding, Input, Output, ViewEncapsulation, } from '@angular/core';
1
+ import { coerceBooleanProperty } from '@angular/cdk/coercion';
2
+ import { Component, computed, ContentChild, contentChildren, HostBinding, Input, input, output, signal, ViewChild, ViewEncapsulation, } from '@angular/core';
2
3
  import { FwMenuComponent } from '../menu.component';
4
+ import { FwMenuItemComponent } from '../menu-item/menu-item.component';
3
5
  import * as i0 from "@angular/core";
4
6
  import * as i1 from "@angular/platform-browser";
5
7
  import * as i2 from "@angular/cdk/menu";
6
8
  import * as i3 from "@angular/common";
7
9
  import * as i4 from "../../text-input/text-input.component";
10
+ import * as i5 from "../menu-item/menu-item.component";
8
11
  export class FwMenuContainerComponent {
9
12
  get classes() {
10
13
  return [
@@ -31,32 +34,60 @@ export class FwMenuContainerComponent {
31
34
  this.shadow = 'large';
32
35
  this.showFilter = false;
33
36
  this.filterText = '';
37
+ this.focusFilterOnMount = false;
34
38
  this.offset = '0px';
35
- /**
36
- * @deprecated please use fw-navbar instead
37
- */
38
- this.collapsed = false;
39
- this.filterChanged = new EventEmitter();
39
+ this.emptyText = input('No results');
40
+ this.filteredMenuItemChange = output();
41
+ this.defaultFilterFn = (filter, menuItems) => {
42
+ return menuItems.filter(menuItem => menuItem.title.toLowerCase().includes(filter.toLowerCase()));
43
+ };
44
+ this.filterFn = input(this.defaultFilterFn);
45
+ this.filterChanged = output();
46
+ // for passing menu items for the container to filter
47
+ // works around a problem with nested content children
48
+ // @see https://stackoverflow.com/questions/62886613/angular-9-nested-ng-content-and-contentchildren
49
+ this.additionalMenuItems = input([]);
50
+ this.childMenuItems = contentChildren(FwMenuItemComponent, { descendants: true });
51
+ this.combinedMenuItems = computed(() => {
52
+ return [...this.childMenuItems(), ...this.additionalMenuItems()];
53
+ });
54
+ this.noResults = signal(false);
40
55
  }
41
- ngAfterContentInit() {
42
- if (this.menu) {
43
- this.menu.setFilter(this.filterText);
56
+ ngAfterViewInit() {
57
+ if (this.focusFilterOnMount && this.showFilter) {
58
+ // eslint-disable-next-line @rx-angular/prefer-no-layout-sensitive-apis
59
+ this.filterRef?.focus();
44
60
  }
61
+ // we need to run the filter on init in case the custom filter is filtering things
62
+ this.onFilterChange('');
45
63
  }
46
- filterTextChange(event) {
64
+ handleFilterClick(event) {
65
+ // stops filters in menus from closing the parent menu
66
+ event.stopPropagation();
67
+ }
68
+ handleFilterInput(event) {
47
69
  const input = event.target;
48
- const inputValue = input.value;
49
- this.filterChanged.emit(inputValue);
50
- if (this.menu) {
51
- this.menu.setFilter(inputValue);
52
- }
70
+ const filterValue = input.value;
71
+ this.onFilterChange(filterValue);
72
+ }
73
+ onFilterChange(filter) {
74
+ const allMenuItems = this.combinedMenuItems();
75
+ this.filterChanged.emit(filter);
76
+ const filterFn = this.filterFn();
77
+ this.filteredMenuItems = filterFn(filter, allMenuItems);
78
+ allMenuItems.forEach(menuItem => {
79
+ const shouldBeHidden = !this.filteredMenuItems.includes(menuItem);
80
+ menuItem.hidden = shouldBeHidden;
81
+ });
82
+ this.noResults.set(allMenuItems.every(item => item.hidden));
83
+ this.filteredMenuItemChange.emit(this.filteredMenuItems);
53
84
  }
54
85
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FwMenuContainerComponent, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
55
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FwMenuContainerComponent, selector: "fw-menu-container", inputs: { width: "width", maxHeight: "maxHeight", minHeight: "minHeight", border: "border", shadow: "shadow", showFilter: "showFilter", filterText: "filterText", offset: "offset", collapsed: "collapsed" }, outputs: { filterChanged: "filterChanged" }, host: { properties: { "attr.class": "this.classes", "style": "this.style" } }, queries: [{ propertyName: "menu", first: true, predicate: FwMenuComponent, descendants: true }], ngImport: i0, template: "<div *ngIf=\"showFilter\" class=\"filter-box\" cdkMenuBar>\n <fw-text-input\n placeholder=\"Search\" leftIcon=\"search\" autofocus\n [value]=\"filterText\" (input)=\"filterTextChange($event)\">\n </fw-text-input>\n</div>\n<div class=\"menu-wrapper\" [ngClass]=\"[showFilter?'filtered':'', collapsed?'collapsed':'']\">\n <ng-content></ng-content>\n</div>\n", styles: [".fw-menu-container{display:flex;border-radius:8px;background:var(--card-background);position:relative}.fw-menu-container.border-default{border:1px solid var(--separations-border)}.fw-menu-container .filter-box{border-top-left-radius:8px;border-top-right-radius:8px;padding:8px;border-bottom:1px solid var(--separations-base);background-color:var(--card-background);position:absolute;left:0;right:0;z-index:1}.fw-menu-container .menu-wrapper{flex:1;padding:6px 4px;scroll-padding:17px;overflow:hidden auto}.fw-menu-container .menu-wrapper.collapsed{scrollbar-width:none}.fw-menu-container .menu-wrapper.filtered{margin-top:54px}.fw-menu-container fw-menu-separator{margin:6px -8px}\n"], dependencies: [{ kind: "directive", type: i2.CdkMenuBar, selector: "[cdkMenuBar]", exportAs: ["cdkMenuBar"] }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.FwTextInputComponent, selector: "fw-text-input", inputs: ["disabled", "useActionableIcons", "leftIcon", "rightIcon", "prefix", "context", "helperText", "errorText", "placeholder", "readOnly", "size", "type", "maxLength", "autofocus", "autocomplete", "value", "error", "width"], outputs: ["leftIconAction", "rightIconAction"] }], encapsulation: i0.ViewEncapsulation.None }); }
86
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "17.3.12", type: FwMenuContainerComponent, selector: "fw-menu-container, fw-menu-filter", inputs: { width: { classPropertyName: "width", publicName: "width", isSignal: false, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: false, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: false, isRequired: false, transformFunction: null }, border: { classPropertyName: "border", publicName: "border", isSignal: false, isRequired: false, transformFunction: null }, shadow: { classPropertyName: "shadow", publicName: "shadow", isSignal: false, isRequired: false, transformFunction: null }, showFilter: { classPropertyName: "showFilter", publicName: "showFilter", isSignal: false, isRequired: false, transformFunction: (val) => coerceBooleanProperty(val) }, filterText: { classPropertyName: "filterText", publicName: "filterText", isSignal: false, isRequired: false, transformFunction: null }, focusFilterOnMount: { classPropertyName: "focusFilterOnMount", publicName: "focusFilterOnMount", isSignal: false, isRequired: false, transformFunction: (val) => coerceBooleanProperty(val) }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: false, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, filterFn: { classPropertyName: "filterFn", publicName: "filterFn", isSignal: true, isRequired: false, transformFunction: null }, additionalMenuItems: { classPropertyName: "additionalMenuItems", publicName: "additionalMenuItems", isSignal: true, isRequired: false, transformFunction: null }, keyHandler: { classPropertyName: "keyHandler", publicName: "keyHandler", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { filteredMenuItemChange: "filteredMenuItemChange", filterChanged: "filterChanged" }, host: { properties: { "attr.class": "this.classes", "style": "this.style" } }, queries: [{ propertyName: "childMenuItems", predicate: FwMenuItemComponent, descendants: true, isSignal: true }, { propertyName: "menu", first: true, predicate: FwMenuComponent, descendants: true }], viewQueries: [{ propertyName: "filterRef", first: true, predicate: ["menuFilter"], descendants: true }], ngImport: i0, template: "<div #filterBox *ngIf=\"showFilter\" class=\"filter-box\" cdkMenuBar>\n <fw-text-input\n (click)=\"handleFilterClick($event)\"\n #menuFilter\n (keydown)=\"keyHandler?.($event)\"\n placeholder=\"Search\" leftIcon=\"search\" autofocus\n [value]=\"filterText\" (input)=\"handleFilterInput($event)\">\n </fw-text-input>\n <ng-content select=\".filter-content\"></ng-content>\n</div>\n<div class=\"menu-wrapper\">\n <fw-menu-item *ngIf=\"noResults()\" [title]=\"emptyText()\" [disabled]=\"true\"></fw-menu-item>\n <ng-content></ng-content>\n <ng-content select=\"custom-menu-items\"></ng-content>\n</div>\n", styles: [".fw-menu-container{display:flex;flex-direction:column;border-radius:8px;background:var(--card-background);position:relative}.fw-menu-container.border-default{border:1px solid var(--separations-border)}.fw-menu-container .filter-box{border-top-left-radius:8px;border-top-right-radius:8px;padding:8px;border-bottom:1px solid var(--separations-base);background-color:var(--card-background);max-width:calc(100% - 16px);height:fit-content}.fw-menu-container .menu-wrapper{flex:1;padding:6px 4px;overflow:hidden auto;margin-bottom:4px}.fw-menu-container fw-menu-separator{margin:6px -8px}\n"], dependencies: [{ kind: "directive", type: i2.CdkMenuBar, selector: "[cdkMenuBar]", exportAs: ["cdkMenuBar"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.FwTextInputComponent, selector: "fw-text-input", inputs: ["disabled", "useActionableIcons", "leftIcon", "rightIcon", "prefix", "context", "helperText", "errorText", "placeholder", "readOnly", "size", "type", "maxLength", "autofocus", "autocomplete", "value", "error", "width"], outputs: ["leftIconAction", "rightIconAction"] }, { kind: "component", type: i5.FwMenuItemComponent, selector: "fw-menu-item", inputs: ["value", "size", "title", "description", "icon", "iconColor", "disabled", "showCheckbox", "checkboxColor", "multiSelect", "hidden", "collapsed", "href", "target", "subItemsOpen", "focused", "selected"], outputs: ["click"] }], encapsulation: i0.ViewEncapsulation.None }); }
56
87
  }
57
88
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FwMenuContainerComponent, decorators: [{
58
89
  type: Component,
59
- args: [{ selector: 'fw-menu-container', encapsulation: ViewEncapsulation.None, template: "<div *ngIf=\"showFilter\" class=\"filter-box\" cdkMenuBar>\n <fw-text-input\n placeholder=\"Search\" leftIcon=\"search\" autofocus\n [value]=\"filterText\" (input)=\"filterTextChange($event)\">\n </fw-text-input>\n</div>\n<div class=\"menu-wrapper\" [ngClass]=\"[showFilter?'filtered':'', collapsed?'collapsed':'']\">\n <ng-content></ng-content>\n</div>\n", styles: [".fw-menu-container{display:flex;border-radius:8px;background:var(--card-background);position:relative}.fw-menu-container.border-default{border:1px solid var(--separations-border)}.fw-menu-container .filter-box{border-top-left-radius:8px;border-top-right-radius:8px;padding:8px;border-bottom:1px solid var(--separations-base);background-color:var(--card-background);position:absolute;left:0;right:0;z-index:1}.fw-menu-container .menu-wrapper{flex:1;padding:6px 4px;scroll-padding:17px;overflow:hidden auto}.fw-menu-container .menu-wrapper.collapsed{scrollbar-width:none}.fw-menu-container .menu-wrapper.filtered{margin-top:54px}.fw-menu-container fw-menu-separator{margin:6px -8px}\n"] }]
90
+ args: [{ selector: 'fw-menu-container, fw-menu-filter', encapsulation: ViewEncapsulation.None, template: "<div #filterBox *ngIf=\"showFilter\" class=\"filter-box\" cdkMenuBar>\n <fw-text-input\n (click)=\"handleFilterClick($event)\"\n #menuFilter\n (keydown)=\"keyHandler?.($event)\"\n placeholder=\"Search\" leftIcon=\"search\" autofocus\n [value]=\"filterText\" (input)=\"handleFilterInput($event)\">\n </fw-text-input>\n <ng-content select=\".filter-content\"></ng-content>\n</div>\n<div class=\"menu-wrapper\">\n <fw-menu-item *ngIf=\"noResults()\" [title]=\"emptyText()\" [disabled]=\"true\"></fw-menu-item>\n <ng-content></ng-content>\n <ng-content select=\"custom-menu-items\"></ng-content>\n</div>\n", styles: [".fw-menu-container{display:flex;flex-direction:column;border-radius:8px;background:var(--card-background);position:relative}.fw-menu-container.border-default{border:1px solid var(--separations-border)}.fw-menu-container .filter-box{border-top-left-radius:8px;border-top-right-radius:8px;padding:8px;border-bottom:1px solid var(--separations-base);background-color:var(--card-background);max-width:calc(100% - 16px);height:fit-content}.fw-menu-container .menu-wrapper{flex:1;padding:6px 4px;overflow:hidden auto;margin-bottom:4px}.fw-menu-container fw-menu-separator{margin:6px -8px}\n"] }]
60
91
  }], ctorParameters: () => [{ type: i1.DomSanitizer }], propDecorators: { width: [{
61
92
  type: Input
62
93
  }], maxHeight: [{
@@ -68,18 +99,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
68
99
  }], shadow: [{
69
100
  type: Input
70
101
  }], showFilter: [{
71
- type: Input
102
+ type: Input,
103
+ args: [{ transform: (val) => coerceBooleanProperty(val) }]
72
104
  }], filterText: [{
73
105
  type: Input
106
+ }], focusFilterOnMount: [{
107
+ type: Input,
108
+ args: [{ transform: (val) => coerceBooleanProperty(val) }]
74
109
  }], offset: [{
75
110
  type: Input
76
- }], collapsed: [{
77
- type: Input
78
- }], filterChanged: [{
79
- type: Output
111
+ }], filterRef: [{
112
+ type: ViewChild,
113
+ args: ['menuFilter']
80
114
  }], menu: [{
81
115
  type: ContentChild,
82
116
  args: [FwMenuComponent]
117
+ }], keyHandler: [{
118
+ type: Input
83
119
  }], classes: [{
84
120
  type: HostBinding,
85
121
  args: ['attr.class']
@@ -87,4 +123,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
87
123
  type: HostBinding,
88
124
  args: ['style']
89
125
  }] } });
90
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudS1jb250YWluZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvbWVudS9tZW51LWNvbnRhaW5lci9tZW51LWNvbnRhaW5lci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9tZW51L21lbnUtY29udGFpbmVyL21lbnUtY29udGFpbmVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFFTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLFlBQVksRUFDWixXQUFXLEVBQ1gsS0FBSyxFQUNMLE1BQU0sRUFDTixpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDOzs7Ozs7QUFRcEQsTUFBTSxPQUFPLHdCQUF3QjtJQWtCbkMsSUFBK0IsT0FBTztRQUNwQyxPQUFPO1lBQ0wsbUJBQW1CO1lBQ25CLGlCQUFpQixJQUFJLENBQUMsTUFBTSxFQUFFO1lBQzlCLFVBQVUsSUFBSSxDQUFDLE1BQU0sRUFBRTtTQUN4QixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNkLENBQUM7SUFBQSxDQUFDO0lBRUYsSUFBMEIsS0FBSztRQUM3QixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsd0JBQXdCLENBQUM7ZUFDcEMsSUFBSSxDQUFDLEtBQUs7b0JBQ0wsSUFBSSxDQUFDLFNBQVM7b0JBQ2QsSUFBSSxDQUFDLFNBQVM7b0JBQ2QsSUFBSSxDQUFDLE1BQU07S0FDMUIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFlBQW9CLFNBQXVCO1FBQXZCLGNBQVMsR0FBVCxTQUFTLENBQWM7UUFsQ2xDLFVBQUssR0FBWSxTQUFTLENBQUM7UUFDM0IsY0FBUyxHQUFZLE1BQU0sQ0FBQztRQUM1QixjQUFTLEdBQVksTUFBTSxDQUFDO1FBQzVCLFdBQU0sR0FBd0IsU0FBUyxDQUFDO1FBQ3hDLFdBQU0sR0FBcUUsT0FBTyxDQUFDO1FBQ25GLGVBQVUsR0FBYSxLQUFLLENBQUM7UUFDN0IsZUFBVSxHQUFZLEVBQUUsQ0FBQztRQUN6QixXQUFNLEdBQVksS0FBSyxDQUFDO1FBQ2pDOztXQUVHO1FBQ00sY0FBUyxHQUFhLEtBQUssQ0FBQztRQUVsQixrQkFBYSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7SUFzQjlELENBQUM7SUFFRCxrQkFBa0I7UUFDaEIsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDZCxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNILENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxLQUFZO1FBQzNCLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUEwQixDQUFDO1FBQy9DLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFFL0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFcEMsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDZCxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNsQyxDQUFDO0lBQ0gsQ0FBQzsrR0FyRFUsd0JBQXdCO21HQUF4Qix3QkFBd0IscWFBZ0JyQixlQUFlLGdEQ3BDL0IsOFdBU0E7OzRGRFdhLHdCQUF3QjtrQkFOcEMsU0FBUzsrQkFDRSxtQkFBbUIsaUJBR2QsaUJBQWlCLENBQUMsSUFBSTtpRkFHNUIsS0FBSztzQkFBYixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUs7Z0JBSUcsU0FBUztzQkFBakIsS0FBSztnQkFFYSxhQUFhO3NCQUEvQixNQUFNO2dCQUV3QixJQUFJO3NCQUFsQyxZQUFZO3VCQUFDLGVBQWU7Z0JBRUUsT0FBTztzQkFBckMsV0FBVzt1QkFBQyxZQUFZO2dCQVFDLEtBQUs7c0JBQTlCLFdBQVc7dUJBQUMsT0FBTyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyQ29udGVudEluaXQsXG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkLFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RCaW5kaW5nLFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBEb21TYW5pdGl6ZXIsIFNhZmVTdHlsZSB9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xuXG5pbXBvcnQgeyBGd01lbnVDb21wb25lbnQgfSBmcm9tICcuLi9tZW51LmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2Z3LW1lbnUtY29udGFpbmVyJyxcbiAgdGVtcGxhdGVVcmw6ICcuL21lbnUtY29udGFpbmVyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vbWVudS1jb250YWluZXIuY29tcG9uZW50LnNjc3MnXSxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbn0pXG5leHBvcnQgY2xhc3MgRndNZW51Q29udGFpbmVyQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCB7XG4gIEBJbnB1dCgpIHdpZHRoPzogc3RyaW5nID0gJ2luaGVyaXQnO1xuICBASW5wdXQoKSBtYXhIZWlnaHQ/OiBzdHJpbmcgPSAnYXV0byc7XG4gIEBJbnB1dCgpIG1pbkhlaWdodD86IHN0cmluZyA9ICdhdXRvJztcbiAgQElucHV0KCkgYm9yZGVyPzogJ25vbmUnIHwgJ2RlZmF1bHQnID0gJ2RlZmF1bHQnO1xuICBASW5wdXQoKSBzaGFkb3c/OiAnbm9uZScgfCAnc21hbGwnIHwgJ21lZGl1bScgfCAnbGFyZ2UnIHwgJ2V4dHJhLWxhcmdlJyB8ICdpbm5lcicgPSAnbGFyZ2UnO1xuICBASW5wdXQoKSBzaG93RmlsdGVyPzogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBmaWx0ZXJUZXh0Pzogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIG9mZnNldD86IHN0cmluZyA9ICcwcHgnO1xuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgcGxlYXNlIHVzZSBmdy1uYXZiYXIgaW5zdGVhZFxuICAgKi9cbiAgQElucHV0KCkgY29sbGFwc2VkPzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIEBPdXRwdXQoKSByZWFkb25seSBmaWx0ZXJDaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgQENvbnRlbnRDaGlsZChGd01lbnVDb21wb25lbnQpIG1lbnU6IEZ3TWVudUNvbXBvbmVudDtcblxuICBASG9zdEJpbmRpbmcoJ2F0dHIuY2xhc3MnKSBnZXQgY2xhc3NlcygpOiBzdHJpbmcge1xuICAgIHJldHVybiBbXG4gICAgICAnZnctbWVudS1jb250YWluZXInLFxuICAgICAgYHZpc2lvbi1zaGFkb3ctJHt0aGlzLnNoYWRvd31gLFxuICAgICAgYGJvcmRlci0ke3RoaXMuYm9yZGVyfWAsXG4gICAgXS5qb2luKCcgJyk7XG4gIH07XG5cbiAgQEhvc3RCaW5kaW5nKCdzdHlsZScpIGdldCBzdHlsZSgpOiBTYWZlU3R5bGUge1xuICAgIHJldHVybiB0aGlzLnNhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0U3R5bGUoYFxuICAgICAgd2lkdGg6ICR7dGhpcy53aWR0aH07XG4gICAgICBtYXgtaGVpZ2h0OiAke3RoaXMubWF4SGVpZ2h0fTtcbiAgICAgIG1pbi1oZWlnaHQ6ICR7dGhpcy5taW5IZWlnaHR9O1xuICAgICAgbWFyZ2luLXRvcDogJHt0aGlzLm9mZnNldH07XG4gICAgYCk7XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNhbml0aXplcjogRG9tU2FuaXRpemVyKSB7XG4gIH1cblxuICBuZ0FmdGVyQ29udGVudEluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubWVudSkge1xuICAgICAgdGhpcy5tZW51LnNldEZpbHRlcih0aGlzLmZpbHRlclRleHQpO1xuICAgIH1cbiAgfVxuXG4gIGZpbHRlclRleHRDaGFuZ2UoZXZlbnQ6IEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgaW5wdXQgPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcbiAgICBjb25zdCBpbnB1dFZhbHVlID0gaW5wdXQudmFsdWU7XG5cbiAgICB0aGlzLmZpbHRlckNoYW5nZWQuZW1pdChpbnB1dFZhbHVlKTtcblxuICAgIGlmICh0aGlzLm1lbnUpIHtcbiAgICAgIHRoaXMubWVudS5zZXRGaWx0ZXIoaW5wdXRWYWx1ZSk7XG4gICAgfVxuICB9XG5cbn1cbiIsIjxkaXYgKm5nSWY9XCJzaG93RmlsdGVyXCIgY2xhc3M9XCJmaWx0ZXItYm94XCIgY2RrTWVudUJhcj5cbiAgPGZ3LXRleHQtaW5wdXRcbiAgICBwbGFjZWhvbGRlcj1cIlNlYXJjaFwiIGxlZnRJY29uPVwic2VhcmNoXCIgYXV0b2ZvY3VzXG4gICAgW3ZhbHVlXT1cImZpbHRlclRleHRcIiAoaW5wdXQpPVwiZmlsdGVyVGV4dENoYW5nZSgkZXZlbnQpXCI+XG4gIDwvZnctdGV4dC1pbnB1dD5cbjwvZGl2PlxuPGRpdiBjbGFzcz1cIm1lbnUtd3JhcHBlclwiIFtuZ0NsYXNzXT1cIltzaG93RmlsdGVyPydmaWx0ZXJlZCc6JycsIGNvbGxhcHNlZD8nY29sbGFwc2VkJzonJ11cIj5cbiAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuPC9kaXY+XG4iXX0=
126
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudS1jb250YWluZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvbWVudS9tZW51LWNvbnRhaW5lci9tZW51LWNvbnRhaW5lci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9tZW51L21lbnUtY29udGFpbmVyL21lbnUtY29udGFpbmVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBZ0IscUJBQXFCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM1RSxPQUFPLEVBRUwsU0FBUyxFQUNULFFBQVEsRUFDUixZQUFZLEVBQ1osZUFBZSxFQUNmLFdBQVcsRUFDWCxLQUFLLEVBQ0wsS0FBSyxFQUNMLE1BQU0sRUFDTixNQUFNLEVBQ04sU0FBUyxFQUNULGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUl2QixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDcEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7Ozs7Ozs7QUFRdkUsTUFBTSxPQUFPLHdCQUF3QjtJQXNDbkMsSUFBK0IsT0FBTztRQUNwQyxPQUFPO1lBQ0wsbUJBQW1CO1lBQ25CLGlCQUFpQixJQUFJLENBQUMsTUFBTSxFQUFFO1lBQzlCLFVBQVUsSUFBSSxDQUFDLE1BQU0sRUFBRTtTQUN4QixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNkLENBQUM7SUFBQSxDQUFDO0lBRUYsSUFBMEIsS0FBSztRQUM3QixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsd0JBQXdCLENBQUM7ZUFDcEMsSUFBSSxDQUFDLEtBQUs7b0JBQ0wsSUFBSSxDQUFDLFNBQVM7b0JBQ2QsSUFBSSxDQUFDLFNBQVM7b0JBQ2QsSUFBSSxDQUFDLE1BQU07S0FDMUIsQ0FBQyxDQUFDO0lBQ0ws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RXlCLE9BQU87c0JBQXJDLFdBQVc7dUJBQUMsWUFBWTtnQkFRQyxLQUFLO3NCQUE5QixXQUFXO3VCQUFDLE9BQU8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCb29sZWFuSW5wdXQsIGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDb21wb25lbnQsXG4gIGNvbXB1dGVkLFxuICBDb250ZW50Q2hpbGQsXG4gIGNvbnRlbnRDaGlsZHJlbixcbiAgSG9zdEJpbmRpbmcsXG4gIElucHV0LFxuICBpbnB1dCxcbiAgb3V0cHV0LFxuICBzaWduYWwsXG4gIFZpZXdDaGlsZCxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRG9tU2FuaXRpemVyLCBTYWZlU3R5bGUgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcblxuaW1wb3J0IHsgRndUZXh0SW5wdXRDb21wb25lbnQgfSBmcm9tICcuLi8uLi90ZXh0LWlucHV0L3RleHQtaW5wdXQuY29tcG9uZW50JztcbmltcG9ydCB7IEZ3TWVudUNvbXBvbmVudCB9IGZyb20gJy4uL21lbnUuY29tcG9uZW50JztcbmltcG9ydCB7IEZ3TWVudUl0ZW1Db21wb25lbnQgfSBmcm9tICcuLi9tZW51LWl0ZW0vbWVudS1pdGVtLmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2Z3LW1lbnUtY29udGFpbmVyLCBmdy1tZW51LWZpbHRlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9tZW51LWNvbnRhaW5lci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL21lbnUtY29udGFpbmVyLmNvbXBvbmVudC5zY3NzJ10sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG59KVxuZXhwb3J0IGNsYXNzIEZ3TWVudUNvbnRhaW5lckNvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQge1xuXG4gIEBJbnB1dCgpIHdpZHRoPzogc3RyaW5nID0gJ2luaGVyaXQnO1xuICBASW5wdXQoKSBtYXhIZWlnaHQ/OiBzdHJpbmcgPSAnYXV0byc7XG4gIEBJbnB1dCgpIG1pbkhlaWdodD86IHN0cmluZyA9ICdhdXRvJztcbiAgQElucHV0KCkgYm9yZGVyPzogJ25vbmUnIHwgJ2RlZmF1bHQnID0gJ2RlZmF1bHQnO1xuICBASW5wdXQoKSBzaGFkb3c/OiAnbm9uZScgfCAnc21hbGwnIHwgJ21lZGl1bScgfCAnbGFyZ2UnIHwgJ2V4dHJhLWxhcmdlJyB8ICdpbm5lcicgPSAnbGFyZ2UnO1xuICBASW5wdXQoeyB0cmFuc2Zvcm06ICh2YWw6IEJvb2xlYW5JbnB1dCkgPT4gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbCkgfSkgc2hvd0ZpbHRlcjogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBmaWx0ZXJUZXh0Pzogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogKHZhbDogQm9vbGVhbklucHV0KSA9PiBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsKSB9KSBmb2N1c0ZpbHRlck9uTW91bnQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgb2Zmc2V0Pzogc3RyaW5nID0gJzBweCc7XG4gIGVtcHR5VGV4dCA9IGlucHV0KCdObyByZXN1bHRzJylcblxuICBmaWx0ZXJlZE1lbnVJdGVtczogRndNZW51SXRlbUNvbXBvbmVudFtdO1xuICBmaWx0ZXJlZE1lbnVJdGVtQ2hhbmdlID0gb3V0cHV0PEZ3TWVudUl0ZW1Db21wb25lbnRbXT4oKTtcblxuICBwcml2YXRlIGRlZmF1bHRGaWx0ZXJGbiA9IChmaWx0ZXI6IHN0cmluZywgbWVudUl0ZW1zOiBGd01lbnVJdGVtQ29tcG9uZW50W10pOiBGd01lbnVJdGVtQ29tcG9uZW50W10gPT4ge1xuICAgIHJldHVybiBtZW51SXRlbXMuZmlsdGVyKG1lbnVJdGVtID0+IG1lbnVJdGVtLnRpdGxlLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoZmlsdGVyLnRvTG93ZXJDYXNlKCkpKTtcbiAgfVxuXG4gIGZpbHRlckZuID0gaW5wdXQodGhpcy5kZWZhdWx0RmlsdGVyRm4pO1xuXG4gIGZpbHRlckNoYW5nZWQgPSBvdXRwdXQ8c3RyaW5nPigpO1xuICBAVmlld0NoaWxkKCdtZW51RmlsdGVyJykgZmlsdGVyUmVmOiBGd1RleHRJbnB1dENvbXBvbmVudDtcblxuICBAQ29udGVudENoaWxkKEZ3TWVudUNvbXBvbmVudCkgbWVudTogRndNZW51Q29tcG9uZW50O1xuXG4gIC8vIGZvciBwYXNzaW5nIG1lbnUgaXRlbXMgZm9yIHRoZSBjb250YWluZXIgdG8gZmlsdGVyXG4gIC8vIHdvcmtzIGFyb3VuZCBhIHByb2JsZW0gd2l0aCBuZXN0ZWQgY29udGVudCBjaGlsZHJlblxuICAvLyBAc2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzYyODg2NjEzL2FuZ3VsYXItOS1uZXN0ZWQtbmctY29udGVudC1hbmQtY29udGVudGNoaWxkcmVuXG4gIGFkZGl0aW9uYWxNZW51SXRlbXMgPSBpbnB1dDxGd01lbnVJdGVtQ29tcG9uZW50W10+KFtdKTtcbiAgY2hpbGRNZW51SXRlbXMgPSBjb250ZW50Q2hpbGRyZW4oRndNZW51SXRlbUNvbXBvbmVudCwgeyBkZXNjZW5kYW50czogdHJ1ZSB9KTtcbiAgcHJpdmF0ZSBjb21iaW5lZE1lbnVJdGVtcyA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICByZXR1cm4gWy4uLnRoaXMuY2hpbGRNZW51SXRlbXMoKSwgLi4udGhpcy5hZGRpdGlvbmFsTWVudUl0ZW1zKCldO1xuICB9KTtcblxuICBASW5wdXQoKSBrZXlIYW5kbGVyOiAoZXZlbnQ6IEtleWJvYXJkRXZlbnQpID0+IHZvaWQ7XG5cbiAgQEhvc3RCaW5kaW5nKCdhdHRyLmNsYXNzJykgZ2V0IGNsYXNzZXMoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gW1xuICAgICAgJ2Z3LW1lbnUtY29udGFpbmVyJyxcbiAgICAgIGB2aXNpb24tc2hhZG93LSR7dGhpcy5zaGFkb3d9YCxcbiAgICAgIGBib3JkZXItJHt0aGlzLmJvcmRlcn1gLFxuICAgIF0uam9pbignICcpO1xuICB9O1xuXG4gIEBIb3N0QmluZGluZygnc3R5bGUnKSBnZXQgc3R5bGUoKTogU2FmZVN0eWxlIHtcbiAgICByZXR1cm4gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFN0eWxlKGBcbiAgICAgIHdpZHRoOiAke3RoaXMud2lkdGh9O1xuICAgICAgbWF4LWhlaWdodDogJHt0aGlzLm1heEhlaWdodH07XG4gICAgICBtaW4taGVpZ2h0OiAke3RoaXMubWluSGVpZ2h0fTtcbiAgICAgIG1hcmdpbi10b3A6ICR7dGhpcy5vZmZzZXR9O1xuICAgIGApO1xuICB9XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplcikge31cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZm9jdXNGaWx0ZXJPbk1vdW50ICYmIHRoaXMuc2hvd0ZpbHRlcikge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEByeC1hbmd1bGFyL3ByZWZlci1uby1sYXlvdXQtc2Vuc2l0aXZlLWFwaXNcbiAgICAgIHRoaXMuZmlsdGVyUmVmPy5mb2N1cygpO1xuICAgIH1cblxuICAgIC8vIHdlIG5lZWQgdG8gcnVuIHRoZSBmaWx0ZXIgb24gaW5pdCBpbiBjYXNlIHRoZSBjdXN0b20gZmlsdGVyIGlzIGZpbHRlcmluZyB0aGluZ3NcbiAgICB0aGlzLm9uRmlsdGVyQ2hhbmdlKCcnKTtcbiAgfVxuXG4gIG5vUmVzdWx0cyA9IHNpZ25hbChmYWxzZSk7XG5cbiAgaGFuZGxlRmlsdGVyQ2xpY2soZXZlbnQ6IEV2ZW50KTogdm9pZHtcbiAgICAvLyBzdG9wcyBmaWx0ZXJzIGluIG1lbnVzIGZyb20gY2xvc2luZyB0aGUgcGFyZW50IG1lbnVcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIGhhbmRsZUZpbHRlcklucHV0KGV2ZW50OiBFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGlucHV0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XG4gICAgY29uc3QgZmlsdGVyVmFsdWUgPSBpbnB1dC52YWx1ZTtcbiAgICB0aGlzLm9uRmlsdGVyQ2hhbmdlKGZpbHRlclZhbHVlKTtcbiAgfVxuXG4gIG9uRmlsdGVyQ2hhbmdlKGZpbHRlcjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgYWxsTWVudUl0ZW1zID0gdGhpcy5jb21iaW5lZE1lbnVJdGVtcygpO1xuXG4gICAgdGhpcy5maWx0ZXJDaGFuZ2VkLmVtaXQoZmlsdGVyKTtcbiAgICBjb25zdCBmaWx0ZXJGbiA9IHRoaXMuZmlsdGVyRm4oKTtcblxuICAgIHRoaXMuZmlsdGVyZWRNZW51SXRlbXMgPSBmaWx0ZXJGbihmaWx0ZXIsIGFsbE1lbnVJdGVtcyk7XG5cbiAgICBhbGxNZW51SXRlbXMuZm9yRWFjaChtZW51SXRlbSA9PiB7XG4gICAgICBjb25zdCBzaG91bGRCZUhpZGRlbiA9ICF0aGlzLmZpbHRlcmVkTWVudUl0ZW1zLmluY2x1ZGVzKG1lbnVJdGVtKTtcbiAgICAgIG1lbnVJdGVtLmhpZGRlbiA9IHNob3VsZEJlSGlkZGVuO1xuICAgIH0pXG5cbiAgICB0aGlzLm5vUmVzdWx0cy5zZXQoYWxsTWVudUl0ZW1zLmV2ZXJ5KGl0ZW0gPT4gaXRlbS5oaWRkZW4pKTtcblxuICAgIHRoaXMuZmlsdGVyZWRNZW51SXRlbUNoYW5nZS5lbWl0KHRoaXMuZmlsdGVyZWRNZW51SXRlbXMpO1xuICB9XG59XG4iLCI8ZGl2ICNmaWx0ZXJCb3ggKm5nSWY9XCJzaG93RmlsdGVyXCIgY2xhc3M9XCJmaWx0ZXItYm94XCIgY2RrTWVudUJhcj5cbiAgPGZ3LXRleHQtaW5wdXRcbiAgICAoY2xpY2spPVwiaGFuZGxlRmlsdGVyQ2xpY2soJGV2ZW50KVwiXG4gICAgI21lbnVGaWx0ZXJcbiAgICAoa2V5ZG93bik9XCJrZXlIYW5kbGVyPy4oJGV2ZW50KVwiXG4gICAgcGxhY2Vob2xkZXI9XCJTZWFyY2hcIiBsZWZ0SWNvbj1cInNlYXJjaFwiIGF1dG9mb2N1c1xuICAgIFt2YWx1ZV09XCJmaWx0ZXJUZXh0XCIgKGlucHV0KT1cImhhbmRsZUZpbHRlcklucHV0KCRldmVudClcIj5cbiAgPC9mdy10ZXh0LWlucHV0PlxuICA8bmctY29udGVudCBzZWxlY3Q9XCIuZmlsdGVyLWNvbnRlbnRcIj48L25nLWNvbnRlbnQ+XG48L2Rpdj5cbjxkaXYgY2xhc3M9XCJtZW51LXdyYXBwZXJcIj5cbiAgPGZ3LW1lbnUtaXRlbSAqbmdJZj1cIm5vUmVzdWx0cygpXCIgW3RpdGxlXT1cImVtcHR5VGV4dCgpXCIgW2Rpc2FibGVkXT1cInRydWVcIj48L2Z3LW1lbnUtaXRlbT5cbiAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICA8bmctY29udGVudCBzZWxlY3Q9XCJjdXN0b20tbWVudS1pdGVtc1wiPjwvbmctY29udGVudD5cbjwvZGl2PlxuIl19