@ng-nest/ui 20.1.6 → 20.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/attachments/index.d.ts +277 -0
  2. package/auto-complete/index.d.ts +1 -0
  3. package/card/index.d.ts +12 -2
  4. package/core/index.d.ts +40 -3
  5. package/dropdown/index.d.ts +30 -8
  6. package/fesm2022/ng-nest-ui-attachments.mjs +331 -0
  7. package/fesm2022/ng-nest-ui-attachments.mjs.map +1 -0
  8. package/fesm2022/ng-nest-ui-auto-complete.mjs +3 -0
  9. package/fesm2022/ng-nest-ui-auto-complete.mjs.map +1 -1
  10. package/fesm2022/ng-nest-ui-card.mjs +11 -5
  11. package/fesm2022/ng-nest-ui-card.mjs.map +1 -1
  12. package/fesm2022/ng-nest-ui-core.mjs +29 -1
  13. package/fesm2022/ng-nest-ui-core.mjs.map +1 -1
  14. package/fesm2022/ng-nest-ui-dropdown.mjs +160 -38
  15. package/fesm2022/ng-nest-ui-dropdown.mjs.map +1 -1
  16. package/fesm2022/ng-nest-ui-image.mjs +2 -2
  17. package/fesm2022/ng-nest-ui-image.mjs.map +1 -1
  18. package/fesm2022/ng-nest-ui-list.mjs +31 -7
  19. package/fesm2022/ng-nest-ui-list.mjs.map +1 -1
  20. package/fesm2022/ng-nest-ui-prompts.mjs +8 -3
  21. package/fesm2022/ng-nest-ui-prompts.mjs.map +1 -1
  22. package/fesm2022/ng-nest-ui-select.mjs +3 -0
  23. package/fesm2022/ng-nest-ui-select.mjs.map +1 -1
  24. package/fesm2022/ng-nest-ui-sender.mjs +6 -5
  25. package/fesm2022/ng-nest-ui-sender.mjs.map +1 -1
  26. package/fesm2022/ng-nest-ui-suggestion.mjs +110 -0
  27. package/fesm2022/ng-nest-ui-suggestion.mjs.map +1 -0
  28. package/fesm2022/ng-nest-ui-thought-chain.mjs +121 -0
  29. package/fesm2022/ng-nest-ui-thought-chain.mjs.map +1 -0
  30. package/fesm2022/ng-nest-ui-timeline.mjs +27 -5
  31. package/fesm2022/ng-nest-ui-timeline.mjs.map +1 -1
  32. package/fesm2022/ng-nest-ui-upload.mjs +205 -11
  33. package/fesm2022/ng-nest-ui-upload.mjs.map +1 -1
  34. package/fesm2022/ng-nest-ui.mjs +4 -0
  35. package/fesm2022/ng-nest-ui.mjs.map +1 -1
  36. package/index.d.ts +4 -0
  37. package/list/index.d.ts +30 -18
  38. package/package.json +57 -45
  39. package/prompts/index.d.ts +17 -2
  40. package/select/index.d.ts +1 -0
  41. package/sender/index.d.ts +1 -0
  42. package/suggestion/index.d.ts +96 -0
  43. package/thought-chain/index.d.ts +107 -0
  44. package/timeline/index.d.ts +35 -19
  45. package/upload/index.d.ts +39 -2
@@ -1,13 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, model, output, Component, signal, inject, DestroyRef, ViewContainerRef, effect, ElementRef, HostListener, HostBinding, ChangeDetectionStrategy, ViewEncapsulation, viewChild, computed, NgModule } from '@angular/core';
3
- import { XPropertyFunction, XToDataArray, XToBoolean, XToCssPixelValue, XToNumber, XConnectBaseAnimation, XIsEmpty, XGetChildren, XHasChildren } from '@ng-nest/ui/core';
2
+ import { input, model, output, Component, signal, viewChild, inject, DestroyRef, computed, ViewContainerRef, effect, ElementRef, HostListener, HostBinding, ChangeDetectionStrategy, ViewEncapsulation, NgModule } from '@angular/core';
3
+ import { XPropertyFunction, XToDataArray, XToBoolean, XToCssPixelValue, XToNumber, XConnectBaseAnimation, XIsEmpty, XGetChildren, XHasChildren, XIsNull, XIsChange } from '@ng-nest/ui/core';
4
4
  import { Subject, of } from 'rxjs';
5
5
  import { XPortalService, XPortalConnectedPosition } from '@ng-nest/ui/portal';
6
- import { takeUntil, delay, debounceTime } from 'rxjs/operators';
6
+ import { takeUntil, throttleTime, delay, debounceTime } from 'rxjs/operators';
7
7
  import { Overlay } from '@angular/cdk/overlay';
8
8
  import { XListComponent } from '@ng-nest/ui/list';
9
9
  import * as i1 from '@angular/forms';
10
10
  import { FormsModule } from '@angular/forms';
11
+ import { RIGHT_ARROW, LEFT_ARROW, ESCAPE, DOWN_ARROW } from '@angular/cdk/keycodes';
11
12
 
12
13
  /**
13
14
  * Dropdown
@@ -72,6 +73,11 @@ class XDropdownProperty extends XPropertyFunction(X_DROPDOWN_CONFIG_NAME) {
72
73
  * @en_US Hover delay trigger time, only trigger is the 'hover'
73
74
  */
74
75
  this.hoverDelay = input(200, ...(ngDevMode ? [{ debugName: "hoverDelay", transform: XToNumber }] : [{ transform: XToNumber }]));
76
+ /**
77
+ * @zh_CN visible 参数控制显示/隐藏
78
+ * @en_US visible parameter controls display/hide
79
+ */
80
+ this.visible = model(null, ...(ngDevMode ? [{ debugName: "visible" }] : []));
75
81
  /**
76
82
  * @zh_CN 当前激活的菜单
77
83
  * @en_US The currently activated menu
@@ -89,7 +95,7 @@ class XDropdownProperty extends XPropertyFunction(X_DROPDOWN_CONFIG_NAME) {
89
95
  this.nodeClick = output();
90
96
  }
91
97
  /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: XDropdownProperty, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
92
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.0", type: XDropdownProperty, isStandalone: true, selector: "x-dropdown-property", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, children: { classPropertyName: "children", publicName: "children", isSignal: true, isRequired: false, transformFunction: null }, portalMinWidth: { classPropertyName: "portalMinWidth", publicName: "portalMinWidth", isSignal: true, isRequired: false, transformFunction: null }, portalMaxWidth: { classPropertyName: "portalMaxWidth", publicName: "portalMaxWidth", isSignal: true, isRequired: false, transformFunction: null }, portalMinHeight: { classPropertyName: "portalMinHeight", publicName: "portalMinHeight", isSignal: true, isRequired: false, transformFunction: null }, portalMaxHeight: { classPropertyName: "portalMaxHeight", publicName: "portalMaxHeight", isSignal: true, isRequired: false, transformFunction: null }, hoverDelay: { classPropertyName: "hoverDelay", publicName: "hoverDelay", isSignal: true, isRequired: false, transformFunction: null }, activatedId: { classPropertyName: "activatedId", publicName: "activatedId", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activatedId: "activatedIdChange", nodeClick: "nodeClick" }, usesInheritance: true, ngImport: i0, template: '', isInline: true }); }
98
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.0", type: XDropdownProperty, isStandalone: true, selector: "x-dropdown-property", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, children: { classPropertyName: "children", publicName: "children", isSignal: true, isRequired: false, transformFunction: null }, portalMinWidth: { classPropertyName: "portalMinWidth", publicName: "portalMinWidth", isSignal: true, isRequired: false, transformFunction: null }, portalMaxWidth: { classPropertyName: "portalMaxWidth", publicName: "portalMaxWidth", isSignal: true, isRequired: false, transformFunction: null }, portalMinHeight: { classPropertyName: "portalMinHeight", publicName: "portalMinHeight", isSignal: true, isRequired: false, transformFunction: null }, portalMaxHeight: { classPropertyName: "portalMaxHeight", publicName: "portalMaxHeight", isSignal: true, isRequired: false, transformFunction: null }, hoverDelay: { classPropertyName: "hoverDelay", publicName: "hoverDelay", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, activatedId: { classPropertyName: "activatedId", publicName: "activatedId", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visible: "visibleChange", activatedId: "activatedIdChange", nodeClick: "nodeClick" }, usesInheritance: true, ngImport: i0, template: '', isInline: true }); }
93
99
  }
94
100
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: XDropdownProperty, decorators: [{
95
101
  type: Component,
@@ -131,24 +137,41 @@ class XDropdownPortalComponent {
131
137
  this.maxWidth = input(...(ngDevMode ? [undefined, { debugName: "maxWidth" }] : []));
132
138
  this.minHeight = input(...(ngDevMode ? [undefined, { debugName: "minHeight" }] : []));
133
139
  this.maxHeight = input(...(ngDevMode ? [undefined, { debugName: "maxHeight" }] : []));
140
+ this.level = input(0, ...(ngDevMode ? [{ debugName: "level" }] : []));
141
+ this.parentPortalComponent = input(...(ngDevMode ? [undefined, { debugName: "parentPortalComponent" }] : []));
142
+ this.isKeyboardControlled = model(true, ...(ngDevMode ? [{ debugName: "isKeyboardControlled" }] : []));
134
143
  this.closed = output();
135
144
  this.animating = output();
136
145
  this.nodeClick = output();
137
146
  this.portalHover = output();
138
147
  this.node = signal(null, ...(ngDevMode ? [{ debugName: "node" }] : []));
139
- this.openNode = signal(null, ...(ngDevMode ? [{ debugName: "openNode" }] : []));
148
+ this.list = viewChild.required('list');
140
149
  this.portalPlacement = signal(null, ...(ngDevMode ? [{ debugName: "portalPlacement" }] : []));
141
150
  this.childAnimating = signal(false, ...(ngDevMode ? [{ debugName: "childAnimating" }] : []));
142
151
  this.activatedId = model(...(ngDevMode ? [undefined, { debugName: "activatedId" }] : []));
143
152
  this.destroy = signal(false, ...(ngDevMode ? [{ debugName: "destroy" }] : []));
153
+ this.active = signal(0, ...(ngDevMode ? [{ debugName: "active" }] : []));
144
154
  this.unSubject = new Subject();
145
155
  this.destroyRef = inject(DestroyRef);
156
+ this.activatedIdComputed = computed(() => {
157
+ const path = this.findPathById(this.data(), this.activatedId());
158
+ if (path) {
159
+ for (let node of path) {
160
+ const nd = this.data().find((x) => x.id === node.id);
161
+ if (nd)
162
+ return nd.id;
163
+ }
164
+ }
165
+ return null;
166
+ }, ...(ngDevMode ? [{ debugName: "activatedIdComputed" }] : []));
146
167
  this.portalService = inject(XPortalService);
147
168
  this.overlay = inject(Overlay);
148
169
  this.viewContainerRef = inject(ViewContainerRef);
149
170
  this.portalComponent = signal(null, ...(ngDevMode ? [{ debugName: "portalComponent" }] : []));
150
171
  this.portalOverlayRef = signal(null, ...(ngDevMode ? [{ debugName: "portalOverlayRef" }] : []));
151
172
  effect(() => this.portalComponent()?.setInput('data', this.node()?.children));
173
+ effect(() => this.portalComponent()?.setInput('trigger', this.trigger()));
174
+ effect(() => this.portalComponent()?.setInput('level', this.level() + 1));
152
175
  effect(() => this.portalComponent()?.setInput('minWidth', this.minWidth()));
153
176
  effect(() => this.portalComponent()?.setInput('maxWidth', this.maxWidth()));
154
177
  effect(() => this.portalComponent()?.setInput('minHeight', this.minHeight()));
@@ -156,19 +179,53 @@ class XDropdownPortalComponent {
156
179
  effect(() => this.portalComponent()?.setInput('size', this.size()));
157
180
  effect(() => this.portalComponent()?.setInput('placement', this.portalPlacement()));
158
181
  effect(() => this.portalComponent()?.setInput('activatedId', this.activatedId()));
182
+ effect(() => this.portalComponent()?.setInput('parentPortalComponent', this));
159
183
  }
160
184
  ngOnInit() {
185
+ this.closeSubject.subscribe(() => {
186
+ this.data() && this.data().length > 0 && this.list().setUnActive(this.active());
187
+ });
188
+ this.keydownSubject.pipe(takeUntil(this.unSubject)).subscribe((x) => {
189
+ if (!this.isKeyboardControlled())
190
+ return;
191
+ const keyCode = x.keyCode;
192
+ const isRightArrow = [RIGHT_ARROW].includes(keyCode);
193
+ const isLeftArrow = [LEFT_ARROW].includes(keyCode);
194
+ if (isRightArrow) {
195
+ const item = this.list().keyManager.activeItem;
196
+ if (item?.leaf()) {
197
+ const node = item.node();
198
+ node.event = x;
199
+ node.component = item;
200
+ this.isKeyboardControlled.set(false);
201
+ this.onNodeClick(node);
202
+ }
203
+ }
204
+ if (isLeftArrow && this.level() > 0) {
205
+ this.parentPortalComponent()?.isKeyboardControlled.set(true);
206
+ this.parentPortalComponent()?.closePortal();
207
+ }
208
+ this.data() && this.data().length > 0 && this.list().keydown(x);
209
+ });
161
210
  this.destroyRef.onDestroy(() => {
162
211
  this.destroy.set(true);
163
212
  this.unSubject.next();
164
213
  this.unSubject.complete();
165
214
  });
166
215
  }
216
+ ngAfterViewInit() {
217
+ this.list().keyManager.setFirstItemActive();
218
+ }
167
219
  onNodeClick(node) {
168
220
  this.nodeClick.emit(node);
169
221
  if (!node.leaf) {
170
222
  this.activatedId.set(node.id);
171
- this.closed.emit();
223
+ this.closeSubject.next();
224
+ }
225
+ else {
226
+ if (node.disabled || this.childAnimating())
227
+ return;
228
+ this.showPortal(node);
172
229
  }
173
230
  }
174
231
  portalAttached() {
@@ -213,6 +270,11 @@ class XDropdownPortalComponent {
213
270
  return;
214
271
  this.portalComponent.set(componentRef);
215
272
  this.portalOverlayRef.set(overlayRef);
273
+ Object.assign(componentRef.instance, {
274
+ closeSubject: this.closeSubject,
275
+ keydownSubject: this.keydownSubject,
276
+ parantPortal: this
277
+ });
216
278
  const { closed, animating, nodeClick, portalHover, activatedId } = componentRef.instance;
217
279
  closed.subscribe(() => this.closePortal());
218
280
  animating.subscribe((ing) => this.childAnimating.set(ing));
@@ -231,53 +293,63 @@ class XDropdownPortalComponent {
231
293
  }
232
294
  setPlacement() {
233
295
  return this.portalService.setPlacement({
234
- elementRef: new ElementRef(this.node()?.event?.target),
296
+ elementRef: new ElementRef(this.node()?.component?.elementRef?.nativeElement),
235
297
  placement: ['right-start', 'right-end', 'left-start', 'left-end'],
236
298
  transformOriginOn: 'x-dropdown-portal'
237
299
  });
238
300
  }
239
- onEnter(node) {
240
- if (!node.leaf || node.disabled || this.childAnimating())
241
- return;
242
- if (this.timeoutHide)
243
- clearTimeout(this.timeoutHide);
301
+ showPortal(node) {
244
302
  if (this.portalAttached() && this.node()?.id !== node.id) {
245
- this.changeOpenNode(false);
246
303
  this.portalOverlayRef()?.dispose();
247
304
  }
248
305
  this.node.set(node);
249
306
  if (!this.portalAttached()) {
250
- this.openNode.set(node);
251
- this.changeOpenNode(true);
252
307
  this.createPortal();
253
308
  }
254
309
  }
310
+ onEnter(node) {
311
+ if (!node.leaf || node.disabled || this.trigger() === 'click' || this.childAnimating())
312
+ return;
313
+ if (this.timeoutHide)
314
+ clearTimeout(this.timeoutHide);
315
+ this.showPortal(node);
316
+ }
255
317
  onLeave() {
318
+ if (this.trigger() !== 'hover')
319
+ return;
256
320
  if (this.portalAttached()) {
257
321
  this.timeoutHide = setTimeout(() => {
258
- this.changeOpenNode(false);
259
- this.portal?.overlayRef?.dispose();
322
+ this.closePortal();
260
323
  });
261
324
  }
262
- else {
263
- this.changeOpenNode(false);
264
- }
265
325
  }
266
- changeOpenNode(open) {
267
- if (this.openNode()) {
268
- this.openNode.update((x) => {
269
- x.openPortal = open;
270
- x.change && x.change();
271
- return x;
272
- });
326
+ onActive(num) {
327
+ this.active.set(num);
328
+ }
329
+ onTabOut() {
330
+ this.closeSubject.next();
331
+ }
332
+ findPathById(nodes, id, currentPath = []) {
333
+ for (const node of nodes) {
334
+ const newPath = [...currentPath, node];
335
+ if (node.id === id) {
336
+ return newPath;
337
+ }
338
+ if (node.children && node.children.length > 0) {
339
+ const result = this.findPathById(node.children, id, newPath);
340
+ if (result) {
341
+ return result;
342
+ }
343
+ }
273
344
  }
345
+ return null;
274
346
  }
275
347
  /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: XDropdownPortalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
276
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.0", type: XDropdownPortalComponent, isStandalone: true, selector: "x-dropdown-portal", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, activatedId: { classPropertyName: "activatedId", publicName: "activatedId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", animating: "animating", nodeClick: "nodeClick", portalHover: "portalHover", activatedId: "activatedIdChange" }, host: { listeners: { "@x-connect-base-animation.done": "done($event)", "@x-connect-base-animation.start": "start($event)", "mouseenter": "mouseenter()", "mouseleave": "mouseleave()" }, properties: { "@x-connect-base-animation": "this.getPlacement" } }, ngImport: i0, template: "<div\r\n #dropdownPortal\r\n class=\"x-dropdown-portal\"\r\n [style.minWidth]=\"minWidth()\"\r\n [style.maxWidth]=\"maxWidth()\"\r\n [style.minHeight]=\"minHeight()\"\r\n [style.maxHeight]=\"maxHeight()\"\r\n>\r\n <x-list\r\n [data]=\"data()\"\r\n (nodeClick)=\"onNodeClick($event)\"\r\n [(ngModel)]=\"activatedId\"\r\n (nodeMouseenter)=\"onEnter($event)\"\r\n (nodeMouseleave)=\"onLeave()\"\r\n [inPortal]=\"true\"\r\n [size]=\"size()\"\r\n ></x-list>\r\n</div>\r\n", styles: ["x-dropdown-portal{width:100%}.x-dropdown-portal{margin:.0625rem 0;color:var(--x-text);width:100%;background-color:var(--x-background-100);border-radius:var(--x-border-small-radius);box-shadow:var(--x-box-shadow);position:relative;display:flex;overflow:auto}.x-dropdown-portal .x-open-portal{background-color:var(--x-background-a200)}.x-dropdown-portal-child{margin-top:-.3125rem}.x-dropdown-portal-child>x-dropdown-portal{padding:0 .3125rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: XListComponent, selector: "x-list" }], animations: [XConnectBaseAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
348
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.0", type: XDropdownPortalComponent, isStandalone: true, selector: "x-dropdown-portal", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, parentPortalComponent: { classPropertyName: "parentPortalComponent", publicName: "parentPortalComponent", isSignal: true, isRequired: false, transformFunction: null }, isKeyboardControlled: { classPropertyName: "isKeyboardControlled", publicName: "isKeyboardControlled", isSignal: true, isRequired: false, transformFunction: null }, activatedId: { classPropertyName: "activatedId", publicName: "activatedId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isKeyboardControlled: "isKeyboardControlledChange", closed: "closed", animating: "animating", nodeClick: "nodeClick", portalHover: "portalHover", activatedId: "activatedIdChange" }, host: { listeners: { "@x-connect-base-animation.done": "done($event)", "@x-connect-base-animation.start": "start($event)", "mouseenter": "mouseenter()", "mouseleave": "mouseleave()" }, properties: { "@x-connect-base-animation": "this.getPlacement" } }, viewQueries: [{ propertyName: "list", first: true, predicate: ["list"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\r\n #dropdownPortal\r\n class=\"x-dropdown-portal\"\r\n [style.minWidth]=\"minWidth()\"\r\n [style.maxWidth]=\"maxWidth()\"\r\n [style.minHeight]=\"minHeight()\"\r\n [style.maxHeight]=\"maxHeight()\"\r\n>\r\n <x-list\r\n #list\r\n [data]=\"data()\"\r\n [ngModel]=\"activatedIdComputed()\"\r\n (nodeClick)=\"onNodeClick($event)\"\r\n (keyManagerChange)=\"onActive($event)\"\r\n (keyManagerTabOut)=\"onTabOut()\"\r\n (nodeMouseenter)=\"onEnter($event)\"\r\n (nodeMouseleave)=\"onLeave()\"\r\n [isKeyboardControlled]=\"isKeyboardControlled()\"\r\n [inPortal]=\"true\"\r\n [size]=\"size()\"\r\n ></x-list>\r\n</div>\r\n", styles: ["x-dropdown-portal{width:100%}.x-dropdown-portal{margin:.0625rem 0;color:var(--x-text);width:100%;background-color:var(--x-background-100);border-radius:var(--x-border-small-radius);box-shadow:var(--x-box-shadow);position:relative;display:flex;overflow:auto}.x-dropdown-portal .x-open-portal{background-color:var(--x-background-a200)}.x-dropdown-portal-child{margin-top:-.3125rem}.x-dropdown-portal-child>x-dropdown-portal{padding:0 .3125rem}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: XListComponent, selector: "x-list" }], animations: [XConnectBaseAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
277
349
  }
278
350
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: XDropdownPortalComponent, decorators: [{
279
351
  type: Component,
280
- args: [{ selector: `${XDropdownPortalPrefix}`, imports: [FormsModule, XListComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, animations: [XConnectBaseAnimation], template: "<div\r\n #dropdownPortal\r\n class=\"x-dropdown-portal\"\r\n [style.minWidth]=\"minWidth()\"\r\n [style.maxWidth]=\"maxWidth()\"\r\n [style.minHeight]=\"minHeight()\"\r\n [style.maxHeight]=\"maxHeight()\"\r\n>\r\n <x-list\r\n [data]=\"data()\"\r\n (nodeClick)=\"onNodeClick($event)\"\r\n [(ngModel)]=\"activatedId\"\r\n (nodeMouseenter)=\"onEnter($event)\"\r\n (nodeMouseleave)=\"onLeave()\"\r\n [inPortal]=\"true\"\r\n [size]=\"size()\"\r\n ></x-list>\r\n</div>\r\n", styles: ["x-dropdown-portal{width:100%}.x-dropdown-portal{margin:.0625rem 0;color:var(--x-text);width:100%;background-color:var(--x-background-100);border-radius:var(--x-border-small-radius);box-shadow:var(--x-box-shadow);position:relative;display:flex;overflow:auto}.x-dropdown-portal .x-open-portal{background-color:var(--x-background-a200)}.x-dropdown-portal-child{margin-top:-.3125rem}.x-dropdown-portal-child>x-dropdown-portal{padding:0 .3125rem}\n"] }]
352
+ args: [{ selector: `${XDropdownPortalPrefix}`, imports: [FormsModule, XListComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, animations: [XConnectBaseAnimation], template: "<div\r\n #dropdownPortal\r\n class=\"x-dropdown-portal\"\r\n [style.minWidth]=\"minWidth()\"\r\n [style.maxWidth]=\"maxWidth()\"\r\n [style.minHeight]=\"minHeight()\"\r\n [style.maxHeight]=\"maxHeight()\"\r\n>\r\n <x-list\r\n #list\r\n [data]=\"data()\"\r\n [ngModel]=\"activatedIdComputed()\"\r\n (nodeClick)=\"onNodeClick($event)\"\r\n (keyManagerChange)=\"onActive($event)\"\r\n (keyManagerTabOut)=\"onTabOut()\"\r\n (nodeMouseenter)=\"onEnter($event)\"\r\n (nodeMouseleave)=\"onLeave()\"\r\n [isKeyboardControlled]=\"isKeyboardControlled()\"\r\n [inPortal]=\"true\"\r\n [size]=\"size()\"\r\n ></x-list>\r\n</div>\r\n", styles: ["x-dropdown-portal{width:100%}.x-dropdown-portal{margin:.0625rem 0;color:var(--x-text);width:100%;background-color:var(--x-background-100);border-radius:var(--x-border-small-radius);box-shadow:var(--x-box-shadow);position:relative;display:flex;overflow:auto}.x-dropdown-portal .x-open-portal{background-color:var(--x-background-a200)}.x-dropdown-portal-child{margin-top:-.3125rem}.x-dropdown-portal-child>x-dropdown-portal{padding:0 .3125rem}\n"] }]
281
353
  }], ctorParameters: () => [], propDecorators: { getPlacement: [{
282
354
  type: HostBinding,
283
355
  args: ['@x-connect-base-animation']
@@ -310,12 +382,15 @@ class XDropdownComponent extends XDropdownProperty {
310
382
  }
311
383
  return XHasChildren(data, 0);
312
384
  }, ...(ngDevMode ? [{ debugName: "nodes" }] : []));
313
- this.visible = signal(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
314
385
  this.animating = signal(false, ...(ngDevMode ? [{ debugName: "animating" }] : []));
386
+ this.visibleClass = signal(false, ...(ngDevMode ? [{ debugName: "visibleClass" }] : []));
315
387
  this.outsideClick = signal(false, ...(ngDevMode ? [{ debugName: "outsideClick" }] : []));
388
+ this.isClickNodeLeaf = signal(false, ...(ngDevMode ? [{ debugName: "isClickNodeLeaf" }] : []));
316
389
  this.minWidth = signal('0px', ...(ngDevMode ? [{ debugName: "minWidth" }] : []));
317
390
  this.hoverDelayUnsub = new Subject();
318
391
  this.closeSubject = new Subject();
392
+ this.keydownSubject = new Subject();
393
+ this.isNullVisible = signal(false, ...(ngDevMode ? [{ debugName: "isNullVisible" }] : []));
319
394
  this.realPlacement = signal(null, ...(ngDevMode ? [{ debugName: "realPlacement" }] : []));
320
395
  this.portalComponent = signal(null, ...(ngDevMode ? [{ debugName: "portalComponent" }] : []));
321
396
  this.portalOverlayRef = signal(null, ...(ngDevMode ? [{ debugName: "portalOverlayRef" }] : []));
@@ -330,6 +405,11 @@ class XDropdownComponent extends XDropdownProperty {
330
405
  }
331
406
  ngOnInit() {
332
407
  this.setSubject();
408
+ this.isNullVisible.set(XIsNull(this.visible()));
409
+ }
410
+ ngOnChanges(changes) {
411
+ const { visible } = changes;
412
+ XIsChange(visible) && this.setVisible();
333
413
  }
334
414
  ngOnDestroy() {
335
415
  this.unSubject.next();
@@ -337,12 +417,40 @@ class XDropdownComponent extends XDropdownProperty {
337
417
  this.hoverDelayUnsub.next();
338
418
  this.hoverDelayUnsub.complete();
339
419
  }
420
+ setVisible() {
421
+ if (this.disabled() || this.animating())
422
+ return;
423
+ if (this.visible()) {
424
+ if (this.portalAttached()) {
425
+ this.closeSubject.next();
426
+ return;
427
+ }
428
+ this.createPortal();
429
+ }
430
+ else {
431
+ this.closePortal();
432
+ }
433
+ }
340
434
  setSubject() {
341
435
  this.closeSubject.pipe(takeUntil(this.unSubject)).subscribe(() => {
342
436
  this.closePortal();
343
437
  });
438
+ this.keydownSubject.pipe(throttleTime(10), takeUntil(this.unSubject)).subscribe((x) => {
439
+ const keyCode = x.keyCode;
440
+ if (this.portalAttached() && [ESCAPE].includes(keyCode)) {
441
+ this.closeSubject.next();
442
+ }
443
+ if (!this.portalAttached() && [DOWN_ARROW].includes(keyCode)) {
444
+ if (this.disabled())
445
+ return;
446
+ this.visibleClass.set(true);
447
+ this.createPortal();
448
+ }
449
+ });
344
450
  }
345
451
  onEnter() {
452
+ if (!this.isNullVisible())
453
+ return;
346
454
  of(true)
347
455
  .pipe(delay(this.hoverDelay()), takeUntil(this.hoverDelayUnsub))
348
456
  .subscribe(() => {
@@ -353,23 +461,25 @@ class XDropdownComponent extends XDropdownProperty {
353
461
  this.timeoutHide = null;
354
462
  }
355
463
  if (!this.portal || (this.portal && !this.portalOverlayRef()?.hasAttached())) {
356
- this.visible.set(true);
464
+ this.visibleClass.set(true);
357
465
  this.createPortal();
358
466
  }
359
467
  });
360
468
  }
361
469
  onLeave() {
470
+ if (!this.isNullVisible())
471
+ return;
362
472
  this.hoverDelayUnsub.next();
363
473
  if (this.disabled() || this.trigger() === 'click')
364
474
  return;
365
475
  if (this.portalOverlayRef()?.hasAttached()) {
366
476
  this.timeoutHide = setTimeout(() => {
367
477
  this.portalOverlayRef()?.dispose();
368
- this.visible.set(false);
478
+ this.visibleClass.set(false);
369
479
  });
370
480
  }
371
481
  }
372
- showPortal() {
482
+ onClickShow() {
373
483
  if (this.disabled() || this.trigger() === 'hover' || this.animating())
374
484
  return;
375
485
  if (this.trigger() === 'click' && this.portalAttached()) {
@@ -384,7 +494,7 @@ class XDropdownComponent extends XDropdownProperty {
384
494
  closePortal() {
385
495
  if (this.portalAttached()) {
386
496
  this.portalOverlayRef()?.dispose();
387
- this.visible.set(false);
497
+ this.visibleClass.set(false);
388
498
  return true;
389
499
  }
390
500
  return false;
@@ -409,7 +519,9 @@ class XDropdownComponent extends XDropdownProperty {
409
519
  ?.outsidePointerEvents()
410
520
  .pipe(debounceTime(30), takeUntil(this.unSubject))
411
521
  .subscribe(() => {
412
- this.closeSubject.next();
522
+ if (!this.isClickNodeLeaf()) {
523
+ this.closeSubject.next();
524
+ }
413
525
  });
414
526
  }
415
527
  this.setInstance();
@@ -431,10 +543,17 @@ class XDropdownComponent extends XDropdownProperty {
431
543
  this.portalComponent.set(componentRef);
432
544
  this.portalOverlayRef.set(overlayRef);
433
545
  this.realPlacement.set(this.placement());
546
+ Object.assign(componentRef.instance, {
547
+ closeSubject: this.closeSubject,
548
+ keydownSubject: this.keydownSubject
549
+ });
434
550
  const { closed, animating, nodeClick, portalHover, activatedId } = componentRef.instance;
435
551
  closed.subscribe(() => this.closeSubject.next());
436
552
  animating.subscribe((ing) => this.animating.set(ing));
437
- nodeClick.subscribe((node) => this.nodeClick.emit(node));
553
+ nodeClick.subscribe((node) => {
554
+ this.isClickNodeLeaf.set(node.leaf);
555
+ this.nodeClick.emit(node);
556
+ });
438
557
  activatedId.subscribe((id) => this.activatedId.set(id));
439
558
  portalHover.subscribe((hover) => this.portalHover(hover));
440
559
  }
@@ -446,6 +565,9 @@ class XDropdownComponent extends XDropdownProperty {
446
565
  this.onLeave();
447
566
  }
448
567
  }
568
+ onKeydown($event) {
569
+ this.keydownSubject.next($event);
570
+ }
449
571
  setPlacement() {
450
572
  return this.portalService.setPlacement({
451
573
  elementRef: this.dropdown(),
@@ -454,11 +576,11 @@ class XDropdownComponent extends XDropdownProperty {
454
576
  });
455
577
  }
456
578
  /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: XDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
457
- /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.0", type: XDropdownComponent, isStandalone: true, selector: "x-dropdown", viewQueries: [{ propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div\r\n #dropdown\r\n class=\"x-dropdown\"\r\n [class.x-visible]=\"visible()\"\r\n (mouseenter)=\"onEnter()\"\r\n (mouseleave)=\"onLeave()\"\r\n (click)=\"showPortal()\"\r\n>\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".x-dropdown{margin:0;padding:0}.x-dropdown{display:inline-block}.x-dropdown.x-visible{color:var(--x-primary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
579
+ /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.0", type: XDropdownComponent, isStandalone: true, selector: "x-dropdown", viewQueries: [{ propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true, isSignal: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div\r\n #dropdown\r\n class=\"x-dropdown\"\r\n [class.x-visible]=\"visibleClass()\"\r\n (mouseenter)=\"onEnter()\"\r\n (mouseleave)=\"onLeave()\"\r\n (click)=\"onClickShow()\"\r\n (keydown)=\"onKeydown($event)\"\r\n tabindex=\"-1\"\r\n>\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".x-dropdown{margin:0;padding:0}.x-dropdown{display:inline-block}.x-dropdown.x-visible{color:var(--x-primary)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
458
580
  }
459
581
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.0", ngImport: i0, type: XDropdownComponent, decorators: [{
460
582
  type: Component,
461
- args: [{ selector: `${XDropdownPrefix}`, imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n #dropdown\r\n class=\"x-dropdown\"\r\n [class.x-visible]=\"visible()\"\r\n (mouseenter)=\"onEnter()\"\r\n (mouseleave)=\"onLeave()\"\r\n (click)=\"showPortal()\"\r\n>\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".x-dropdown{margin:0;padding:0}.x-dropdown{display:inline-block}.x-dropdown.x-visible{color:var(--x-primary)}\n"] }]
583
+ args: [{ selector: `${XDropdownPrefix}`, imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n #dropdown\r\n class=\"x-dropdown\"\r\n [class.x-visible]=\"visibleClass()\"\r\n (mouseenter)=\"onEnter()\"\r\n (mouseleave)=\"onLeave()\"\r\n (click)=\"onClickShow()\"\r\n (keydown)=\"onKeydown($event)\"\r\n tabindex=\"-1\"\r\n>\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".x-dropdown{margin:0;padding:0}.x-dropdown{display:inline-block}.x-dropdown.x-visible{color:var(--x-primary)}\n"] }]
462
584
  }], ctorParameters: () => [] });
463
585
 
464
586
  class XDropdownModule {