ngx-tethys 14.2.21 → 14.2.23

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 (61) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/avatar/avatar-list/avatar-list.component.d.ts +75 -0
  3. package/avatar/avatar.component.d.ts +57 -1
  4. package/avatar/avatar.module.d.ts +5 -4
  5. package/avatar/index.d.ts +1 -0
  6. package/avatar/styles/avatar-list.scss +36 -0
  7. package/avatar/styles/avatar.scss +2 -0
  8. package/avatar/styles/mixin.scss +10 -0
  9. package/date-picker/styles/calendar.scss +0 -2
  10. package/date-picker/styles/picker.scss +1 -1
  11. package/date-picker/styles/range-picker.scss +1 -1
  12. package/esm2020/avatar/avatar-list/avatar-list.component.mjs +175 -0
  13. package/esm2020/avatar/avatar.component.mjs +47 -3
  14. package/esm2020/avatar/avatar.module.mjs +5 -4
  15. package/esm2020/avatar/index.mjs +2 -1
  16. package/esm2020/comment/comment.component.mjs +1 -1
  17. package/esm2020/date-picker/lib/date/date-table.component.mjs +12 -3
  18. package/esm2020/date-picker/lib/popups/date-popup.component.mjs +2 -1
  19. package/esm2020/input-number/input-number.component.mjs +6 -6
  20. package/esm2020/layout/sidebar.component.mjs +18 -7
  21. package/esm2020/list/list-item-meta.component.mjs +1 -1
  22. package/esm2020/popover/header/popover-header.component.mjs +9 -5
  23. package/esm2020/version.mjs +2 -2
  24. package/fesm2015/ngx-tethys-avatar.mjs +221 -7
  25. package/fesm2015/ngx-tethys-avatar.mjs.map +1 -1
  26. package/fesm2015/ngx-tethys-comment.mjs +1 -1
  27. package/fesm2015/ngx-tethys-comment.mjs.map +1 -1
  28. package/fesm2015/ngx-tethys-date-picker.mjs +13 -2
  29. package/fesm2015/ngx-tethys-date-picker.mjs.map +1 -1
  30. package/fesm2015/ngx-tethys-input-number.mjs +5 -5
  31. package/fesm2015/ngx-tethys-input-number.mjs.map +1 -1
  32. package/fesm2015/ngx-tethys-layout.mjs +12 -1
  33. package/fesm2015/ngx-tethys-layout.mjs.map +1 -1
  34. package/fesm2015/ngx-tethys-list.mjs +1 -1
  35. package/fesm2015/ngx-tethys-list.mjs.map +1 -1
  36. package/fesm2015/ngx-tethys-popover.mjs +8 -4
  37. package/fesm2015/ngx-tethys-popover.mjs.map +1 -1
  38. package/fesm2015/ngx-tethys.mjs +1 -1
  39. package/fesm2015/ngx-tethys.mjs.map +1 -1
  40. package/fesm2020/ngx-tethys-avatar.mjs +221 -7
  41. package/fesm2020/ngx-tethys-avatar.mjs.map +1 -1
  42. package/fesm2020/ngx-tethys-comment.mjs +1 -1
  43. package/fesm2020/ngx-tethys-comment.mjs.map +1 -1
  44. package/fesm2020/ngx-tethys-date-picker.mjs +12 -2
  45. package/fesm2020/ngx-tethys-date-picker.mjs.map +1 -1
  46. package/fesm2020/ngx-tethys-input-number.mjs +5 -5
  47. package/fesm2020/ngx-tethys-input-number.mjs.map +1 -1
  48. package/fesm2020/ngx-tethys-layout.mjs +13 -2
  49. package/fesm2020/ngx-tethys-layout.mjs.map +1 -1
  50. package/fesm2020/ngx-tethys-list.mjs +1 -1
  51. package/fesm2020/ngx-tethys-list.mjs.map +1 -1
  52. package/fesm2020/ngx-tethys-popover.mjs +8 -4
  53. package/fesm2020/ngx-tethys-popover.mjs.map +1 -1
  54. package/fesm2020/ngx-tethys.mjs +1 -1
  55. package/fesm2020/ngx-tethys.mjs.map +1 -1
  56. package/layout/sidebar.component.d.ts +6 -4
  57. package/package.json +1 -1
  58. package/popover/header/popover-header.component.d.ts +6 -2
  59. package/schematics/version.d.ts +1 -1
  60. package/schematics/version.js +1 -1
  61. package/styles/variables.scss +1 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,36 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [14.2.23](https://github.com/atinc/ngx-tethys/compare/14.2.21...14.2.23) (2023-03-02)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **date-picker:** fix quick select label style justify content center #INFR-5621 ([#2557](https://github.com/atinc/ngx-tethys/issues/2557)) ([6f16b1e](https://github.com/atinc/ngx-tethys/commit/6f16b1e314d92638900148f4754373d585921b96)), closes [#INFR-5621](https://github.com/atinc/ngx-tethys/issues/INFR-5621)
11
+ * **date-picker:** same month does not appear twice in week range picker and adjust week range width #INFR-6644 ([#2554](https://github.com/atinc/ngx-tethys/issues/2554)) ([84d1cbe](https://github.com/atinc/ngx-tethys/commit/84d1cbeb945c18dda332f16ff595900232ea4871)), closes [#INFR-6644](https://github.com/atinc/ngx-tethys/issues/INFR-6644) [#INFR-6644](https://github.com/atinc/ngx-tethys/issues/INFR-6644) [#INFR-6644](https://github.com/atinc/ngx-tethys/issues/INFR-6644) [#INFR-6644](https://github.com/atinc/ngx-tethys/issues/INFR-6644) [#INFR-6644](https://github.com/atinc/ngx-tethys/issues/INFR-6644) [#INFR-6644](https://github.com/atinc/ngx-tethys/issues/INFR-6644)
12
+ * **input-number:** fix display null when thyMin or thyMax is null#INFR-6594 ([#2547](https://github.com/atinc/ngx-tethys/issues/2547)) ([3a49083](https://github.com/atinc/ngx-tethys/commit/3a490839d80fcf452beb4dffbe9e4e1c8b307ad3)), closes [null#INFR-6594](https://github.com/null/issues/INFR-6594) [null#INFR-6594](https://github.com/null/issues/INFR-6594)
13
+
14
+
15
+ ### Features
16
+
17
+ * **avatar:** add thy-avatar-list #INFR-5295 [#2525](https://github.com/atinc/ngx-tethys/issues/2525) ([#2526](https://github.com/atinc/ngx-tethys/issues/2526)) ([112eac3](https://github.com/atinc/ngx-tethys/commit/112eac3ff65a78b9a3305195d46464cf5256218e)), closes [#INFR-5295](https://github.com/atinc/ngx-tethys/issues/INFR-5295)
18
+ * **layout:** sidebar support dblclick restore to default width #INFR-6017 ([#2551](https://github.com/atinc/ngx-tethys/issues/2551)) ([06d85ad](https://github.com/atinc/ngx-tethys/commit/06d85ad1fba810837915bf8df688c91003eca8ea)), closes [#INFR-6017](https://github.com/atinc/ngx-tethys/issues/INFR-6017) [#INFR-6017](https://github.com/atinc/ngx-tethys/issues/INFR-6017)
19
+ * **popover:** support popover hader template and add test(#INFR-6586) ([#2549](https://github.com/atinc/ngx-tethys/issues/2549)) ([d5dff36](https://github.com/atinc/ngx-tethys/commit/d5dff368b8cb0f27821ae689f81671b639826ad1)), closes [#INFR-6586](https://github.com/atinc/ngx-tethys/issues/INFR-6586)
20
+ * send message and merge after pub #INFR-6280 ([9353382](https://github.com/atinc/ngx-tethys/commit/9353382acc00bec1545abb6ba7e4daf21935d10b)), closes [#INFR-6280](https://github.com/atinc/ngx-tethys/issues/INFR-6280)
21
+
22
+
23
+
24
+ ## [14.2.22](https://github.com/atinc/ngx-tethys/compare/14.2.21...14.2.22) (2023-02-27)
25
+
26
+
27
+ ### Features
28
+
29
+ * **avatar:** add thy-avatar-list #INFR-5295 [#2525](https://github.com/atinc/ngx-tethys/issues/2525) ([#2526](https://github.com/atinc/ngx-tethys/issues/2526)) ([112eac3](https://github.com/atinc/ngx-tethys/commit/112eac3ff65a78b9a3305195d46464cf5256218e)), closes [#INFR-5295](https://github.com/atinc/ngx-tethys/issues/INFR-5295)
30
+ * **popover:** support popover hader template and add test(#INFR-6586) ([#2549](https://github.com/atinc/ngx-tethys/issues/2549)) ([d5dff36](https://github.com/atinc/ngx-tethys/commit/d5dff368b8cb0f27821ae689f81671b639826ad1)), closes [#INFR-6586](https://github.com/atinc/ngx-tethys/issues/INFR-6586)
31
+ * send message and merge after pub #INFR-6280 ([9353382](https://github.com/atinc/ngx-tethys/commit/9353382acc00bec1545abb6ba7e4daf21935d10b)), closes [#INFR-6280](https://github.com/atinc/ngx-tethys/issues/INFR-6280)
32
+
33
+
34
+
5
35
  ## [14.2.21](https://github.com/atinc/ngx-tethys/compare/14.2.20...14.2.21) (2023-02-22)
6
36
 
7
37
 
@@ -0,0 +1,75 @@
1
+ import { AfterContentInit, AfterViewInit, ElementRef, EventEmitter, NgZone, OnChanges, OnDestroy, SimpleChanges, TemplateRef } from '@angular/core';
2
+ import { ThyAvatarComponent } from '../avatar.component';
3
+ import { SafeAny } from 'ngx-tethys/types';
4
+ import * as i0 from "@angular/core";
5
+ export declare const enum ThyAvatarListMode {
6
+ overlap = "overlap",
7
+ default = "default"
8
+ }
9
+ /**
10
+ * 头像列表组件
11
+ */
12
+ export declare class ThyAvatarListComponent implements OnChanges, OnDestroy, AfterContentInit, AfterViewInit {
13
+ private elementRef;
14
+ private ngZone;
15
+ overlapMode: boolean;
16
+ avatarItems: ThyAvatarComponent[];
17
+ avatarRenderItems: ThyAvatarComponent[];
18
+ avatarSpace: number;
19
+ avatarOverlapSpace: number;
20
+ get more(): number;
21
+ private ngUnsubscribe$;
22
+ private avatarList;
23
+ /**
24
+ * 展示方式
25
+ * @type 'overlap'| 'default'
26
+ * @default default
27
+ */
28
+ set thyMode(value: ThyAvatarListMode);
29
+ /**
30
+ * 响应式,自动计算宽度存放 avatar
31
+ * @default false
32
+ */
33
+ thyResponsive: boolean;
34
+ /**
35
+ * 列表组件允许展示 avatar 最大数量
36
+ */
37
+ thyMax: number;
38
+ /**
39
+ * 头像大小
40
+ * @type 22 | 24 | 28 | 32 | 36 | 44 | 48 | 68 | 110 | 160 | xxs(22px) | xs(24px) | sm(32px) | md(36px) | lg(48px)
41
+ * @default 36
42
+ */
43
+ thyAvatarSize: number | string;
44
+ /**
45
+ * 是否展示移除按钮
46
+ * @type boolean
47
+ * @default false
48
+ */
49
+ thyRemovable: boolean;
50
+ /**
51
+ * avatar 移除按钮事件
52
+ */
53
+ thyRemove: EventEmitter<string>;
54
+ /**
55
+ * append 自定义操作
56
+ */
57
+ append: TemplateRef<SafeAny>;
58
+ /**
59
+ * @private
60
+ */
61
+ private set avatarComponents(value);
62
+ appendContent: ElementRef<HTMLInputElement>;
63
+ constructor(elementRef: ElementRef, ngZone: NgZone);
64
+ ngOnChanges(changes: SimpleChanges): void;
65
+ ngAfterContentInit(): void;
66
+ ngAfterViewInit(): void;
67
+ private setAvatarSize;
68
+ remove(name: string): void;
69
+ private getRenderAvatar;
70
+ private getEndIndex;
71
+ private createResizeObserver;
72
+ ngOnDestroy(): void;
73
+ static ɵfac: i0.ɵɵFactoryDeclaration<ThyAvatarListComponent, never>;
74
+ static ɵcmp: i0.ɵɵComponentDeclaration<ThyAvatarListComponent, "thy-avatar-list", never, { "thyMode": "thyMode"; "thyResponsive": "thyResponsive"; "thyMax": "thyMax"; "thyAvatarSize": "thyAvatarSize"; "thyRemovable": "thyRemovable"; }, { "thyRemove": "thyRemove"; }, ["append", "avatarComponents"], ["*"], false>;
75
+ }
@@ -2,6 +2,7 @@ import { EventEmitter, OnInit } from '@angular/core';
2
2
  import { SafeHtml } from '@angular/platform-browser';
3
3
  import { ThyAvatarService } from './avatar.service';
4
4
  import * as i0 from "@angular/core";
5
+ export declare const DEFAULT_SIZE = 36;
5
6
  export declare const thyAvatarSizeMap: {
6
7
  xxs: number;
7
8
  xs: number;
@@ -13,6 +14,9 @@ export declare const thyAvatarSizeMap: {
13
14
  export declare type ThyAvatarLoading = 'eager' | 'lazy';
14
15
  /** https://wicg.github.io/priority-hints/#idl-index */
15
16
  export declare type ThyAvatarFetchPriority = 'high' | 'low' | 'auto';
17
+ /**
18
+ * 头像组件
19
+ */
16
20
  export declare class ThyAvatarComponent implements OnInit {
17
21
  private thyAvatarService;
18
22
  _src: string;
@@ -23,16 +27,68 @@ export declare class ThyAvatarComponent implements OnInit {
23
27
  avatarName?: string;
24
28
  avatarNameSafeHtml?: SafeHtml;
25
29
  _isAvatar: boolean;
30
+ /**
31
+ * * 已废弃,请使用 thyRemove
32
+ * @deprecated
33
+ */
26
34
  thyOnRemove: EventEmitter<any>;
35
+ /**
36
+ * 移除按钮的事件, 当 thyRemovable 为 true 时起作用
37
+ */
38
+ thyRemove: EventEmitter<any>;
39
+ /**
40
+ * 头像 img 加载 error 时触发
41
+ */
27
42
  thyError: EventEmitter<Event>;
43
+ /**
44
+ * 是否展示人员名称
45
+ * @default false
46
+ */
28
47
  thyShowName: boolean;
48
+ /**
49
+ * 头像路径地址, 默认为全路径,如果不是全路径,可以通过自定义服务 ThyAvatarService,重写 srcTransform 方法实现转换
50
+ *
51
+ */
29
52
  set thySrc(value: string);
53
+ /**
54
+ * 人员名称(可设置自定义名称,需通过自定义服务 ThyAvatarService,重写 nameTransform 方法去实现转换)
55
+ */
30
56
  set thyName(value: string);
57
+ /**
58
+ * 头像大小
59
+ * @type 16 | 22 | 24 | 28 | 32 | 36 | 44 | 48 | 68 | 110 | 160 | xxs(22px) | xs(24px) | sm(32px) | md(36px) | lg(48px)
60
+ * @default md
61
+ */
31
62
  set thySize(value: number | string);
63
+ /**
64
+ * 已废弃,请使用 thyRemovable
65
+ * @deprecated
66
+ * @default false
67
+ */
32
68
  set thyShowRemove(value: boolean);
69
+ /**
70
+ * 是否展示移除按钮
71
+ * @default false
72
+ */
73
+ set thyRemovable(value: boolean);
74
+ /**
75
+ * 图片自定义类
76
+ */
33
77
  thyImgClass: string;
78
+ /**
79
+ * 禁用
80
+ * @default false
81
+ */
34
82
  thyDisabled: boolean;
83
+ /**
84
+ * 图片加载策略
85
+ * @type eager(立即加载) | lazy(延迟加载)
86
+ */
35
87
  thyLoading?: ThyAvatarLoading;
88
+ /**
89
+ * 图片加载优先级
90
+ * @type auto(默认) | high(高) | low(低)
91
+ */
36
92
  thyFetchPriority?: ThyAvatarFetchPriority;
37
93
  private _setAvatarSize;
38
94
  private findClosestSize;
@@ -44,5 +100,5 @@ export declare class ThyAvatarComponent implements OnInit {
44
100
  remove($event: Event): void;
45
101
  avatarImgError($event: Event): void;
46
102
  static ɵfac: i0.ɵɵFactoryDeclaration<ThyAvatarComponent, never>;
47
- static ɵcmp: i0.ɵɵComponentDeclaration<ThyAvatarComponent, "thy-avatar", never, { "thyShowName": "thyShowName"; "thySrc": "thySrc"; "thyName": "thyName"; "thySize": "thySize"; "thyShowRemove": "thyShowRemove"; "thyImgClass": "thyImgClass"; "thyDisabled": "thyDisabled"; "thyLoading": "thyLoading"; "thyFetchPriority": "thyFetchPriority"; }, { "thyOnRemove": "thyOnRemove"; "thyError": "thyError"; }, never, never, false>;
103
+ static ɵcmp: i0.ɵɵComponentDeclaration<ThyAvatarComponent, "thy-avatar", never, { "thyShowName": "thyShowName"; "thySrc": "thySrc"; "thyName": "thyName"; "thySize": "thySize"; "thyShowRemove": "thyShowRemove"; "thyRemovable": "thyRemovable"; "thyImgClass": "thyImgClass"; "thyDisabled": "thyDisabled"; "thyLoading": "thyLoading"; "thyFetchPriority": "thyFetchPriority"; }, { "thyOnRemove": "thyOnRemove"; "thyRemove": "thyRemove"; "thyError": "thyError"; }, never, never, false>;
48
104
  }
@@ -1,10 +1,11 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import * as i1 from "./avatar.component";
3
- import * as i2 from "./avatar.pipe";
4
- import * as i3 from "@angular/common";
5
- import * as i4 from "ngx-tethys/icon";
3
+ import * as i2 from "./avatar-list/avatar-list.component";
4
+ import * as i3 from "./avatar.pipe";
5
+ import * as i4 from "@angular/common";
6
+ import * as i5 from "ngx-tethys/icon";
6
7
  export declare class ThyAvatarModule {
7
8
  static ɵfac: i0.ɵɵFactoryDeclaration<ThyAvatarModule, never>;
8
- static ɵmod: i0.ɵɵNgModuleDeclaration<ThyAvatarModule, [typeof i1.ThyAvatarComponent, typeof i2.AvatarShortNamePipe, typeof i2.AvatarBgColorPipe, typeof i2.AvatarSrcPipe], [typeof i3.CommonModule, typeof i4.ThyIconModule], [typeof i1.ThyAvatarComponent, typeof i2.AvatarShortNamePipe, typeof i2.AvatarBgColorPipe, typeof i2.AvatarSrcPipe]>;
9
+ static ɵmod: i0.ɵɵNgModuleDeclaration<ThyAvatarModule, [typeof i1.ThyAvatarComponent, typeof i2.ThyAvatarListComponent, typeof i3.AvatarShortNamePipe, typeof i3.AvatarBgColorPipe, typeof i3.AvatarSrcPipe], [typeof i4.CommonModule, typeof i5.ThyIconModule], [typeof i1.ThyAvatarComponent, typeof i2.ThyAvatarListComponent, typeof i3.AvatarShortNamePipe, typeof i3.AvatarBgColorPipe, typeof i3.AvatarSrcPipe]>;
9
10
  static ɵinj: i0.ɵɵInjectorDeclaration<ThyAvatarModule>;
10
11
  }
package/avatar/index.d.ts CHANGED
@@ -2,3 +2,4 @@ export * from './avatar.module';
2
2
  export * from './avatar.service';
3
3
  export * from './avatar.pipe';
4
4
  export * from './avatar.component';
5
+ export * from './avatar-list/avatar-list.component';
@@ -0,0 +1,36 @@
1
+ @use "../../styles/variables";
2
+ @use "mixin";
3
+
4
+ .thy-avatar-list {
5
+ display: inline-flex;
6
+ flex: 1;
7
+ line-height: initial;
8
+ width: 100%;
9
+
10
+ .thy-avatar-content {
11
+ position: relative;
12
+ }
13
+ }
14
+
15
+ .thy-avatar-list-overlap {
16
+ @each $size, $value in variables.$avatar-sizes {
17
+ .thy-avatar-#{$size} {
18
+ @include mixin.avatarSize($size, $value);
19
+
20
+ .avatar-default {
21
+ border: 1px solid variables.$white;
22
+ }
23
+ }
24
+ }
25
+ }
26
+
27
+ @each $size, $value in variables.$avatar-sizes {
28
+ .more-#{$size} {
29
+ @include mixin.avatarMoreSize($size, $value);
30
+ background-color: rgba(variables.$black, 0.3);
31
+ color: variables.$white;
32
+ position: absolute;
33
+ left: 0;
34
+ top: 0;
35
+ }
36
+ }
@@ -1,5 +1,7 @@
1
+ @use "sass:meta";
1
2
  @use "../../styles/variables";
2
3
  @use "mixin";
4
+ @use './avatar-list.scss';
3
5
 
4
6
  .thy-avatar {
5
7
  display: inline-block;
@@ -22,3 +22,13 @@
22
22
  }
23
23
  }
24
24
  }
25
+
26
+ @mixin avatarMoreSize($size, $font-size: 12px) {
27
+ width: #{$size}px;
28
+ height: #{$size}px;
29
+ border-radius: 50%;
30
+ line-height: #{$size}px;
31
+ font-size: #{$font-size}px;
32
+ text-align: center;
33
+ display: inline-block;
34
+ }
@@ -26,8 +26,6 @@
26
26
  }
27
27
 
28
28
  &-week-number {
29
- width: 286px;
30
-
31
29
  &-cell {
32
30
  text-align: center;
33
31
  }
@@ -41,7 +41,7 @@
41
41
  &-item {
42
42
  width: 84px;
43
43
  height: 28px;
44
- line-height: 28px;
44
+ line-height: 26px;
45
45
  display: inline-block;
46
46
  text-align: center;
47
47
  border: 1px solid variables.$gray-200;
@@ -135,7 +135,7 @@ $input-box-height: 34px;
135
135
  width:100%;
136
136
 
137
137
  .#{style.$calendar-prefix-cls}-range-part {
138
- width: 286px;
138
+ width: 50%;
139
139
  }
140
140
  }
141
141
 
@@ -0,0 +1,175 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { Component, ContentChild, ContentChildren, ElementRef, EventEmitter, HostBinding, Input, NgZone, Output, QueryList, TemplateRef, ViewChild } from '@angular/core';
3
+ import { InputBoolean, UpdateHostClassService } from 'ngx-tethys/core';
4
+ import { merge, Observable, of, Subject } from 'rxjs';
5
+ import { debounceTime, take, takeUntil } from 'rxjs/operators';
6
+ import { DEFAULT_SIZE, ThyAvatarComponent } from '../avatar.component';
7
+ import * as i0 from "@angular/core";
8
+ import * as i1 from "@angular/common";
9
+ import * as i2 from "../avatar.component";
10
+ const AVATAR_ITEM_SPACE = 6;
11
+ const OVERLAP_AVATAR_ITEM_SPACE = -8;
12
+ /**
13
+ * 头像列表组件
14
+ */
15
+ export class ThyAvatarListComponent {
16
+ constructor(elementRef, ngZone) {
17
+ this.elementRef = elementRef;
18
+ this.ngZone = ngZone;
19
+ this.overlapMode = false;
20
+ this.avatarItems = [];
21
+ this.avatarRenderItems = [];
22
+ this.avatarSpace = AVATAR_ITEM_SPACE;
23
+ this.avatarOverlapSpace = OVERLAP_AVATAR_ITEM_SPACE;
24
+ this.ngUnsubscribe$ = new Subject();
25
+ /**
26
+ * 响应式,自动计算宽度存放 avatar
27
+ * @default false
28
+ */
29
+ this.thyResponsive = false;
30
+ /**
31
+ * 头像大小
32
+ * @type 22 | 24 | 28 | 32 | 36 | 44 | 48 | 68 | 110 | 160 | xxs(22px) | xs(24px) | sm(32px) | md(36px) | lg(48px)
33
+ * @default 36
34
+ */
35
+ this.thyAvatarSize = DEFAULT_SIZE;
36
+ /**
37
+ * 是否展示移除按钮
38
+ * @type boolean
39
+ * @default false
40
+ */
41
+ this.thyRemovable = false;
42
+ /**
43
+ * avatar 移除按钮事件
44
+ */
45
+ this.thyRemove = new EventEmitter();
46
+ }
47
+ get more() {
48
+ return this.avatarItems.length - this.avatarRenderItems.length;
49
+ }
50
+ /**
51
+ * 展示方式
52
+ * @type 'overlap'| 'default'
53
+ * @default default
54
+ */
55
+ set thyMode(value) {
56
+ this.overlapMode = value === "overlap" /* ThyAvatarListMode.overlap */;
57
+ }
58
+ /**
59
+ * @private
60
+ */
61
+ set avatarComponents(value) {
62
+ this.avatarItems = value.toArray();
63
+ this.avatarList = value;
64
+ }
65
+ ngOnChanges(changes) {
66
+ if (changes.thyAvatarSize && !changes.thyAvatarSize.firstChange) {
67
+ this.setAvatarSize();
68
+ }
69
+ if (changes.thyMax && !changes.thyMax.firstChange) {
70
+ this.getRenderAvatar();
71
+ }
72
+ }
73
+ ngAfterContentInit() {
74
+ this.setAvatarSize();
75
+ }
76
+ ngAfterViewInit() {
77
+ this.ngZone.onStable.pipe(take(1)).subscribe(() => {
78
+ this.getRenderAvatar();
79
+ });
80
+ if (this.thyResponsive) {
81
+ this.ngZone.runOutsideAngular(() => {
82
+ merge(this.avatarList.changes, this.createResizeObserver(this.elementRef.nativeElement))
83
+ .pipe(debounceTime(100), takeUntil(this.ngUnsubscribe$))
84
+ .subscribe(() => {
85
+ this.getRenderAvatar();
86
+ });
87
+ });
88
+ }
89
+ }
90
+ setAvatarSize() {
91
+ this.avatarItems.forEach((avatar) => {
92
+ avatar.thySize = this.thyAvatarSize;
93
+ });
94
+ this.getRenderAvatar();
95
+ }
96
+ remove(name) {
97
+ this.thyRemove.emit(name);
98
+ }
99
+ getRenderAvatar() {
100
+ const endIndex = this.getEndIndex();
101
+ const max = this.thyMax || this.avatarItems.length;
102
+ const showCount = Math.max(0, Math.min(max, endIndex));
103
+ this.avatarRenderItems = this.avatarItems.slice(0, showCount);
104
+ }
105
+ getEndIndex() {
106
+ if (this.avatarItems.length) {
107
+ const space = this.overlapMode ? this.avatarOverlapSpace : this.avatarSpace;
108
+ const avatarWidth = this.avatarItems[0]._size + space;
109
+ const wrapperWidth = this.elementRef.nativeElement.offsetWidth;
110
+ const appendWidth = this.appendContent ? this.appendContent.nativeElement.offsetWidth : 0;
111
+ const lastAvatarSpecialSpace = this.overlapMode ? space : 0; // overlap 模式下最后一个 avatar 元素占位比其他多 this.avatarSpace 个 px
112
+ return Math.floor((wrapperWidth - appendWidth + lastAvatarSpecialSpace) / avatarWidth);
113
+ }
114
+ else {
115
+ return 0;
116
+ }
117
+ }
118
+ createResizeObserver(element) {
119
+ return typeof ResizeObserver === 'undefined'
120
+ ? of(null)
121
+ : new Observable(observer => {
122
+ const resize = new ResizeObserver(entries => {
123
+ this.ngZone.run(() => {
124
+ observer.next(entries);
125
+ });
126
+ });
127
+ resize.observe(element);
128
+ return () => {
129
+ resize.disconnect();
130
+ };
131
+ });
132
+ }
133
+ ngOnDestroy() {
134
+ this.ngUnsubscribe$.next();
135
+ this.ngUnsubscribe$.complete();
136
+ }
137
+ }
138
+ ThyAvatarListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.0", ngImport: i0, type: ThyAvatarListComponent, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
139
+ ThyAvatarListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.0", type: ThyAvatarListComponent, selector: "thy-avatar-list", inputs: { thyMode: "thyMode", thyResponsive: "thyResponsive", thyMax: "thyMax", thyAvatarSize: "thyAvatarSize", thyRemovable: "thyRemovable" }, outputs: { thyRemove: "thyRemove" }, host: { properties: { "style.margin-left.px": "overlapMode ? -avatarOverlapSpace : 0", "class.thy-avatar-list-overlap": "this.overlapMode" }, classAttribute: "thy-avatar-list" }, providers: [UpdateHostClassService], queries: [{ propertyName: "append", first: true, predicate: ["append"], descendants: true }, { propertyName: "avatarComponents", predicate: ThyAvatarComponent }], viewQueries: [{ propertyName: "appendContent", first: true, predicate: ["appendContent"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-template>\n <ng-content></ng-content>\n</ng-template>\n\n<ng-container *ngFor=\"let avatar of avatarRenderItems; index as index; last as isLast\">\n <div\n class=\"thy-avatar-content\"\n [ngStyle]=\"overlapMode ? { 'margin-left.px': avatarOverlapSpace } : { 'margin-right.px': isLast ? 0 : avatarSpace }\"\n >\n <thy-avatar\n [thySrc]=\"avatar._src\"\n [thyName]=\"avatar.avatarName\"\n [thySize]=\"avatar._size\"\n [thyRemovable]=\"overlapMode ? false : thyRemovable\"\n [thyImgClass]=\"avatar.thyImgClass\"\n [thyDisabled]=\"avatar.thyDisabled\"\n [thyLoading]=\"avatar.thyLoading\"\n [thyFetchPriority]=\"avatar.thyFetchPriority\"\n (thyRemove)=\"remove(avatar.avatarName)\"\n ></thy-avatar>\n <span *ngIf=\"isLast && more && thyResponsive\" ngClass=\"more-{{ avatar._size }}\">+{{ more }} </span>\n </div>\n</ng-container>\n\n<div #appendContent *ngIf=\"append\" [ngStyle]=\"{ 'padding-left.px': avatarSpace }\">\n <ng-container [ngTemplateOutlet]=\"append\"></ng-container>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.ThyAvatarComponent, selector: "thy-avatar", inputs: ["thyShowName", "thySrc", "thyName", "thySize", "thyShowRemove", "thyRemovable", "thyImgClass", "thyDisabled", "thyLoading", "thyFetchPriority"], outputs: ["thyOnRemove", "thyRemove", "thyError"] }] });
140
+ __decorate([
141
+ InputBoolean(),
142
+ __metadata("design:type", Object)
143
+ ], ThyAvatarListComponent.prototype, "thyResponsive", void 0);
144
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.0", ngImport: i0, type: ThyAvatarListComponent, decorators: [{
145
+ type: Component,
146
+ args: [{ selector: 'thy-avatar-list', host: {
147
+ class: 'thy-avatar-list',
148
+ '[style.margin-left.px]': 'overlapMode ? -avatarOverlapSpace : 0'
149
+ }, providers: [UpdateHostClassService], template: "<ng-template>\n <ng-content></ng-content>\n</ng-template>\n\n<ng-container *ngFor=\"let avatar of avatarRenderItems; index as index; last as isLast\">\n <div\n class=\"thy-avatar-content\"\n [ngStyle]=\"overlapMode ? { 'margin-left.px': avatarOverlapSpace } : { 'margin-right.px': isLast ? 0 : avatarSpace }\"\n >\n <thy-avatar\n [thySrc]=\"avatar._src\"\n [thyName]=\"avatar.avatarName\"\n [thySize]=\"avatar._size\"\n [thyRemovable]=\"overlapMode ? false : thyRemovable\"\n [thyImgClass]=\"avatar.thyImgClass\"\n [thyDisabled]=\"avatar.thyDisabled\"\n [thyLoading]=\"avatar.thyLoading\"\n [thyFetchPriority]=\"avatar.thyFetchPriority\"\n (thyRemove)=\"remove(avatar.avatarName)\"\n ></thy-avatar>\n <span *ngIf=\"isLast && more && thyResponsive\" ngClass=\"more-{{ avatar._size }}\">+{{ more }} </span>\n </div>\n</ng-container>\n\n<div #appendContent *ngIf=\"append\" [ngStyle]=\"{ 'padding-left.px': avatarSpace }\">\n <ng-container [ngTemplateOutlet]=\"append\"></ng-container>\n</div>\n" }]
150
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }]; }, propDecorators: { overlapMode: [{
151
+ type: HostBinding,
152
+ args: ['class.thy-avatar-list-overlap']
153
+ }], thyMode: [{
154
+ type: Input
155
+ }], thyResponsive: [{
156
+ type: Input
157
+ }], thyMax: [{
158
+ type: Input
159
+ }], thyAvatarSize: [{
160
+ type: Input
161
+ }], thyRemovable: [{
162
+ type: Input
163
+ }], thyRemove: [{
164
+ type: Output
165
+ }], append: [{
166
+ type: ContentChild,
167
+ args: ['append', { static: false }]
168
+ }], avatarComponents: [{
169
+ type: ContentChildren,
170
+ args: [ThyAvatarComponent]
171
+ }], appendContent: [{
172
+ type: ViewChild,
173
+ args: ['appendContent']
174
+ }] } });
175
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXZhdGFyLWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2F2YXRhci9hdmF0YXItbGlzdC9hdmF0YXItbGlzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9zcmMvYXZhdGFyL2F2YXRhci1saXN0L2F2YXRhci1saXN0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBR0gsU0FBUyxFQUNULFlBQVksRUFDWixlQUFlLEVBQ2YsVUFBVSxFQUNWLFlBQVksRUFDWixXQUFXLEVBQ1gsS0FBSyxFQUNMLE1BQU0sRUFHTixNQUFNLEVBQ04sU0FBUyxFQUVULFdBQVcsRUFDWCxTQUFTLEVBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEQsT0FBTyxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDL0QsT0FBTyxFQUFFLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDOzs7O0FBR3ZFLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0FBRTVCLE1BQU0seUJBQXlCLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFNckM7O0dBRUc7QUFVSCxNQUFNLE9BQU8sc0JBQXNCO0lBNkUvQixZQUFvQixVQUFzQixFQUFVLE1BQWM7UUFBOUMsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUFVLFdBQU0sR0FBTixNQUFNLENBQVE7UUE1RXBCLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBRTNELGdCQUFXLEdBQXlCLEVBQUUsQ0FBQztRQUV2QyxzQkFBaUIsR0FBeUIsRUFBRSxDQUFDO1FB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QkFLb0MsTUFBTTtzQkFBaEQsWUFBWTt1QkFBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQU03QixnQkFBZ0I7c0JBRDNCLGVBQWU7dUJBQUMsa0JBQWtCO2dCQU1QLGFBQWE7c0JBQXhDLFNBQVM7dUJBQUMsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgQWZ0ZXJDb250ZW50SW5pdCxcbiAgICBBZnRlclZpZXdJbml0LFxuICAgIENvbXBvbmVudCxcbiAgICBDb250ZW50Q2hpbGQsXG4gICAgQ29udGVudENoaWxkcmVuLFxuICAgIEVsZW1lbnRSZWYsXG4gICAgRXZlbnRFbWl0dGVyLFxuICAgIEhvc3RCaW5kaW5nLFxuICAgIElucHV0LFxuICAgIE5nWm9uZSxcbiAgICBPbkNoYW5nZXMsXG4gICAgT25EZXN0cm95LFxuICAgIE91dHB1dCxcbiAgICBRdWVyeUxpc3QsXG4gICAgU2ltcGxlQ2hhbmdlcyxcbiAgICBUZW1wbGF0ZVJlZixcbiAgICBWaWV3Q2hpbGRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBJbnB1dEJvb2xlYW4sIFVwZGF0ZUhvc3RDbGFzc1NlcnZpY2UgfSBmcm9tICduZ3gtdGV0aHlzL2NvcmUnO1xuaW1wb3J0IHsgbWVyZ2UsIE9ic2VydmFibGUsIG9mLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUsIHRha2UsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IERFRkFVTFRfU0laRSwgVGh5QXZhdGFyQ29tcG9uZW50IH0gZnJvbSAnLi4vYXZhdGFyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTYWZlQW55IH0gZnJvbSAnbmd4LXRldGh5cy90eXBlcyc7XG5cbmNvbnN0IEFWQVRBUl9JVEVNX1NQQUNFID0gNjtcblxuY29uc3QgT1ZFUkxBUF9BVkFUQVJfSVRFTV9TUEFDRSA9IC04O1xuXG5leHBvcnQgY29uc3QgZW51bSBUaHlBdmF0YXJMaXN0TW9kZSB7XG4gICAgb3ZlcmxhcCA9ICdvdmVybGFwJyxcbiAgICBkZWZhdWx0ID0gJ2RlZmF1bHQnXG59XG4vKipcbiAqIOWktOWDj+WIl+ihqOe7hOS7tlxuICovXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3RoeS1hdmF0YXItbGlzdCcsXG4gICAgdGVtcGxhdGVVcmw6IGAuL2F2YXRhci1saXN0LmNvbXBvbmVudC5odG1sYCxcbiAgICBob3N0OiB7XG4gICAgICAgIGNsYXNzOiAndGh5LWF2YXRhci1saXN0JyxcbiAgICAgICAgJ1tzdHlsZS5tYXJnaW4tbGVmdC5weF0nOiAnb3ZlcmxhcE1vZGUgPyAtYXZhdGFyT3ZlcmxhcFNwYWNlIDogMCdcbiAgICB9LFxuICAgIHByb3ZpZGVyczogW1VwZGF0ZUhvc3RDbGFzc1NlcnZpY2VdXG59KVxuZXhwb3J0IGNsYXNzIFRoeUF2YXRhckxpc3RDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIE9uRGVzdHJveSwgQWZ0ZXJDb250ZW50SW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy50aHktYXZhdGFyLWxpc3Qtb3ZlcmxhcCcpIG92ZXJsYXBNb2RlID0gZmFsc2U7XG5cbiAgICBwdWJsaWMgYXZhdGFySXRlbXM6IFRoeUF2YXRhckNvbXBvbmVudFtdID0gW107XG5cbiAgICBwdWJsaWMgYXZhdGFyUmVuZGVySXRlbXM6IFRoeUF2YXRhckNvbXBvbmVudFtdID0gW107XG5cbiAgICBwdWJsaWMgYXZhdGFyU3BhY2UgPSBBVkFUQVJfSVRFTV9TUEFDRTtcblxuICAgIHB1YmxpYyBhdmF0YXJPdmVybGFwU3BhY2UgPSBPVkVSTEFQX0FWQVRBUl9JVEVNX1NQQUNFO1xuXG4gICAgcHVibGljIGdldCBtb3JlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5hdmF0YXJJdGVtcy5sZW5ndGggLSB0aGlzLmF2YXRhclJlbmRlckl0ZW1zLmxlbmd0aDtcbiAgICB9XG5cbiAgICBwcml2YXRlIG5nVW5zdWJzY3JpYmUkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIHByaXZhdGUgYXZhdGFyTGlzdDogUXVlcnlMaXN0PFRoeUF2YXRhckNvbXBvbmVudD47XG5cbiAgICAvKipcbiAgICAgKiDlsZXnpLrmlrnlvI9cbiAgICAgKiBAdHlwZSAgJ292ZXJsYXAnfCAnZGVmYXVsdCdcbiAgICAgKiBAZGVmYXVsdCBkZWZhdWx0XG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBzZXQgdGh5TW9kZSh2YWx1ZTogVGh5QXZhdGFyTGlzdE1vZGUpIHtcbiAgICAgICAgdGhpcy5vdmVybGFwTW9kZSA9IHZhbHVlID09PSBUaHlBdmF0YXJMaXN0TW9kZS5vdmVybGFwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIOWTjeW6lOW8j++8jOiHquWKqOiuoeeul+WuveW6puWtmOaUviBhdmF0YXJcbiAgICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgQElucHV0Qm9vbGVhbigpXG4gICAgdGh5UmVzcG9uc2l2ZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICog5YiX6KGo57uE5Lu25YWB6K645bGV56S6IGF2YXRhciDmnIDlpKfmlbDph49cbiAgICAgKi9cbiAgICBASW5wdXQoKSB0aHlNYXg6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIOWktOWDj+Wkp+Wwj1xuICAgICAqIEB0eXBlIDIyIHwgMjQgfCAyOCB8IDMyIHwgMzYgfCA0NCB8IDQ4IHwgNjggfCAxMTAgfCAxNjAgfCB4eHMoMjJweCkgfCB4cygyNHB4KSB8IHNtKDMycHgpIHwgbWQoMzZweCkgfCBsZyg0OHB4KVxuICAgICAqIEBkZWZhdWx0IDM2XG4gICAgICovXG4gICAgQElucHV0KCkgdGh5QXZhdGFyU2l6ZTogbnVtYmVyIHwgc3RyaW5nID0gREVGQVVMVF9TSVpFO1xuXG4gICAgLyoqXG4gICAgICog5piv5ZCm5bGV56S656e76Zmk5oyJ6ZKuXG4gICAgICogQHR5cGUgYm9vbGVhblxuICAgICAqIEBkZWZhdWx0IGZhbHNlXG4gICAgICovXG4gICAgQElucHV0KCkgdGh5UmVtb3ZhYmxlID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBhdmF0YXIg56e76Zmk5oyJ6ZKu5LqL5Lu2XG4gICAgICovXG4gICAgQE91dHB1dCgpIHRoeVJlbW92ZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gICAgLyoqXG4gICAgICogIGFwcGVuZCDoh6rlrprkuYnmk43kvZxcbiAgICAgKi9cbiAgICBAQ29udGVudENoaWxkKCdhcHBlbmQnLCB7IHN0YXRpYzogZmFsc2UgfSkgYXBwZW5kOiBUZW1wbGF0ZVJlZjxTYWZlQW55PjtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgQENvbnRlbnRDaGlsZHJlbihUaHlBdmF0YXJDb21wb25lbnQpXG4gICAgcHJpdmF0ZSBzZXQgYXZhdGFyQ29tcG9uZW50cyh2YWx1ZTogUXVlcnlMaXN0PFRoeUF2YXRhckNvbXBvbmVudD4pIHtcbiAgICAgICAgdGhpcy5hdmF0YXJJdGVtcyA9IHZhbHVlLnRvQXJyYXkoKTtcbiAgICAgICAgdGhpcy5hdmF0YXJMaXN0ID0gdmFsdWU7XG4gICAgfVxuXG4gICAgQFZpZXdDaGlsZCgnYXBwZW5kQ29udGVudCcpIGFwcGVuZENvbnRlbnQ6IEVsZW1lbnRSZWY8SFRNTElucHV0RWxlbWVudD47XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsIHByaXZhdGUgbmdab25lOiBOZ1pvbmUpIHt9XG5cbiAgICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgICAgIGlmIChjaGFuZ2VzLnRoeUF2YXRhclNpemUgJiYgIWNoYW5nZXMudGh5QXZhdGFyU2l6ZS5maXJzdENoYW5nZSkge1xuICAgICAgICAgICAgdGhpcy5zZXRBdmF0YXJTaXplKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2hhbmdlcy50aHlNYXggJiYgIWNoYW5nZXMudGh5TWF4LmZpcnN0Q2hhbmdlKSB7XG4gICAgICAgICAgICB0aGlzLmdldFJlbmRlckF2YXRhcigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgICAgICB0aGlzLnNldEF2YXRhclNpemUoKTtcbiAgICB9XG5cbiAgICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgICAgIHRoaXMubmdab25lLm9uU3RhYmxlLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZ2V0UmVuZGVyQXZhdGFyKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0aGlzLnRoeVJlc3BvbnNpdmUpIHtcbiAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgICAgICAgICBtZXJnZSh0aGlzLmF2YXRhckxpc3QuY2hhbmdlcywgdGhpcy5jcmVhdGVSZXNpemVPYnNlcnZlcih0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCkpXG4gICAgICAgICAgICAgICAgICAgIC5waXBlKGRlYm91bmNlVGltZSgxMDApLCB0YWtlVW50aWwodGhpcy5uZ1Vuc3Vic2NyaWJlJCkpXG4gICAgICAgICAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRSZW5kZXJBdmF0YXIoKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc2V0QXZhdGFyU2l6ZSgpIHtcbiAgICAgICAgdGhpcy5hdmF0YXJJdGVtcy5mb3JFYWNoKChhdmF0YXI6IFRoeUF2YXRhckNvbXBvbmVudCkgPT4ge1xuICAgICAgICAgICAgYXZhdGFyLnRoeVNpemUgPSB0aGlzLnRoeUF2YXRhclNpemU7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmdldFJlbmRlckF2YXRhcigpO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW1vdmUobmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMudGh5UmVtb3ZlLmVtaXQobmFtZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZW5kZXJBdmF0YXIoKSB7XG4gICAgICAgIGNvbnN0IGVuZEluZGV4ID0gdGhpcy5nZXRFbmRJbmRleCgpO1xuICAgICAgICBjb25zdCBtYXggPSB0aGlzLnRoeU1heCB8fCB0aGlzLmF2YXRhckl0ZW1zLmxlbmd0aDtcbiAgICAgICAgY29uc3Qgc2hvd0NvdW50ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obWF4LCBlbmRJbmRleCkpO1xuICAgICAgICB0aGlzLmF2YXRhclJlbmRlckl0ZW1zID0gdGhpcy5hdmF0YXJJdGVtcy5zbGljZSgwLCBzaG93Q291bnQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0RW5kSW5kZXgoKSB7XG4gICAgICAgIGlmICh0aGlzLmF2YXRhckl0ZW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3Qgc3BhY2UgPSB0aGlzLm92ZXJsYXBNb2RlID8gdGhpcy5hdmF0YXJPdmVybGFwU3BhY2UgOiB0aGlzLmF2YXRhclNwYWNlO1xuICAgICAgICAgICAgY29uc3QgYXZhdGFyV2lkdGggPSB0aGlzLmF2YXRhckl0ZW1zWzBdLl9zaXplICsgc3BhY2U7XG4gICAgICAgICAgICBjb25zdCB3cmFwcGVyV2lkdGggPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgICAgICAgIGNvbnN0IGFwcGVuZFdpZHRoID0gdGhpcy5hcHBlbmRDb250ZW50ID8gdGhpcy5hcHBlbmRDb250ZW50Lm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGggOiAwO1xuICAgICAgICAgICAgY29uc3QgbGFzdEF2YXRhclNwZWNpYWxTcGFjZSA9IHRoaXMub3ZlcmxhcE1vZGUgPyBzcGFjZSA6IDA7IC8vIG92ZXJsYXAg5qih5byP5LiL5pyA5ZCO5LiA5LiqIGF2YXRhciDlhYPntKDljaDkvY3mr5Tlhbbku5blpJogdGhpcy5hdmF0YXJTcGFjZSDkuKogcHhcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKCh3cmFwcGVyV2lkdGggLSBhcHBlbmRXaWR0aCArIGxhc3RBdmF0YXJTcGVjaWFsU3BhY2UpIC8gYXZhdGFyV2lkdGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNyZWF0ZVJlc2l6ZU9ic2VydmVyKGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgUmVzaXplT2JzZXJ2ZXIgPT09ICd1bmRlZmluZWQnXG4gICAgICAgICAgICA/IG9mKG51bGwpXG4gICAgICAgICAgICA6IG5ldyBPYnNlcnZhYmxlKG9ic2VydmVyID0+IHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc2l6ZSA9IG5ldyBSZXNpemVPYnNlcnZlcihlbnRyaWVzID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KGVudHJpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICByZXNpemUub2JzZXJ2ZShlbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgcmVzaXplLmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCkge1xuICAgICAgICB0aGlzLm5nVW5zdWJzY3JpYmUkLm5leHQoKTtcbiAgICAgICAgdGhpcy5uZ1Vuc3Vic2NyaWJlJC5jb21wbGV0ZSgpO1xuICAgIH1cbn1cbiIsIjxuZy10ZW1wbGF0ZT5cbiAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgYXZhdGFyIG9mIGF2YXRhclJlbmRlckl0ZW1zOyBpbmRleCBhcyBpbmRleDsgbGFzdCBhcyBpc0xhc3RcIj5cbiAgPGRpdlxuICAgIGNsYXNzPVwidGh5LWF2YXRhci1jb250ZW50XCJcbiAgICBbbmdTdHlsZV09XCJvdmVybGFwTW9kZSA/IHsgJ21hcmdpbi1sZWZ0LnB4JzogYXZhdGFyT3ZlcmxhcFNwYWNlIH0gOiB7ICdtYXJnaW4tcmlnaHQucHgnOiBpc0xhc3QgPyAwIDogYXZhdGFyU3BhY2UgfVwiXG4gID5cbiAgICA8dGh5LWF2YXRhclxuICAgICAgW3RoeVNyY109XCJhdmF0YXIuX3NyY1wiXG4gICAgICBbdGh5TmFtZV09XCJhdmF0YXIuYXZhdGFyTmFtZVwiXG4gICAgICBbdGh5U2l6ZV09XCJhdmF0YXIuX3NpemVcIlxuICAgICAgW3RoeVJlbW92YWJsZV09XCJvdmVybGFwTW9kZSA/IGZhbHNlIDogdGh5UmVtb3ZhYmxlXCJcbiAgICAgIFt0aHlJbWdDbGFzc109XCJhdmF0YXIudGh5SW1nQ2xhc3NcIlxuICAgICAgW3RoeURpc2FibGVkXT1cImF2YXRhci50aHlEaXNhYmxlZFwiXG4gICAgICBbdGh5TG9hZGluZ109XCJhdmF0YXIudGh5TG9hZGluZ1wiXG4gICAgICBbdGh5RmV0Y2hQcmlvcml0eV09XCJhdmF0YXIudGh5RmV0Y2hQcmlvcml0eVwiXG4gICAgICAodGh5UmVtb3ZlKT1cInJlbW92ZShhdmF0YXIuYXZhdGFyTmFtZSlcIlxuICAgID48L3RoeS1hdmF0YXI+XG4gICAgPHNwYW4gKm5nSWY9XCJpc0xhc3QgJiYgbW9yZSAmJiB0aHlSZXNwb25zaXZlXCIgbmdDbGFzcz1cIm1vcmUte3sgYXZhdGFyLl9zaXplIH19XCI+K3t7IG1vcmUgfX0gPC9zcGFuPlxuICA8L2Rpdj5cbjwvbmctY29udGFpbmVyPlxuXG48ZGl2ICNhcHBlbmRDb250ZW50ICpuZ0lmPVwiYXBwZW5kXCIgW25nU3R5bGVdPVwieyAncGFkZGluZy1sZWZ0LnB4JzogYXZhdGFyU3BhY2UgfVwiPlxuICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImFwcGVuZFwiPjwvbmctY29udGFpbmVyPlxuPC9kaXY+XG4iXX0=