ng-zorro-antd-auto-complete.mjs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. import * as i0 from '@angular/core';
  2. import { Input, ViewEncapsulation, ChangeDetectionStrategy, Component, EventEmitter, inject, booleanAttribute, Output, forwardRef, Directive, TemplateRef, ViewChild, ViewChildren, ContentChildren, NgModule } from '@angular/core';
  3. import * as i1 from 'ng-zorro-antd/core/outlet';
  4. import { NzOutletModule } from 'ng-zorro-antd/core/outlet';
  5. import { Subject, Subscription, defer, merge } from 'rxjs';
  6. import { filter, takeUntil, tap, delay, switchMap } from 'rxjs/operators';
  7. import { fromEventOutsideAngular, scrollIntoView, numberAttributeWithZeroFallback } from 'ng-zorro-antd/core/util';
  8. import { UP_ARROW, DOWN_ARROW, ESCAPE, TAB, ENTER } from '@angular/cdk/keycodes';
  9. import * as i1$1 from '@angular/cdk/overlay';
  10. import { OverlayConfig, ConnectionPositionPair } from '@angular/cdk/overlay';
  11. import { TemplatePortal } from '@angular/cdk/portal';
  12. import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
  13. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  14. import { NzInputGroupWhitSuffixOrPrefixDirective } from 'ng-zorro-antd/input';
  15. import { slideMotion } from 'ng-zorro-antd/core/animation';
  16. import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation';
  17. import { NZ_AFTER_NEXT_RENDER$ } from 'ng-zorro-antd/core/render';
  18. import * as i1$2 from '@angular/cdk/bidi';
  19. /**
  20. * Use of this source code is governed by an MIT-style license that can be
  21. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  22. */
  23. class NzAutocompleteOptgroupComponent {
  24. nzLabel;
  25. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteOptgroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
  26. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.2", type: NzAutocompleteOptgroupComponent, isStandalone: true, selector: "nz-auto-optgroup", inputs: { nzLabel: "nzLabel" }, exportAs: ["nzAutoOptgroup"], ngImport: i0, template: `
  27. <div class="ant-select-item ant-select-item-group">
  28. <ng-container *nzStringTemplateOutlet="nzLabel">{{ nzLabel }}</ng-container>
  29. </div>
  30. <ng-content select="nz-auto-option"></ng-content>
  31. `, isInline: true, dependencies: [{ kind: "ngmodule", type: NzOutletModule }, { kind: "directive", type: i1.NzStringTemplateOutletDirective, selector: "[nzStringTemplateOutlet]", inputs: ["nzStringTemplateOutletContext", "nzStringTemplateOutlet"], exportAs: ["nzStringTemplateOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
  32. }
  33. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteOptgroupComponent, decorators: [{
  34. type: Component,
  35. args: [{
  36. selector: 'nz-auto-optgroup',
  37. exportAs: 'nzAutoOptgroup',
  38. preserveWhitespaces: false,
  39. changeDetection: ChangeDetectionStrategy.OnPush,
  40. encapsulation: ViewEncapsulation.None,
  41. imports: [NzOutletModule],
  42. template: `
  43. <div class="ant-select-item ant-select-item-group">
  44. <ng-container *nzStringTemplateOutlet="nzLabel">{{ nzLabel }}</ng-container>
  45. </div>
  46. <ng-content select="nz-auto-option"></ng-content>
  47. `
  48. }]
  49. }], propDecorators: { nzLabel: [{
  50. type: Input
  51. }] } });
  52. /**
  53. * Use of this source code is governed by an MIT-style license that can be
  54. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  55. */
  56. class NzOptionSelectionChange {
  57. source;
  58. isUserInput;
  59. constructor(source, isUserInput = false) {
  60. this.source = source;
  61. this.isUserInput = isUserInput;
  62. }
  63. }
  64. class NzAutocompleteOptionComponent {
  65. ngZone;
  66. changeDetectorRef;
  67. element;
  68. nzValue;
  69. nzLabel;
  70. nzDisabled = false;
  71. selectionChange = new EventEmitter();
  72. mouseEntered = new EventEmitter();
  73. active = false;
  74. selected = false;
  75. nzAutocompleteOptgroupComponent = inject(NzAutocompleteOptgroupComponent, { optional: true });
  76. destroy$ = new Subject();
  77. constructor(ngZone, changeDetectorRef, element) {
  78. this.ngZone = ngZone;
  79. this.changeDetectorRef = changeDetectorRef;
  80. this.element = element;
  81. }
  82. ngOnInit() {
  83. fromEventOutsideAngular(this.element.nativeElement, 'mouseenter')
  84. .pipe(filter(() => this.mouseEntered.observers.length > 0), takeUntil(this.destroy$))
  85. .subscribe(() => {
  86. this.ngZone.run(() => this.mouseEntered.emit(this));
  87. });
  88. fromEventOutsideAngular(this.element.nativeElement, 'mousedown')
  89. .pipe(takeUntil(this.destroy$))
  90. .subscribe(event => event.preventDefault());
  91. }
  92. ngOnDestroy() {
  93. this.destroy$.next();
  94. }
  95. select(emit = true) {
  96. this.selected = true;
  97. this.changeDetectorRef.markForCheck();
  98. if (emit) {
  99. this.emitSelectionChangeEvent();
  100. }
  101. }
  102. deselect() {
  103. this.selected = false;
  104. this.changeDetectorRef.markForCheck();
  105. this.emitSelectionChangeEvent();
  106. }
  107. /** Git display label */
  108. getLabel() {
  109. return this.nzLabel || this.nzValue.toString();
  110. }
  111. /** Set active (only styles) */
  112. setActiveStyles() {
  113. if (!this.active) {
  114. this.active = true;
  115. this.changeDetectorRef.markForCheck();
  116. }
  117. }
  118. /** Unset active (only styles) */
  119. setInactiveStyles() {
  120. if (this.active) {
  121. this.active = false;
  122. this.changeDetectorRef.markForCheck();
  123. }
  124. }
  125. scrollIntoViewIfNeeded() {
  126. scrollIntoView(this.element.nativeElement);
  127. }
  128. selectViaInteraction() {
  129. if (!this.nzDisabled) {
  130. this.selected = !this.selected;
  131. if (this.selected) {
  132. this.setActiveStyles();
  133. }
  134. else {
  135. this.setInactiveStyles();
  136. }
  137. this.emitSelectionChangeEvent(true);
  138. this.changeDetectorRef.markForCheck();
  139. }
  140. }
  141. emitSelectionChangeEvent(isUserInput = false) {
  142. this.selectionChange.emit(new NzOptionSelectionChange(this, isUserInput));
  143. }
  144. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteOptionComponent, deps: [{ token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
  145. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "19.2.2", type: NzAutocompleteOptionComponent, isStandalone: true, selector: "nz-auto-option", inputs: { nzValue: "nzValue", nzLabel: "nzLabel", nzDisabled: ["nzDisabled", "nzDisabled", booleanAttribute] }, outputs: { selectionChange: "selectionChange", mouseEntered: "mouseEntered" }, host: { attributes: { "role": "menuitem" }, listeners: { "click": "selectViaInteraction()" }, properties: { "class.ant-select-item-option-grouped": "nzAutocompleteOptgroupComponent", "class.ant-select-item-option-selected": "selected", "class.ant-select-item-option-active": "active", "class.ant-select-item-option-disabled": "nzDisabled", "attr.aria-selected": "selected.toString()", "attr.aria-disabled": "nzDisabled.toString()" }, classAttribute: "ant-select-item ant-select-item-option" }, exportAs: ["nzAutoOption"], ngImport: i0, template: `
  146. <div class="ant-select-item-option-content">
  147. <ng-content></ng-content>
  148. </div>
  149. `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
  150. }
  151. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteOptionComponent, decorators: [{
  152. type: Component,
  153. args: [{
  154. selector: 'nz-auto-option',
  155. exportAs: 'nzAutoOption',
  156. preserveWhitespaces: false,
  157. changeDetection: ChangeDetectionStrategy.OnPush,
  158. encapsulation: ViewEncapsulation.None,
  159. template: `
  160. <div class="ant-select-item-option-content">
  161. <ng-content></ng-content>
  162. </div>
  163. `,
  164. host: {
  165. role: 'menuitem',
  166. class: 'ant-select-item ant-select-item-option',
  167. '[class.ant-select-item-option-grouped]': 'nzAutocompleteOptgroupComponent',
  168. '[class.ant-select-item-option-selected]': 'selected',
  169. '[class.ant-select-item-option-active]': 'active',
  170. '[class.ant-select-item-option-disabled]': 'nzDisabled',
  171. '[attr.aria-selected]': 'selected.toString()',
  172. '[attr.aria-disabled]': 'nzDisabled.toString()',
  173. '(click)': 'selectViaInteraction()'
  174. }
  175. }]
  176. }], ctorParameters: () => [{ type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { nzValue: [{
  177. type: Input
  178. }], nzLabel: [{
  179. type: Input
  180. }], nzDisabled: [{
  181. type: Input,
  182. args: [{ transform: booleanAttribute }]
  183. }], selectionChange: [{
  184. type: Output
  185. }], mouseEntered: [{
  186. type: Output
  187. }] } });
  188. /**
  189. * Use of this source code is governed by an MIT-style license that can be
  190. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  191. */
  192. const NZ_AUTOCOMPLETE_VALUE_ACCESSOR = {
  193. provide: NG_VALUE_ACCESSOR,
  194. useExisting: forwardRef(() => NzAutocompleteTriggerDirective),
  195. multi: true
  196. };
  197. function getNzAutocompleteMissingPanelError() {
  198. return Error('Attempting to open an undefined instance of `nz-autocomplete`. ' +
  199. 'Make sure that the id passed to the `nzAutocomplete` is correct and that ' +
  200. "you're attempting to open it after the ngAfterContentInit hook.");
  201. }
  202. class NzAutocompleteTriggerDirective {
  203. ngZone;
  204. elementRef;
  205. overlay;
  206. viewContainerRef;
  207. /** Bind nzAutocomplete component */
  208. nzAutocomplete;
  209. onChange = () => { };
  210. onTouched = () => { };
  211. panelOpen = false;
  212. /** Current active option */
  213. get activeOption() {
  214. if (this.nzAutocomplete && this.nzAutocomplete.options.length) {
  215. return this.nzAutocomplete.activeItem;
  216. }
  217. else {
  218. return null;
  219. }
  220. }
  221. destroy$ = new Subject();
  222. overlayRef = null;
  223. portal = null;
  224. positionStrategy;
  225. previousValue = null;
  226. selectionChangeSubscription;
  227. optionsChangeSubscription;
  228. overlayOutsideClickSubscription;
  229. document = inject(DOCUMENT);
  230. nzInputGroupWhitSuffixOrPrefixDirective = inject(NzInputGroupWhitSuffixOrPrefixDirective, { optional: true });
  231. constructor(ngZone, elementRef, overlay, viewContainerRef) {
  232. this.ngZone = ngZone;
  233. this.elementRef = elementRef;
  234. this.overlay = overlay;
  235. this.viewContainerRef = viewContainerRef;
  236. }
  237. ngAfterViewInit() {
  238. if (this.nzAutocomplete) {
  239. this.nzAutocomplete.animationStateChange.pipe(takeUntil(this.destroy$)).subscribe(event => {
  240. if (event.toState === 'void') {
  241. if (this.overlayRef) {
  242. this.overlayRef.dispose();
  243. this.overlayRef = null;
  244. }
  245. }
  246. });
  247. }
  248. }
  249. ngOnDestroy() {
  250. this.destroy$.next();
  251. this.destroy$.complete();
  252. this.destroyPanel();
  253. }
  254. writeValue(value) {
  255. this.ngZone.runOutsideAngular(() => Promise.resolve(null).then(() => this.setTriggerValue(value)));
  256. }
  257. registerOnChange(fn) {
  258. this.onChange = fn;
  259. }
  260. registerOnTouched(fn) {
  261. this.onTouched = fn;
  262. }
  263. setDisabledState(isDisabled) {
  264. const element = this.elementRef.nativeElement;
  265. element.disabled = isDisabled;
  266. this.closePanel();
  267. }
  268. openPanel() {
  269. this.previousValue = this.elementRef.nativeElement.value;
  270. this.attachOverlay();
  271. this.updateStatus();
  272. }
  273. closePanel() {
  274. if (this.panelOpen) {
  275. this.nzAutocomplete.isOpen = this.panelOpen = false;
  276. if (this.overlayRef && this.overlayRef.hasAttached()) {
  277. this.overlayRef.detach();
  278. this.selectionChangeSubscription.unsubscribe();
  279. this.overlayOutsideClickSubscription.unsubscribe();
  280. this.optionsChangeSubscription.unsubscribe();
  281. this.portal = null;
  282. }
  283. }
  284. }
  285. handleKeydown(event) {
  286. const keyCode = event.keyCode;
  287. const isArrowKey = keyCode === UP_ARROW || keyCode === DOWN_ARROW;
  288. if (keyCode === ESCAPE) {
  289. event.preventDefault();
  290. }
  291. if (this.panelOpen && (keyCode === ESCAPE || keyCode === TAB)) {
  292. // Reset value when tab / ESC close
  293. if (this.activeOption && this.activeOption.getLabel() !== this.previousValue) {
  294. this.setTriggerValue(this.previousValue);
  295. }
  296. this.closePanel();
  297. }
  298. else if (this.panelOpen && keyCode === ENTER) {
  299. if (this.nzAutocomplete.showPanel) {
  300. event.preventDefault();
  301. if (this.activeOption) {
  302. this.activeOption.selectViaInteraction();
  303. }
  304. else {
  305. this.closePanel();
  306. }
  307. }
  308. }
  309. else if (this.panelOpen && isArrowKey && this.nzAutocomplete.showPanel) {
  310. event.stopPropagation();
  311. event.preventDefault();
  312. if (keyCode === UP_ARROW) {
  313. this.nzAutocomplete.setPreviousItemActive();
  314. }
  315. else {
  316. this.nzAutocomplete.setNextItemActive();
  317. }
  318. if (this.activeOption) {
  319. this.activeOption.scrollIntoViewIfNeeded();
  320. }
  321. this.doBackfill();
  322. }
  323. }
  324. handleInput(event) {
  325. const target = event.target;
  326. const document = this.document;
  327. let value = target.value;
  328. if (target.type === 'number') {
  329. value = value === '' ? null : parseFloat(value);
  330. }
  331. if (this.previousValue !== value) {
  332. this.previousValue = value;
  333. this.onChange(value);
  334. if (this.canOpen() && document.activeElement === event.target) {
  335. this.openPanel();
  336. }
  337. }
  338. }
  339. handleFocus() {
  340. if (this.canOpen()) {
  341. this.openPanel();
  342. }
  343. }
  344. handleClick() {
  345. if (this.canOpen() && !this.panelOpen) {
  346. this.openPanel();
  347. }
  348. }
  349. handleBlur() {
  350. this.onTouched();
  351. }
  352. /**
  353. * Subscription data source changes event
  354. */
  355. subscribeOptionsChange() {
  356. const optionChanges = this.nzAutocomplete.options.changes.pipe(tap(() => this.positionStrategy.reapplyLastPosition()), delay(0));
  357. return optionChanges.subscribe(() => {
  358. this.resetActiveItem();
  359. if (this.panelOpen) {
  360. this.overlayRef.updatePosition();
  361. }
  362. });
  363. }
  364. /**
  365. * Subscription option changes event and set the value
  366. */
  367. subscribeSelectionChange() {
  368. return this.nzAutocomplete.selectionChange.subscribe((option) => {
  369. this.setValueAndClose(option);
  370. });
  371. }
  372. subscribeOverlayOutsideClick() {
  373. return this.overlayRef.outsidePointerEvents()
  374. .pipe(filter((e) => !this.elementRef.nativeElement.contains(e.target)))
  375. .subscribe(() => {
  376. this.closePanel();
  377. });
  378. }
  379. attachOverlay() {
  380. if (!this.nzAutocomplete) {
  381. throw getNzAutocompleteMissingPanelError();
  382. }
  383. if (!this.portal && this.nzAutocomplete.template) {
  384. this.portal = new TemplatePortal(this.nzAutocomplete.template, this.viewContainerRef);
  385. }
  386. if (!this.overlayRef) {
  387. this.overlayRef = this.overlay.create(this.getOverlayConfig());
  388. }
  389. if (this.overlayRef && !this.overlayRef.hasAttached()) {
  390. this.overlayRef.attach(this.portal);
  391. this.selectionChangeSubscription = this.subscribeSelectionChange();
  392. this.optionsChangeSubscription = this.subscribeOptionsChange();
  393. this.overlayOutsideClickSubscription = this.subscribeOverlayOutsideClick();
  394. this.overlayRef
  395. .detachments()
  396. .pipe(takeUntil(this.destroy$))
  397. .subscribe(() => {
  398. this.closePanel();
  399. });
  400. }
  401. this.nzAutocomplete.isOpen = this.panelOpen = true;
  402. }
  403. updateStatus() {
  404. if (this.overlayRef) {
  405. this.overlayRef.updateSize({ width: this.nzAutocomplete.nzWidth || this.getHostWidth() });
  406. }
  407. this.nzAutocomplete.setVisibility();
  408. this.resetActiveItem();
  409. if (this.activeOption) {
  410. this.activeOption.scrollIntoViewIfNeeded();
  411. }
  412. }
  413. destroyPanel() {
  414. if (this.overlayRef) {
  415. this.closePanel();
  416. }
  417. }
  418. getOverlayConfig() {
  419. return new OverlayConfig({
  420. positionStrategy: this.getOverlayPosition(),
  421. disposeOnNavigation: true,
  422. scrollStrategy: this.overlay.scrollStrategies.reposition(),
  423. // default host element width
  424. width: this.nzAutocomplete.nzWidth || this.getHostWidth()
  425. });
  426. }
  427. getConnectedElement() {
  428. return this.nzInputGroupWhitSuffixOrPrefixDirective
  429. ? this.nzInputGroupWhitSuffixOrPrefixDirective.elementRef
  430. : this.elementRef;
  431. }
  432. getHostWidth() {
  433. return this.getConnectedElement().nativeElement.getBoundingClientRect().width;
  434. }
  435. getOverlayPosition() {
  436. const positions = [
  437. new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' }),
  438. new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'bottom' })
  439. ];
  440. this.positionStrategy = this.overlay
  441. .position()
  442. .flexibleConnectedTo(this.getConnectedElement())
  443. .withFlexibleDimensions(false)
  444. .withPush(false)
  445. .withPositions(positions)
  446. .withTransformOriginOn('.ant-select-dropdown');
  447. return this.positionStrategy;
  448. }
  449. resetActiveItem() {
  450. const index = this.nzAutocomplete.getOptionIndex(this.previousValue);
  451. this.nzAutocomplete.clearSelectedOptions(null, true);
  452. if (index !== -1) {
  453. this.nzAutocomplete.setActiveItem(index);
  454. this.nzAutocomplete.activeItem.select(false);
  455. }
  456. else {
  457. this.nzAutocomplete.setActiveItem(this.nzAutocomplete.nzDefaultActiveFirstOption ? 0 : -1);
  458. }
  459. }
  460. setValueAndClose(option) {
  461. const value = option.nzValue;
  462. this.setTriggerValue(option.getLabel());
  463. this.onChange(value);
  464. this.elementRef.nativeElement.focus();
  465. this.closePanel();
  466. }
  467. setTriggerValue(value) {
  468. const option = this.nzAutocomplete.getOption(value);
  469. const displayValue = option ? option.getLabel() : value;
  470. this.elementRef.nativeElement.value = displayValue != null ? displayValue : '';
  471. if (!this.nzAutocomplete.nzBackfill) {
  472. this.previousValue = displayValue;
  473. }
  474. }
  475. doBackfill() {
  476. if (this.nzAutocomplete.nzBackfill && this.nzAutocomplete.activeItem) {
  477. this.setTriggerValue(this.nzAutocomplete.activeItem.getLabel());
  478. }
  479. }
  480. canOpen() {
  481. const element = this.elementRef.nativeElement;
  482. return !element.readOnly && !element.disabled;
  483. }
  484. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteTriggerDirective, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }, { token: i1$1.Overlay }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
  485. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.2", type: NzAutocompleteTriggerDirective, isStandalone: true, selector: "input[nzAutocomplete], textarea[nzAutocomplete]", inputs: { nzAutocomplete: "nzAutocomplete" }, host: { attributes: { "autocomplete": "off", "aria-autocomplete": "list" }, listeners: { "focusin": "handleFocus()", "blur": "handleBlur()", "input": "handleInput($event)", "keydown": "handleKeydown($event)", "click": "handleClick($event)" } }, providers: [NZ_AUTOCOMPLETE_VALUE_ACCESSOR], exportAs: ["nzAutocompleteTrigger"], ngImport: i0 });
  486. }
  487. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteTriggerDirective, decorators: [{
  488. type: Directive,
  489. args: [{
  490. selector: `input[nzAutocomplete], textarea[nzAutocomplete]`,
  491. exportAs: 'nzAutocompleteTrigger',
  492. providers: [NZ_AUTOCOMPLETE_VALUE_ACCESSOR],
  493. host: {
  494. autocomplete: 'off',
  495. 'aria-autocomplete': 'list',
  496. '(focusin)': 'handleFocus()',
  497. '(blur)': 'handleBlur()',
  498. '(input)': 'handleInput($event)',
  499. '(keydown)': 'handleKeydown($event)',
  500. '(click)': 'handleClick($event)'
  501. }
  502. }]
  503. }], ctorParameters: () => [{ type: i0.NgZone }, { type: i0.ElementRef }, { type: i1$1.Overlay }, { type: i0.ViewContainerRef }], propDecorators: { nzAutocomplete: [{
  504. type: Input
  505. }] } });
  506. function normalizeDataSource(value) {
  507. return value?.map(item => {
  508. if (typeof item === 'number' || typeof item === 'string') {
  509. return {
  510. label: item.toString(),
  511. value: item.toString()
  512. };
  513. }
  514. return item;
  515. });
  516. }
  517. class NzAutocompleteComponent {
  518. changeDetectorRef;
  519. directionality;
  520. nzWidth;
  521. nzOverlayClassName = '';
  522. nzOverlayStyle = {};
  523. nzDefaultActiveFirstOption = true;
  524. nzBackfill = false;
  525. compareWith = (o1, o2) => o1 === o2;
  526. nzDataSource;
  527. selectionChange = new EventEmitter();
  528. showPanel = true;
  529. isOpen = false;
  530. activeItem = null;
  531. dir = 'ltr';
  532. normalizedDataSource = [];
  533. destroy$ = new Subject();
  534. animationStateChange = new EventEmitter();
  535. /**
  536. * Options accessor, its source may be content or dataSource
  537. */
  538. get options() {
  539. // first dataSource
  540. if (this.nzDataSource) {
  541. return this.fromDataSourceOptions;
  542. }
  543. else {
  544. return this.fromContentOptions;
  545. }
  546. }
  547. /** Provided by content */
  548. fromContentOptions;
  549. /** Provided by dataSource */
  550. fromDataSourceOptions;
  551. /** cdk-overlay */
  552. template;
  553. panel;
  554. content;
  555. activeItemIndex = -1;
  556. selectionChangeSubscription = Subscription.EMPTY;
  557. optionMouseEnterSubscription = Subscription.EMPTY;
  558. dataSourceChangeSubscription = Subscription.EMPTY;
  559. /** Options changes listener */
  560. optionSelectionChanges = defer(() => {
  561. if (this.options) {
  562. return merge(...this.options.map(option => option.selectionChange));
  563. }
  564. return this.afterNextRender$.pipe(switchMap(() => this.optionSelectionChanges));
  565. });
  566. optionMouseEnter = defer(() => {
  567. if (this.options) {
  568. return merge(...this.options.map(option => option.mouseEntered));
  569. }
  570. return this.afterNextRender$.pipe(switchMap(() => this.optionMouseEnter));
  571. });
  572. afterNextRender$ = inject(NZ_AFTER_NEXT_RENDER$);
  573. noAnimation = inject(NzNoAnimationDirective, { host: true, optional: true });
  574. constructor(changeDetectorRef, directionality) {
  575. this.changeDetectorRef = changeDetectorRef;
  576. this.directionality = directionality;
  577. }
  578. ngOnInit() {
  579. this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction) => {
  580. this.dir = direction;
  581. this.changeDetectorRef.detectChanges();
  582. });
  583. this.dir = this.directionality.value;
  584. }
  585. ngOnChanges(changes) {
  586. const { nzDataSource } = changes;
  587. if (nzDataSource) {
  588. this.normalizedDataSource = normalizeDataSource(nzDataSource.currentValue);
  589. }
  590. }
  591. onAnimationEvent(event) {
  592. this.animationStateChange.emit(event);
  593. }
  594. ngAfterContentInit() {
  595. if (!this.nzDataSource) {
  596. this.optionsInit();
  597. }
  598. }
  599. ngAfterViewInit() {
  600. if (this.nzDataSource) {
  601. this.optionsInit();
  602. }
  603. }
  604. ngOnDestroy() {
  605. this.dataSourceChangeSubscription.unsubscribe();
  606. this.selectionChangeSubscription.unsubscribe();
  607. this.optionMouseEnterSubscription.unsubscribe();
  608. // Caretaker note: we have to set these subscriptions to `null` since these will be closed subscriptions, but they
  609. // still keep references to destinations (which are `SafeSubscriber`s). Destinations keep referencing `next` functions,
  610. // which we pass, for instance, to `this.optionSelectionChanges.subscribe(...)`.
  611. this.dataSourceChangeSubscription = this.selectionChangeSubscription = this.optionMouseEnterSubscription = null;
  612. this.destroy$.next();
  613. this.destroy$.complete();
  614. }
  615. setVisibility() {
  616. this.showPanel = !!this.options.length;
  617. this.changeDetectorRef.markForCheck();
  618. }
  619. setActiveItem(index) {
  620. const activeItem = this.options.get(index);
  621. if (activeItem && !activeItem.active) {
  622. this.activeItem = activeItem;
  623. this.activeItemIndex = index;
  624. this.clearSelectedOptions(this.activeItem);
  625. this.activeItem.setActiveStyles();
  626. }
  627. else {
  628. this.activeItem = null;
  629. this.activeItemIndex = -1;
  630. this.clearSelectedOptions();
  631. }
  632. this.changeDetectorRef.markForCheck();
  633. }
  634. setNextItemActive() {
  635. const nextIndex = this.activeItemIndex + 1 <= this.options.length - 1 ? this.activeItemIndex + 1 : 0;
  636. this.setActiveItem(nextIndex);
  637. }
  638. setPreviousItemActive() {
  639. const previousIndex = this.activeItemIndex - 1 < 0 ? this.options.length - 1 : this.activeItemIndex - 1;
  640. this.setActiveItem(previousIndex);
  641. }
  642. getOptionIndex(value) {
  643. return this.options.reduce((result, current, index) => result === -1 ? (this.compareWith(value, current.nzValue) ? index : -1) : result, -1);
  644. }
  645. getOption(value) {
  646. return this.options.find(item => this.compareWith(value, item.nzValue)) || null;
  647. }
  648. optionsInit() {
  649. this.setVisibility();
  650. this.subscribeOptionChanges();
  651. const changes = this.nzDataSource ? this.fromDataSourceOptions.changes : this.fromContentOptions.changes;
  652. // async
  653. this.dataSourceChangeSubscription = changes.subscribe(e => {
  654. if (!e.dirty && this.isOpen) {
  655. setTimeout(() => this.setVisibility());
  656. }
  657. this.subscribeOptionChanges();
  658. });
  659. }
  660. /**
  661. * Clear the status of options
  662. */
  663. clearSelectedOptions(skip, deselect = false) {
  664. this.options.forEach(option => {
  665. if (option !== skip) {
  666. if (deselect) {
  667. option.deselect();
  668. }
  669. option.setInactiveStyles();
  670. }
  671. });
  672. }
  673. subscribeOptionChanges() {
  674. this.selectionChangeSubscription.unsubscribe();
  675. this.selectionChangeSubscription = this.optionSelectionChanges
  676. .pipe(filter((event) => event.isUserInput))
  677. .subscribe((event) => {
  678. event.source.select();
  679. event.source.setActiveStyles();
  680. this.activeItem = event.source;
  681. this.activeItemIndex = this.getOptionIndex(this.activeItem.nzValue);
  682. this.clearSelectedOptions(event.source, true);
  683. this.selectionChange.emit(event.source);
  684. });
  685. this.optionMouseEnterSubscription.unsubscribe();
  686. this.optionMouseEnterSubscription = this.optionMouseEnter.subscribe((event) => {
  687. event.setActiveStyles();
  688. this.activeItem = event;
  689. this.activeItemIndex = this.getOptionIndex(this.activeItem.nzValue);
  690. this.clearSelectedOptions(event);
  691. });
  692. }
  693. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$2.Directionality }], target: i0.ɵɵFactoryTarget.Component });
  694. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.2", type: NzAutocompleteComponent, isStandalone: true, selector: "nz-autocomplete", inputs: { nzWidth: ["nzWidth", "nzWidth", numberAttributeWithZeroFallback], nzOverlayClassName: "nzOverlayClassName", nzOverlayStyle: "nzOverlayStyle", nzDefaultActiveFirstOption: ["nzDefaultActiveFirstOption", "nzDefaultActiveFirstOption", booleanAttribute], nzBackfill: ["nzBackfill", "nzBackfill", booleanAttribute], compareWith: "compareWith", nzDataSource: "nzDataSource" }, outputs: { selectionChange: "selectionChange" }, queries: [{ propertyName: "fromContentOptions", predicate: NzAutocompleteOptionComponent, descendants: true }], viewQueries: [{ propertyName: "template", first: true, predicate: TemplateRef, descendants: true }, { propertyName: "panel", first: true, predicate: ["panel"], descendants: true }, { propertyName: "content", first: true, predicate: ["content"], descendants: true }, { propertyName: "fromDataSourceOptions", predicate: NzAutocompleteOptionComponent, descendants: true }], exportAs: ["nzAutocomplete"], usesOnChanges: true, ngImport: i0, template: `
  695. <ng-template>
  696. <div
  697. #panel
  698. class="ant-select-dropdown ant-select-dropdown-placement-bottomLeft"
  699. [class.ant-select-dropdown-hidden]="!showPanel"
  700. [class.ant-select-dropdown-rtl]="dir === 'rtl'"
  701. [class]="nzOverlayClassName"
  702. [style]="nzOverlayStyle"
  703. [nzNoAnimation]="noAnimation?.nzNoAnimation"
  704. @slideMotion
  705. (@slideMotion.done)="onAnimationEvent($event)"
  706. [@.disabled]="!!noAnimation?.nzNoAnimation"
  707. >
  708. <div class="ant-select-dropdown-content-wrapper">
  709. <div class="ant-select-dropdown-content">
  710. <ng-template *ngTemplateOutlet="nzDataSource ? optionsTemplate : contentTemplate"></ng-template>
  711. </div>
  712. </div>
  713. </div>
  714. <ng-template #contentTemplate>
  715. <ng-content></ng-content>
  716. </ng-template>
  717. <ng-template #optionsTemplate>
  718. @for (option of normalizedDataSource; track option.value) {
  719. <nz-auto-option [nzValue]="option.value" [nzLabel]="option.label">
  720. {{ option.label }}
  721. </nz-auto-option>
  722. }
  723. </ng-template>
  724. </ng-template>
  725. `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NzAutocompleteOptionComponent, selector: "nz-auto-option", inputs: ["nzValue", "nzLabel", "nzDisabled"], outputs: ["selectionChange", "mouseEntered"], exportAs: ["nzAutoOption"] }, { kind: "directive", type: NzNoAnimationDirective, selector: "[nzNoAnimation]", inputs: ["nzNoAnimation"], exportAs: ["nzNoAnimation"] }], animations: [slideMotion], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
  726. }
  727. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteComponent, decorators: [{
  728. type: Component,
  729. args: [{
  730. selector: 'nz-autocomplete',
  731. exportAs: 'nzAutocomplete',
  732. preserveWhitespaces: false,
  733. changeDetection: ChangeDetectionStrategy.OnPush,
  734. encapsulation: ViewEncapsulation.None,
  735. imports: [NgTemplateOutlet, NzAutocompleteOptionComponent, NzNoAnimationDirective],
  736. template: `
  737. <ng-template>
  738. <div
  739. #panel
  740. class="ant-select-dropdown ant-select-dropdown-placement-bottomLeft"
  741. [class.ant-select-dropdown-hidden]="!showPanel"
  742. [class.ant-select-dropdown-rtl]="dir === 'rtl'"
  743. [class]="nzOverlayClassName"
  744. [style]="nzOverlayStyle"
  745. [nzNoAnimation]="noAnimation?.nzNoAnimation"
  746. @slideMotion
  747. (@slideMotion.done)="onAnimationEvent($event)"
  748. [@.disabled]="!!noAnimation?.nzNoAnimation"
  749. >
  750. <div class="ant-select-dropdown-content-wrapper">
  751. <div class="ant-select-dropdown-content">
  752. <ng-template *ngTemplateOutlet="nzDataSource ? optionsTemplate : contentTemplate"></ng-template>
  753. </div>
  754. </div>
  755. </div>
  756. <ng-template #contentTemplate>
  757. <ng-content></ng-content>
  758. </ng-template>
  759. <ng-template #optionsTemplate>
  760. @for (option of normalizedDataSource; track option.value) {
  761. <nz-auto-option [nzValue]="option.value" [nzLabel]="option.label">
  762. {{ option.label }}
  763. </nz-auto-option>
  764. }
  765. </ng-template>
  766. </ng-template>
  767. `,
  768. animations: [slideMotion]
  769. }]
  770. }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1$2.Directionality }], propDecorators: { nzWidth: [{
  771. type: Input,
  772. args: [{ transform: numberAttributeWithZeroFallback }]
  773. }], nzOverlayClassName: [{
  774. type: Input
  775. }], nzOverlayStyle: [{
  776. type: Input
  777. }], nzDefaultActiveFirstOption: [{
  778. type: Input,
  779. args: [{ transform: booleanAttribute }]
  780. }], nzBackfill: [{
  781. type: Input,
  782. args: [{ transform: booleanAttribute }]
  783. }], compareWith: [{
  784. type: Input
  785. }], nzDataSource: [{
  786. type: Input
  787. }], selectionChange: [{
  788. type: Output
  789. }], fromContentOptions: [{
  790. type: ContentChildren,
  791. args: [NzAutocompleteOptionComponent, { descendants: true }]
  792. }], fromDataSourceOptions: [{
  793. type: ViewChildren,
  794. args: [NzAutocompleteOptionComponent]
  795. }], template: [{
  796. type: ViewChild,
  797. args: [TemplateRef, { static: false }]
  798. }], panel: [{
  799. type: ViewChild,
  800. args: ['panel', { static: false }]
  801. }], content: [{
  802. type: ViewChild,
  803. args: ['content', { static: false }]
  804. }] } });
  805. /**
  806. * Use of this source code is governed by an MIT-style license that can be
  807. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  808. */
  809. class NzAutocompleteModule {
  810. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
  811. static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteModule, imports: [NzAutocompleteComponent,
  812. NzAutocompleteOptionComponent,
  813. NzAutocompleteTriggerDirective,
  814. NzAutocompleteOptgroupComponent], exports: [NzAutocompleteComponent,
  815. NzAutocompleteOptionComponent,
  816. NzAutocompleteTriggerDirective,
  817. NzAutocompleteOptgroupComponent] });
  818. static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteModule, imports: [NzAutocompleteOptgroupComponent] });
  819. }
  820. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzAutocompleteModule, decorators: [{
  821. type: NgModule,
  822. args: [{
  823. exports: [
  824. NzAutocompleteComponent,
  825. NzAutocompleteOptionComponent,
  826. NzAutocompleteTriggerDirective,
  827. NzAutocompleteOptgroupComponent
  828. ],
  829. imports: [
  830. NzAutocompleteComponent,
  831. NzAutocompleteOptionComponent,
  832. NzAutocompleteTriggerDirective,
  833. NzAutocompleteOptgroupComponent
  834. ]
  835. }]
  836. }] });
  837. /**
  838. * Use of this source code is governed by an MIT-style license that can be
  839. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  840. */
  841. /**
  842. * Generated bundle index. Do not edit.
  843. */
  844. export { NZ_AUTOCOMPLETE_VALUE_ACCESSOR, NzAutocompleteComponent, NzAutocompleteModule, NzAutocompleteOptgroupComponent, NzAutocompleteOptionComponent, NzAutocompleteTriggerDirective, NzOptionSelectionChange, getNzAutocompleteMissingPanelError };
  845. //# sourceMappingURL=ng-zorro-antd-auto-complete.mjs.map