ng-zorro-antd-mention.mjs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. import * as i0 from '@angular/core';
  2. import { Directive, Injectable, forwardRef, EventEmitter, Output, inject, TemplateRef, ElementRef, booleanAttribute, ContentChild, ViewChildren, ViewChild, Input, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';
  3. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  4. import { takeUntil, distinctUntilChanged, withLatestFrom, map, startWith, switchMap } from 'rxjs/operators';
  5. import * as i1 from 'ng-zorro-antd/core/services';
  6. import { NzDestroyService } from 'ng-zorro-antd/core/services';
  7. import { fromEventOutsideAngular, getMentions, getCaretCoordinates, getStatusClassNames } from 'ng-zorro-antd/core/util';
  8. import { Subject, of, merge, Subscription } from 'rxjs';
  9. import { ENTER, LEFT_ARROW, RIGHT_ARROW, TAB, ESCAPE, UP_ARROW, DOWN_ARROW } from '@angular/cdk/keycodes';
  10. import * as i2 from '@angular/cdk/overlay';
  11. import { OverlayConfig, ConnectionPositionPair } from '@angular/cdk/overlay';
  12. import { TemplatePortal } from '@angular/cdk/portal';
  13. import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
  14. import { NzFormStatusService, NzFormNoStatusService, NzFormItemFeedbackIconComponent } from 'ng-zorro-antd/core/form';
  15. import { DEFAULT_MENTION_BOTTOM_POSITIONS, DEFAULT_MENTION_TOP_POSITIONS } from 'ng-zorro-antd/core/overlay';
  16. import * as i6 from 'ng-zorro-antd/empty';
  17. import { NzEmptyModule } from 'ng-zorro-antd/empty';
  18. import * as i5 from 'ng-zorro-antd/icon';
  19. import { NzIconModule } from 'ng-zorro-antd/icon';
  20. import * as i1$1 from '@angular/cdk/bidi';
  21. /**
  22. * Use of this source code is governed by an MIT-style license that can be
  23. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  24. */
  25. class NzMentionSuggestionDirective {
  26. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionSuggestionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
  27. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.2", type: NzMentionSuggestionDirective, isStandalone: true, selector: "[nzMentionSuggestion]", exportAs: ["nzMentionSuggestion"], ngImport: i0 });
  28. }
  29. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionSuggestionDirective, decorators: [{
  30. type: Directive,
  31. args: [{
  32. selector: '[nzMentionSuggestion]',
  33. exportAs: 'nzMentionSuggestion'
  34. }]
  35. }] });
  36. /**
  37. * Use of this source code is governed by an MIT-style license that can be
  38. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  39. */
  40. const NZ_MENTION_CONFIG = {
  41. split: ' '
  42. };
  43. /**
  44. * Use of this source code is governed by an MIT-style license that can be
  45. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  46. */
  47. class NzMentionService {
  48. trigger;
  49. triggerChange$ = new Subject();
  50. triggerChanged() {
  51. return this.triggerChange$.asObservable();
  52. }
  53. registerTrigger(trigger) {
  54. if (this.trigger !== trigger) {
  55. this.trigger = trigger;
  56. this.triggerChange$.next(trigger);
  57. }
  58. }
  59. ngOnDestroy() {
  60. this.triggerChange$.complete();
  61. }
  62. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  63. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionService });
  64. }
  65. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionService, decorators: [{
  66. type: Injectable
  67. }] });
  68. /**
  69. * Use of this source code is governed by an MIT-style license that can be
  70. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  71. */
  72. const NZ_MENTION_TRIGGER_ACCESSOR = {
  73. provide: NG_VALUE_ACCESSOR,
  74. useExisting: forwardRef(() => NzMentionTriggerDirective),
  75. multi: true
  76. };
  77. class NzMentionTriggerDirective {
  78. el;
  79. ngZone;
  80. ref;
  81. destroy$;
  82. nzMentionService;
  83. onChange = () => { };
  84. onTouched = () => { };
  85. // eslint-disable-next-line @angular-eslint/no-output-on-prefix
  86. onFocusin = new EventEmitter();
  87. // eslint-disable-next-line @angular-eslint/no-output-on-prefix
  88. onBlur = new EventEmitter();
  89. // eslint-disable-next-line @angular-eslint/no-output-on-prefix
  90. onInput = new EventEmitter();
  91. // eslint-disable-next-line @angular-eslint/no-output-on-prefix
  92. onKeydown = new EventEmitter();
  93. // eslint-disable-next-line @angular-eslint/no-output-on-prefix
  94. onClick = new EventEmitter();
  95. value;
  96. constructor(el, ngZone, ref, destroy$, nzMentionService) {
  97. this.el = el;
  98. this.ngZone = ngZone;
  99. this.ref = ref;
  100. this.destroy$ = destroy$;
  101. this.nzMentionService = nzMentionService;
  102. }
  103. completeEvents() {
  104. this.onFocusin.complete();
  105. this.onBlur.complete();
  106. this.onInput.complete();
  107. this.onKeydown.complete();
  108. this.onClick.complete();
  109. }
  110. focus(caretPos = null) {
  111. this.el.nativeElement.focus();
  112. this.el.nativeElement.setSelectionRange(caretPos, caretPos);
  113. }
  114. insertMention(mention) {
  115. const value = this.el.nativeElement.value;
  116. const insertValue = `${mention.mention}${NZ_MENTION_CONFIG.split}`;
  117. const newValue = [
  118. value.slice(0, mention.startPos + 1),
  119. insertValue,
  120. value.slice(mention.endPos, value.length)
  121. ].join('');
  122. this.el.nativeElement.value = newValue;
  123. this.focus(mention.startPos + insertValue.length + 1);
  124. this.onChange(newValue);
  125. this.value = newValue;
  126. }
  127. writeValue(value) {
  128. this.value = value;
  129. if (typeof value === 'string') {
  130. this.el.nativeElement.value = value;
  131. }
  132. else {
  133. this.el.nativeElement.value = '';
  134. }
  135. }
  136. registerOnChange(fn) {
  137. this.onChange = fn;
  138. }
  139. registerOnTouched(fn) {
  140. this.onTouched = fn;
  141. }
  142. ngAfterViewInit() {
  143. this.nzMentionService.registerTrigger(this);
  144. this.setupEventListener('blur', this.onBlur);
  145. this.setupEventListener('focusin', this.onFocusin);
  146. this.setupEventListener('input', this.onInput);
  147. this.setupEventListener('click', this.onClick);
  148. this.setupEventListener('keydown', this.onKeydown);
  149. }
  150. ngOnDestroy() {
  151. this.completeEvents();
  152. }
  153. setupEventListener(eventName, eventEmitter) {
  154. fromEventOutsideAngular(this.el.nativeElement, eventName)
  155. .pipe(takeUntil(this.destroy$))
  156. .subscribe(event => {
  157. if (eventEmitter.observers.length) {
  158. this.ngZone.run(() => {
  159. eventEmitter.emit(event);
  160. this.ref.markForCheck();
  161. });
  162. }
  163. });
  164. }
  165. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionTriggerDirective, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i1.NzDestroyService }, { token: NzMentionService }], target: i0.ɵɵFactoryTarget.Directive });
  166. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.2", type: NzMentionTriggerDirective, isStandalone: true, selector: "input[nzMentionTrigger], textarea[nzMentionTrigger]", outputs: { onFocusin: "onFocusin", onBlur: "onBlur", onInput: "onInput", onKeydown: "onKeydown", onClick: "onClick" }, host: { attributes: { "autocomplete": "off" } }, providers: [NzDestroyService, NZ_MENTION_TRIGGER_ACCESSOR], exportAs: ["nzMentionTrigger"], ngImport: i0 });
  167. }
  168. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionTriggerDirective, decorators: [{
  169. type: Directive,
  170. args: [{
  171. selector: 'input[nzMentionTrigger], textarea[nzMentionTrigger]',
  172. exportAs: 'nzMentionTrigger',
  173. providers: [NzDestroyService, NZ_MENTION_TRIGGER_ACCESSOR],
  174. host: {
  175. autocomplete: 'off'
  176. }
  177. }]
  178. }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i1.NzDestroyService }, { type: NzMentionService }], propDecorators: { onFocusin: [{
  179. type: Output
  180. }], onBlur: [{
  181. type: Output
  182. }], onInput: [{
  183. type: Output
  184. }], onKeydown: [{
  185. type: Output
  186. }], onClick: [{
  187. type: Output
  188. }] } });
  189. class NzMentionComponent {
  190. ngZone;
  191. directionality;
  192. cdr;
  193. overlay;
  194. viewContainerRef;
  195. elementRef;
  196. renderer;
  197. nzMentionService;
  198. destroy$;
  199. nzValueWith = value => value;
  200. nzPrefix = '@';
  201. nzLoading = false;
  202. nzNotFoundContent = '无匹配结果,轻敲空格完成输入';
  203. nzPlacement = 'bottom';
  204. nzSuggestions = [];
  205. nzStatus = '';
  206. nzOnSelect = new EventEmitter();
  207. nzOnSearchChange = new EventEmitter();
  208. trigger;
  209. suggestionsTemp;
  210. items;
  211. set suggestionChild(value) {
  212. if (value) {
  213. this.suggestionTemplate = value;
  214. }
  215. }
  216. isOpen = false;
  217. filteredSuggestions = [];
  218. suggestionTemplate = null;
  219. activeIndex = -1;
  220. dir = 'ltr';
  221. // status
  222. prefixCls = 'ant-mentions';
  223. statusCls = {};
  224. status = '';
  225. hasFeedback = false;
  226. previousValue = null;
  227. cursorMention = null;
  228. cursorMentionStart;
  229. cursorMentionEnd;
  230. overlayRef = null;
  231. portal;
  232. positionStrategy;
  233. overlayOutsideClickSubscription;
  234. document = inject(DOCUMENT);
  235. get triggerNativeElement() {
  236. return this.trigger.el.nativeElement;
  237. }
  238. get focusItemElement() {
  239. const itemArr = this.items?.toArray();
  240. if (itemArr && itemArr[this.activeIndex]) {
  241. return itemArr[this.activeIndex].nativeElement;
  242. }
  243. return null;
  244. }
  245. nzFormStatusService = inject(NzFormStatusService, { optional: true });
  246. nzFormNoStatusService = inject(NzFormNoStatusService, { optional: true });
  247. constructor(ngZone, directionality, cdr, overlay, viewContainerRef, elementRef, renderer, nzMentionService, destroy$) {
  248. this.ngZone = ngZone;
  249. this.directionality = directionality;
  250. this.cdr = cdr;
  251. this.overlay = overlay;
  252. this.viewContainerRef = viewContainerRef;
  253. this.elementRef = elementRef;
  254. this.renderer = renderer;
  255. this.nzMentionService = nzMentionService;
  256. this.destroy$ = destroy$;
  257. }
  258. ngOnInit() {
  259. this.nzFormStatusService?.formStatusChanges
  260. .pipe(distinctUntilChanged((pre, cur) => {
  261. return pre.status === cur.status && pre.hasFeedback === cur.hasFeedback;
  262. }), withLatestFrom(this.nzFormNoStatusService ? this.nzFormNoStatusService.noFormStatus : of(false)), map(([{ status, hasFeedback }, noStatus]) => ({ status: noStatus ? '' : status, hasFeedback })), takeUntil(this.destroy$))
  263. .subscribe(({ status, hasFeedback }) => {
  264. this.setStatusStyles(status, hasFeedback);
  265. });
  266. this.nzMentionService.triggerChanged().subscribe(trigger => {
  267. this.trigger = trigger;
  268. this.bindTriggerEvents();
  269. this.closeDropdown();
  270. this.overlayRef = null;
  271. });
  272. this.dir = this.directionality.value;
  273. this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction) => {
  274. this.dir = direction;
  275. });
  276. }
  277. ngOnChanges(changes) {
  278. const { nzSuggestions, nzStatus } = changes;
  279. if (nzSuggestions) {
  280. if (this.isOpen) {
  281. this.previousValue = null;
  282. this.activeIndex = -1;
  283. this.resetDropdown(false);
  284. }
  285. }
  286. if (nzStatus) {
  287. this.setStatusStyles(this.nzStatus, this.hasFeedback);
  288. }
  289. }
  290. ngAfterViewInit() {
  291. this.items.changes
  292. .pipe(startWith(this.items), switchMap(() => {
  293. const items = this.items.toArray();
  294. return merge(...items.map(item => fromEventOutsideAngular(item.nativeElement, 'mousedown')));
  295. }))
  296. .subscribe(event => {
  297. event.preventDefault();
  298. });
  299. }
  300. ngOnDestroy() {
  301. this.closeDropdown();
  302. }
  303. closeDropdown() {
  304. if (this.overlayRef && this.overlayRef.hasAttached()) {
  305. this.overlayRef.detach();
  306. this.overlayOutsideClickSubscription.unsubscribe();
  307. this.isOpen = false;
  308. this.cdr.markForCheck();
  309. }
  310. }
  311. openDropdown() {
  312. this.attachOverlay();
  313. this.isOpen = true;
  314. this.cdr.markForCheck();
  315. }
  316. getMentions() {
  317. return this.trigger ? getMentions(this.trigger.value, this.nzPrefix) : [];
  318. }
  319. selectSuggestion(suggestion) {
  320. const value = this.nzValueWith(suggestion);
  321. this.trigger.insertMention({
  322. mention: value,
  323. startPos: this.cursorMentionStart,
  324. endPos: this.cursorMentionEnd
  325. });
  326. this.nzOnSelect.emit(suggestion);
  327. this.closeDropdown();
  328. this.activeIndex = -1;
  329. }
  330. handleInput(event) {
  331. const target = event.target;
  332. this.trigger.onChange(target.value);
  333. this.trigger.value = target.value;
  334. this.resetDropdown();
  335. }
  336. handleKeydown(event) {
  337. const keyCode = event.keyCode;
  338. if (this.isOpen && keyCode === ENTER && this.activeIndex !== -1 && this.filteredSuggestions.length) {
  339. this.selectSuggestion(this.filteredSuggestions[this.activeIndex]);
  340. event.preventDefault();
  341. }
  342. else if (keyCode === LEFT_ARROW || keyCode === RIGHT_ARROW) {
  343. this.resetDropdown();
  344. event.stopPropagation();
  345. }
  346. else {
  347. if (this.isOpen && (keyCode === TAB || keyCode === ESCAPE)) {
  348. this.closeDropdown();
  349. return;
  350. }
  351. if (this.isOpen && keyCode === UP_ARROW) {
  352. this.setPreviousItemActive();
  353. event.preventDefault();
  354. event.stopPropagation();
  355. }
  356. if (this.isOpen && keyCode === DOWN_ARROW) {
  357. this.setNextItemActive();
  358. event.preventDefault();
  359. event.stopPropagation();
  360. }
  361. }
  362. }
  363. handleClick() {
  364. this.resetDropdown();
  365. }
  366. bindTriggerEvents() {
  367. this.trigger.onInput.subscribe((e) => this.handleInput(e));
  368. this.trigger.onKeydown.subscribe((e) => this.handleKeydown(e));
  369. this.trigger.onClick.subscribe(() => this.handleClick());
  370. }
  371. suggestionsFilter(value, emit) {
  372. const suggestions = value.substring(1);
  373. /**
  374. * Should always emit (nzOnSearchChange) when value empty
  375. *
  376. * @[something]... @[empty]... @[empty]
  377. * ^ ^ ^
  378. * preValue preValue (should emit)
  379. */
  380. if (this.previousValue === value && value !== this.cursorMention[0]) {
  381. return;
  382. }
  383. this.previousValue = value;
  384. if (emit) {
  385. this.nzOnSearchChange.emit({
  386. value: this.cursorMention.substring(1),
  387. prefix: this.cursorMention[0]
  388. });
  389. }
  390. const searchValue = suggestions.toLowerCase();
  391. this.filteredSuggestions = this.nzSuggestions.filter(suggestion => this.nzValueWith(suggestion).toLowerCase().includes(searchValue));
  392. }
  393. resetDropdown(emit = true) {
  394. this.resetCursorMention();
  395. if (typeof this.cursorMention !== 'string' || !this.canOpen()) {
  396. this.closeDropdown();
  397. return;
  398. }
  399. this.suggestionsFilter(this.cursorMention, emit);
  400. const activeIndex = this.filteredSuggestions.indexOf(this.cursorMention.substring(1));
  401. this.activeIndex = activeIndex >= 0 ? activeIndex : 0;
  402. this.openDropdown();
  403. }
  404. setNextItemActive() {
  405. this.activeIndex = this.activeIndex + 1 <= this.filteredSuggestions.length - 1 ? this.activeIndex + 1 : 0;
  406. this.cdr.markForCheck();
  407. this.scrollToFocusItem();
  408. }
  409. setPreviousItemActive() {
  410. this.activeIndex = this.activeIndex - 1 < 0 ? this.filteredSuggestions.length - 1 : this.activeIndex - 1;
  411. this.cdr.markForCheck();
  412. this.scrollToFocusItem();
  413. }
  414. scrollToFocusItem() {
  415. if (this.focusItemElement) {
  416. this.focusItemElement.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
  417. }
  418. }
  419. canOpen() {
  420. const element = this.triggerNativeElement;
  421. return !element.readOnly && !element.disabled;
  422. }
  423. resetCursorMention() {
  424. const value = this.triggerNativeElement.value.replace(/[\r\n]/g, NZ_MENTION_CONFIG.split) || '';
  425. const selectionStart = this.triggerNativeElement.selectionStart;
  426. const prefix = typeof this.nzPrefix === 'string' ? [this.nzPrefix] : this.nzPrefix;
  427. let i = prefix.length;
  428. while (i >= 0) {
  429. const startPos = value.lastIndexOf(prefix[i], selectionStart);
  430. const endPos = value.indexOf(NZ_MENTION_CONFIG.split, selectionStart) > -1
  431. ? value.indexOf(NZ_MENTION_CONFIG.split, selectionStart)
  432. : value.length;
  433. const mention = value.substring(startPos, endPos);
  434. if ((startPos > 0 && value[startPos - 1] !== NZ_MENTION_CONFIG.split) ||
  435. startPos < 0 ||
  436. mention.includes(prefix[i], 1) ||
  437. mention.includes(NZ_MENTION_CONFIG.split)) {
  438. this.cursorMention = null;
  439. this.cursorMentionStart = -1;
  440. this.cursorMentionEnd = -1;
  441. }
  442. else {
  443. this.cursorMention = mention;
  444. this.cursorMentionStart = startPos;
  445. this.cursorMentionEnd = endPos;
  446. return;
  447. }
  448. i--;
  449. }
  450. }
  451. updatePositions() {
  452. const coordinates = getCaretCoordinates(this.triggerNativeElement, this.cursorMentionStart);
  453. const top = coordinates.top -
  454. this.triggerNativeElement.getBoundingClientRect().height -
  455. this.triggerNativeElement.scrollTop +
  456. (this.nzPlacement === 'bottom' ? coordinates.height - 6 : -6);
  457. const left = coordinates.left - this.triggerNativeElement.scrollLeft;
  458. this.positionStrategy.withDefaultOffsetX(left).withDefaultOffsetY(top);
  459. if (this.nzPlacement === 'bottom') {
  460. this.positionStrategy.withPositions([...DEFAULT_MENTION_BOTTOM_POSITIONS]);
  461. }
  462. if (this.nzPlacement === 'top') {
  463. this.positionStrategy.withPositions([...DEFAULT_MENTION_TOP_POSITIONS]);
  464. }
  465. this.positionStrategy.apply();
  466. }
  467. subscribeOverlayOutsideClick() {
  468. const canCloseDropdown = (event) => {
  469. const clickTarget = event.target;
  470. return (this.isOpen &&
  471. clickTarget !== this.trigger.el.nativeElement &&
  472. !this.overlayRef?.overlayElement.contains(clickTarget));
  473. };
  474. const subscription = new Subscription();
  475. subscription.add(this.overlayRef.outsidePointerEvents().subscribe(event => canCloseDropdown(event) && this.closeDropdown()));
  476. subscription.add(fromEventOutsideAngular(this.document, 'touchend').subscribe(event => canCloseDropdown(event) && this.ngZone.run(() => this.closeDropdown())));
  477. return subscription;
  478. }
  479. attachOverlay() {
  480. if (!this.overlayRef) {
  481. this.portal = new TemplatePortal(this.suggestionsTemp, this.viewContainerRef);
  482. this.overlayRef = this.overlay.create(this.getOverlayConfig());
  483. }
  484. if (this.overlayRef && !this.overlayRef.hasAttached()) {
  485. this.overlayRef.attach(this.portal);
  486. this.overlayOutsideClickSubscription = this.subscribeOverlayOutsideClick();
  487. }
  488. this.updatePositions();
  489. }
  490. getOverlayConfig() {
  491. return new OverlayConfig({
  492. positionStrategy: this.getOverlayPosition(),
  493. scrollStrategy: this.overlay.scrollStrategies.reposition(),
  494. disposeOnNavigation: true
  495. });
  496. }
  497. getOverlayPosition() {
  498. const positions = [
  499. new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' }),
  500. new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'bottom' })
  501. ];
  502. this.positionStrategy = this.overlay
  503. .position()
  504. .flexibleConnectedTo(this.trigger.el)
  505. .withPositions(positions)
  506. .withFlexibleDimensions(false)
  507. .withPush(false);
  508. return this.positionStrategy;
  509. }
  510. setStatusStyles(status, hasFeedback) {
  511. // set inner status
  512. this.status = status;
  513. this.hasFeedback = hasFeedback;
  514. this.cdr.markForCheck();
  515. // render status if nzStatus is set
  516. this.statusCls = getStatusClassNames(this.prefixCls, status, hasFeedback);
  517. Object.keys(this.statusCls).forEach(status => {
  518. if (this.statusCls[status]) {
  519. this.renderer.addClass(this.elementRef.nativeElement, status);
  520. }
  521. else {
  522. this.renderer.removeClass(this.elementRef.nativeElement, status);
  523. }
  524. });
  525. }
  526. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionComponent, deps: [{ token: i0.NgZone }, { token: i1$1.Directionality }, { token: i0.ChangeDetectorRef }, { token: i2.Overlay }, { token: i0.ViewContainerRef }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: NzMentionService }, { token: i1.NzDestroyService }], target: i0.ɵɵFactoryTarget.Component });
  527. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.2", type: NzMentionComponent, isStandalone: true, selector: "nz-mention", inputs: { nzValueWith: "nzValueWith", nzPrefix: "nzPrefix", nzLoading: ["nzLoading", "nzLoading", booleanAttribute], nzNotFoundContent: "nzNotFoundContent", nzPlacement: "nzPlacement", nzSuggestions: "nzSuggestions", nzStatus: "nzStatus" }, outputs: { nzOnSelect: "nzOnSelect", nzOnSearchChange: "nzOnSearchChange" }, host: { properties: { "class.ant-mentions-rtl": "dir === 'rtl'" }, classAttribute: "ant-mentions" }, providers: [NzMentionService, NzDestroyService], queries: [{ propertyName: "suggestionChild", first: true, predicate: NzMentionSuggestionDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "suggestionsTemp", first: true, predicate: TemplateRef, descendants: true }, { propertyName: "items", predicate: ["items"], descendants: true, read: ElementRef }], exportAs: ["nzMention"], usesOnChanges: true, ngImport: i0, template: `
  528. <ng-content></ng-content>
  529. <ng-template #suggestions>
  530. <div class="ant-mentions-dropdown">
  531. <ul class="ant-mentions-dropdown-menu" role="menu" tabindex="0">
  532. @for (suggestion of filteredSuggestions; track suggestion) {
  533. <li
  534. #items
  535. class="ant-mentions-dropdown-menu-item"
  536. role="menuitem"
  537. tabindex="-1"
  538. [class.ant-mentions-dropdown-menu-item-active]="$index === activeIndex"
  539. [class.ant-mentions-dropdown-menu-item-selected]="$index === activeIndex"
  540. (click)="selectSuggestion(suggestion)"
  541. >
  542. @if (suggestionTemplate) {
  543. <ng-container *ngTemplateOutlet="suggestionTemplate; context: { $implicit: suggestion }" />
  544. } @else {
  545. {{ nzValueWith(suggestion) }}
  546. }
  547. </li>
  548. }
  549. @if (filteredSuggestions.length === 0) {
  550. <li class="ant-mentions-dropdown-menu-item ant-mentions-dropdown-menu-item-disabled">
  551. @if (nzLoading) {
  552. <span><nz-icon nzType="loading" /></span>
  553. } @else {
  554. <span>
  555. <nz-embed-empty nzComponentName="select" [specificContent]="nzNotFoundContent!" />
  556. </span>
  557. }
  558. </li>
  559. }
  560. </ul>
  561. </div>
  562. </ng-template>
  563. @if (hasFeedback && !!status) {
  564. <nz-form-item-feedback-icon class="ant-mentions-suffix" [status]="status" />
  565. }
  566. `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: NzIconModule }, { kind: "directive", type: i5.NzIconDirective, selector: "nz-icon,[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "ngmodule", type: NzEmptyModule }, { kind: "component", type: i6.NzEmbedEmptyComponent, selector: "nz-embed-empty", inputs: ["nzComponentName", "specificContent"], exportAs: ["nzEmbedEmpty"] }, { kind: "component", type: NzFormItemFeedbackIconComponent, selector: "nz-form-item-feedback-icon", inputs: ["status"], exportAs: ["nzFormFeedbackIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
  567. }
  568. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionComponent, decorators: [{
  569. type: Component,
  570. args: [{
  571. selector: 'nz-mention',
  572. exportAs: 'nzMention',
  573. template: `
  574. <ng-content></ng-content>
  575. <ng-template #suggestions>
  576. <div class="ant-mentions-dropdown">
  577. <ul class="ant-mentions-dropdown-menu" role="menu" tabindex="0">
  578. @for (suggestion of filteredSuggestions; track suggestion) {
  579. <li
  580. #items
  581. class="ant-mentions-dropdown-menu-item"
  582. role="menuitem"
  583. tabindex="-1"
  584. [class.ant-mentions-dropdown-menu-item-active]="$index === activeIndex"
  585. [class.ant-mentions-dropdown-menu-item-selected]="$index === activeIndex"
  586. (click)="selectSuggestion(suggestion)"
  587. >
  588. @if (suggestionTemplate) {
  589. <ng-container *ngTemplateOutlet="suggestionTemplate; context: { $implicit: suggestion }" />
  590. } @else {
  591. {{ nzValueWith(suggestion) }}
  592. }
  593. </li>
  594. }
  595. @if (filteredSuggestions.length === 0) {
  596. <li class="ant-mentions-dropdown-menu-item ant-mentions-dropdown-menu-item-disabled">
  597. @if (nzLoading) {
  598. <span><nz-icon nzType="loading" /></span>
  599. } @else {
  600. <span>
  601. <nz-embed-empty nzComponentName="select" [specificContent]="nzNotFoundContent!" />
  602. </span>
  603. }
  604. </li>
  605. }
  606. </ul>
  607. </div>
  608. </ng-template>
  609. @if (hasFeedback && !!status) {
  610. <nz-form-item-feedback-icon class="ant-mentions-suffix" [status]="status" />
  611. }
  612. `,
  613. preserveWhitespaces: false,
  614. changeDetection: ChangeDetectionStrategy.OnPush,
  615. providers: [NzMentionService, NzDestroyService],
  616. host: {
  617. class: 'ant-mentions',
  618. '[class.ant-mentions-rtl]': `dir === 'rtl'`
  619. },
  620. imports: [NgTemplateOutlet, NzIconModule, NzEmptyModule, NzFormItemFeedbackIconComponent]
  621. }]
  622. }], ctorParameters: () => [{ type: i0.NgZone }, { type: i1$1.Directionality }, { type: i0.ChangeDetectorRef }, { type: i2.Overlay }, { type: i0.ViewContainerRef }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: NzMentionService }, { type: i1.NzDestroyService }], propDecorators: { nzValueWith: [{
  623. type: Input
  624. }], nzPrefix: [{
  625. type: Input
  626. }], nzLoading: [{
  627. type: Input,
  628. args: [{ transform: booleanAttribute }]
  629. }], nzNotFoundContent: [{
  630. type: Input
  631. }], nzPlacement: [{
  632. type: Input
  633. }], nzSuggestions: [{
  634. type: Input
  635. }], nzStatus: [{
  636. type: Input
  637. }], nzOnSelect: [{
  638. type: Output
  639. }], nzOnSearchChange: [{
  640. type: Output
  641. }], suggestionsTemp: [{
  642. type: ViewChild,
  643. args: [TemplateRef, { static: false }]
  644. }], items: [{
  645. type: ViewChildren,
  646. args: ['items', { read: ElementRef }]
  647. }], suggestionChild: [{
  648. type: ContentChild,
  649. args: [NzMentionSuggestionDirective, { static: false, read: TemplateRef }]
  650. }] } });
  651. /**
  652. * Use of this source code is governed by an MIT-style license that can be
  653. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  654. */
  655. const COMPONENTS = [NzMentionComponent, NzMentionTriggerDirective, NzMentionSuggestionDirective];
  656. class NzMentionModule {
  657. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
  658. static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.2", ngImport: i0, type: NzMentionModule, imports: [NzMentionComponent, NzMentionTriggerDirective, NzMentionSuggestionDirective], exports: [NzMentionComponent, NzMentionTriggerDirective, NzMentionSuggestionDirective] });
  659. static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionModule, imports: [NzMentionComponent] });
  660. }
  661. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: NzMentionModule, decorators: [{
  662. type: NgModule,
  663. args: [{
  664. imports: [...COMPONENTS],
  665. exports: [...COMPONENTS]
  666. }]
  667. }] });
  668. /**
  669. * Use of this source code is governed by an MIT-style license that can be
  670. * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
  671. */
  672. /**
  673. * Generated bundle index. Do not edit.
  674. */
  675. export { NZ_MENTION_TRIGGER_ACCESSOR, NzMentionComponent, NzMentionModule, NzMentionService, NzMentionSuggestionDirective, NzMentionTriggerDirective };
  676. //# sourceMappingURL=ng-zorro-antd-mention.mjs.map