@taiga-ui/core 5.23.0 → 5.24.0-canary.51d7c08

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 (75) hide show
  1. package/classes/accessors.d.ts +6 -1
  2. package/components/cell/cell-stretch.directive.d.ts +1 -1
  3. package/components/data-list/option.directive.d.ts +1 -1
  4. package/components/textfield/select-like.directive.d.ts +2 -1
  5. package/components/textfield/textfield.component.d.ts +2 -0
  6. package/fesm2022/taiga-ui-core-classes.mjs +23 -7
  7. package/fesm2022/taiga-ui-core-classes.mjs.map +1 -1
  8. package/fesm2022/taiga-ui-core-components-button.mjs +2 -2
  9. package/fesm2022/taiga-ui-core-components-button.mjs.map +1 -1
  10. package/fesm2022/taiga-ui-core-components-calendar.mjs +1 -1
  11. package/fesm2022/taiga-ui-core-components-calendar.mjs.map +1 -1
  12. package/fesm2022/taiga-ui-core-components-cell.mjs +6 -9
  13. package/fesm2022/taiga-ui-core-components-cell.mjs.map +1 -1
  14. package/fesm2022/taiga-ui-core-components-checkbox.mjs +2 -2
  15. package/fesm2022/taiga-ui-core-components-checkbox.mjs.map +1 -1
  16. package/fesm2022/taiga-ui-core-components-data-list.mjs +7 -7
  17. package/fesm2022/taiga-ui-core-components-data-list.mjs.map +1 -1
  18. package/fesm2022/taiga-ui-core-components-icon.mjs +2 -2
  19. package/fesm2022/taiga-ui-core-components-icon.mjs.map +1 -1
  20. package/fesm2022/taiga-ui-core-components-input.mjs +2 -1
  21. package/fesm2022/taiga-ui-core-components-input.mjs.map +1 -1
  22. package/fesm2022/taiga-ui-core-components-label.mjs +3 -3
  23. package/fesm2022/taiga-ui-core-components-label.mjs.map +1 -1
  24. package/fesm2022/taiga-ui-core-components-link.mjs +2 -2
  25. package/fesm2022/taiga-ui-core-components-link.mjs.map +1 -1
  26. package/fesm2022/taiga-ui-core-components-notification.mjs +2 -2
  27. package/fesm2022/taiga-ui-core-components-notification.mjs.map +1 -1
  28. package/fesm2022/taiga-ui-core-components-radio.mjs +2 -2
  29. package/fesm2022/taiga-ui-core-components-radio.mjs.map +1 -1
  30. package/fesm2022/taiga-ui-core-components-root.mjs +1 -1
  31. package/fesm2022/taiga-ui-core-components-root.mjs.map +1 -1
  32. package/fesm2022/taiga-ui-core-components-scrollbar.mjs +5 -5
  33. package/fesm2022/taiga-ui-core-components-scrollbar.mjs.map +1 -1
  34. package/fesm2022/taiga-ui-core-components-textfield.mjs +25 -10
  35. package/fesm2022/taiga-ui-core-components-textfield.mjs.map +1 -1
  36. package/fesm2022/taiga-ui-core-components-title.mjs +3 -3
  37. package/fesm2022/taiga-ui-core-components-title.mjs.map +1 -1
  38. package/fesm2022/taiga-ui-core-directives-appearance.mjs +3 -3
  39. package/fesm2022/taiga-ui-core-directives-appearance.mjs.map +1 -1
  40. package/fesm2022/taiga-ui-core-directives-group.mjs +3 -3
  41. package/fesm2022/taiga-ui-core-directives-group.mjs.map +1 -1
  42. package/fesm2022/taiga-ui-core-directives-icons.mjs +3 -3
  43. package/fesm2022/taiga-ui-core-directives-icons.mjs.map +1 -1
  44. package/fesm2022/taiga-ui-core-portals-alert.mjs +3 -3
  45. package/fesm2022/taiga-ui-core-portals-alert.mjs.map +1 -1
  46. package/fesm2022/taiga-ui-core-portals-dialog.mjs +2 -2
  47. package/fesm2022/taiga-ui-core-portals-dialog.mjs.map +1 -1
  48. package/fesm2022/taiga-ui-core-portals-dropdown.mjs +191 -112
  49. package/fesm2022/taiga-ui-core-portals-dropdown.mjs.map +1 -1
  50. package/fesm2022/taiga-ui-core-portals-hint.mjs +171 -82
  51. package/fesm2022/taiga-ui-core-portals-hint.mjs.map +1 -1
  52. package/fesm2022/taiga-ui-core-portals-modal.mjs +3 -3
  53. package/fesm2022/taiga-ui-core-portals-modal.mjs.map +1 -1
  54. package/fesm2022/taiga-ui-core-tokens.mjs +4 -2
  55. package/fesm2022/taiga-ui-core-tokens.mjs.map +1 -1
  56. package/package.json +12 -12
  57. package/portals/dropdown/dropdown-anchor.directive.d.ts +6 -12
  58. package/portals/dropdown/dropdown-anchored.directive.d.ts +16 -0
  59. package/portals/dropdown/dropdown-context.directive.d.ts +5 -1
  60. package/portals/dropdown/dropdown-selection.directive.d.ts +5 -3
  61. package/portals/dropdown/dropdown.component.d.ts +2 -2
  62. package/portals/dropdown/dropdown.directive.d.ts +6 -4
  63. package/portals/dropdown/dropdown.providers.d.ts +1 -0
  64. package/portals/dropdown/index.d.ts +1 -0
  65. package/portals/hint/hint-anchor.directive.d.ts +12 -0
  66. package/portals/hint/hint-anchored.directive.d.ts +17 -0
  67. package/portals/hint/hint-host.directive.d.ts +4 -1
  68. package/portals/hint/hint-hover.directive.d.ts +1 -1
  69. package/portals/hint/hint-pointer.directive.d.ts +6 -1
  70. package/portals/hint/hint.component.d.ts +3 -10
  71. package/portals/hint/hint.d.ts +1 -2
  72. package/portals/hint/hint.directive.d.ts +5 -4
  73. package/portals/hint/index.d.ts +2 -0
  74. package/tokens/anchor-support.d.ts +2 -0
  75. package/tokens/index.d.ts +1 -0
@@ -1,27 +1,27 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Directive, inject, input, signal, INJECTOR, ChangeDetectionStrategy, Component, TemplateRef, forwardRef, computed } from '@angular/core';
3
- import { outputFromObservable, toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
- import { EMPTY_CLIENT_RECT } from '@taiga-ui/cdk/constants';
2
+ import { InjectionToken, ElementRef, Directive, inject, input, signal, INJECTOR, afterNextRender, ChangeDetectionStrategy, Component, TemplateRef, computed, effect } from '@angular/core';
5
3
  import * as i3 from '@taiga-ui/cdk/directives/active-zone';
6
4
  import { TuiActiveZone } from '@taiga-ui/cdk/directives/active-zone';
7
5
  import * as i2 from '@taiga-ui/cdk/directives/animated';
8
6
  import { TuiAnimated } from '@taiga-ui/cdk/directives/animated';
9
- import { TuiHoveredService } from '@taiga-ui/cdk/directives/hovered';
10
7
  import { tuiInjectElement, tuiPointToClientRect } from '@taiga-ui/cdk/utils/dom';
11
- import { tuiClamp } from '@taiga-ui/cdk/utils/math';
12
- import { tuiSetSignal, tuiPx, tuiIsPresent } from '@taiga-ui/cdk/utils/miscellaneous';
13
- import { TuiDriverDirective, TuiDriver, tuiAsDriver, TuiPositionAccessor, tuiFallbackAccessor, TuiRectAccessor, tuiAsVehicle, tuiAsRectAccessor, tuiPositionAccessorFor, tuiRectAccessorFor } from '@taiga-ui/core/classes';
8
+ import { TuiRectAccessor, tuiAsRectAccessor, TuiDriverDirective, TuiDriver, tuiAsDriver, TuiPositionAccessor, tuiInjectAccessor, tuiAsPositionAccessor, tuiAsVehicle, tuiProvideAccessor } from '@taiga-ui/core/classes';
14
9
  import { tuiButtonOptionsProvider } from '@taiga-ui/core/components/button';
15
10
  import * as i1 from '@taiga-ui/core/directives/appearance';
16
11
  import { tuiAppearance, TuiAppearance } from '@taiga-ui/core/directives/appearance';
17
- import { TuiPositionService, TuiVisualViewportService } from '@taiga-ui/core/services';
18
- import { TUI_VIEWPORT } from '@taiga-ui/core/tokens';
19
12
  import { tuiIsObscured } from '@taiga-ui/core/utils/miscellaneous';
20
13
  import { PolymorpheusComponent, PolymorpheusOutlet } from '@taiga-ui/polymorpheus';
21
- import { Subject, merge, switchMap, of, delay, takeUntil, repeat, filter, map, tap, distinctUntilChanged, skip, takeWhile, fromEvent, debounce, timer, startWith, BehaviorSubject } from 'rxjs';
14
+ import { outputFromObservable, toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
22
15
  import { TuiPopupService } from '@taiga-ui/core/portals/popup';
16
+ import { Subject, merge, switchMap, of, delay, takeUntil, repeat, filter, map, tap, distinctUntilChanged, skip, takeWhile, fromEvent, debounce, timer, startWith, BehaviorSubject } from 'rxjs';
17
+ import { tuiProvide, tuiCreateOptions } from '@taiga-ui/cdk/utils/di';
18
+ import { tuiGenerateId, tuiPx, tuiSetSignal, tuiIsPresent } from '@taiga-ui/cdk/utils/miscellaneous';
23
19
  import { WA_IS_MOBILE } from '@ng-web-apis/platform';
24
- import { tuiCreateOptions } from '@taiga-ui/cdk/utils/di';
20
+ import { TuiHoveredService } from '@taiga-ui/cdk/directives/hovered';
21
+ import { TUI_VIEWPORT } from '@taiga-ui/core/tokens';
22
+ import { EMPTY_CLIENT_RECT } from '@taiga-ui/cdk/constants';
23
+ import { tuiClamp } from '@taiga-ui/cdk/utils/math';
24
+ import { TuiVisualViewportService, TuiPositionService } from '@taiga-ui/core/services';
25
25
  import { DOCUMENT } from '@angular/common';
26
26
  import { tuiIfMap, tuiTypedFromEvent, tuiZoneOptimized } from '@taiga-ui/cdk/observables';
27
27
  import { tuiIsFocused } from '@taiga-ui/cdk/utils/focus';
@@ -31,6 +31,37 @@ import { tuiIsFocused } from '@taiga-ui/cdk/utils/focus';
31
31
  */
32
32
  const TUI_HINT_COMPONENT = new InjectionToken(ngDevMode ? 'TUI_HINT_COMPONENT' : '', { factory: () => TuiHintComponent });
33
33
 
34
+ const TUI_HINT_ANCHOR = new InjectionToken(ngDevMode ? 'TUI_HINT_ANCHOR' : '');
35
+ class TuiHintAnchor extends TuiRectAccessor {
36
+ constructor() {
37
+ super(...arguments);
38
+ this.el = tuiInjectElement();
39
+ this.anchor = `--${tuiGenerateId()}`;
40
+ this.type = 'hint';
41
+ }
42
+ getClientRect() {
43
+ return this.el.getBoundingClientRect();
44
+ }
45
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintAnchor, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
46
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.25", type: TuiHintAnchor, isStandalone: true, host: { properties: { "attr.data-tui-anchor": "anchor", "style.anchor-name": "anchor" } }, providers: [
47
+ tuiAsRectAccessor(TuiHintAnchor),
48
+ tuiProvide(TUI_HINT_ANCHOR, ElementRef),
49
+ ], usesInheritance: true, ngImport: i0 }); }
50
+ }
51
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintAnchor, decorators: [{
52
+ type: Directive,
53
+ args: [{
54
+ providers: [
55
+ tuiAsRectAccessor(TuiHintAnchor),
56
+ tuiProvide(TUI_HINT_ANCHOR, ElementRef),
57
+ ],
58
+ host: {
59
+ '[attr.data-tui-anchor]': 'anchor',
60
+ '[style.anchor-name]': 'anchor',
61
+ },
62
+ }]
63
+ }] });
64
+
34
65
  class TuiHintDriver extends TuiDriverDirective {
35
66
  constructor() {
36
67
  super(...arguments);
@@ -77,7 +108,6 @@ class TuiHintHover extends TuiDriver {
77
108
  constructor() {
78
109
  super((subscriber) => this.stream$.subscribe(subscriber));
79
110
  this.isMobile = inject(WA_IS_MOBILE);
80
- this.el = tuiInjectElement();
81
111
  this.hovered$ = inject(TuiHoveredService);
82
112
  this.options = inject(TUI_HINT_OPTIONS);
83
113
  this.visible = false;
@@ -94,6 +124,7 @@ class TuiHintHover extends TuiDriver {
94
124
  optional: true,
95
125
  skipSelf: true,
96
126
  });
127
+ this.el = tuiInjectElement();
97
128
  this.showDelay = input(this.options.showDelay, {
98
129
  alias: 'tuiHintShowDelay',
99
130
  });
@@ -142,7 +173,7 @@ class TuiHintPosition extends TuiPositionAccessor {
142
173
  this.viewport = inject(TUI_VIEWPORT);
143
174
  this.options = inject(TUI_HINT_OPTIONS);
144
175
  this.directionChange = new Subject();
145
- this.accessor = tuiFallbackAccessor('hint')(inject(TuiRectAccessor, { optional: true }), { getClientRect: () => this.el.getBoundingClientRect() });
176
+ this.accessor = tuiInjectAccessor(TuiRectAccessor, 'hint');
146
177
  this.points = TUI_HINT_DIRECTIONS.reduce((acc, direction) => ({ ...acc, [direction]: [0, 0] }), {});
147
178
  this.direction = input(this.options.direction, {
148
179
  alias: 'tuiHintDirection',
@@ -213,10 +244,11 @@ class TuiHintPosition extends TuiPositionAccessor {
213
244
  left + width < viewport.right - GAP$1);
214
245
  }
215
246
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintPosition, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
216
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.25", type: TuiHintPosition, isStandalone: true, inputs: { direction: { classPropertyName: "direction", publicName: "tuiHintDirection", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "tuiHintOffset", isSignal: true, isRequired: false, transformFunction: null }, centered: { classPropertyName: "centered", publicName: "tuiHintCentered", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { tuiHintDirectionChange: "tuiHintDirectionChange" }, usesInheritance: true, ngImport: i0 }); }
247
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.25", type: TuiHintPosition, isStandalone: true, inputs: { direction: { classPropertyName: "direction", publicName: "tuiHintDirection", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "tuiHintOffset", isSignal: true, isRequired: false, transformFunction: null }, centered: { classPropertyName: "centered", publicName: "tuiHintCentered", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { tuiHintDirectionChange: "tuiHintDirectionChange" }, providers: [tuiAsPositionAccessor(TuiHintPosition)], usesInheritance: true, ngImport: i0 }); }
217
248
  }
218
249
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintPosition, decorators: [{
219
- type: Directive
250
+ type: Directive,
251
+ args: [{ providers: [tuiAsPositionAccessor(TuiHintPosition)] }]
220
252
  }] });
221
253
  function adjust(direction, rtl) {
222
254
  if (rtl && direction.includes('left')) {
@@ -269,7 +301,7 @@ class TuiHintDirective {
269
301
  deps: [TUI_HINT_COMPONENT, INJECTOR],
270
302
  useClass: PolymorpheusComponent,
271
303
  },
272
- ], usesOnChanges: true, hostDirectives: [{ directive: TuiHintDriver }, { directive: TuiHintHover, inputs: ["tuiHintHideDelay", "tuiHintHideDelay", "tuiHintShowDelay", "tuiHintShowDelay"] }, { directive: TuiHintPosition, inputs: ["tuiHintDirection", "tuiHintDirection", "tuiHintCentered", "tuiHintCentered", "tuiHintOffset", "tuiHintOffset"], outputs: ["tuiHintDirectionChange", "tuiHintDirectionChange"] }], ngImport: i0 }); }
304
+ ], usesOnChanges: true, hostDirectives: [{ directive: TuiHintAnchor }, { directive: TuiHintDriver }, { directive: TuiHintHover, inputs: ["tuiHintHideDelay", "tuiHintHideDelay", "tuiHintShowDelay", "tuiHintShowDelay"] }, { directive: TuiHintPosition, inputs: ["tuiHintDirection", "tuiHintDirection", "tuiHintCentered", "tuiHintCentered", "tuiHintOffset", "tuiHintOffset"], outputs: ["tuiHintDirectionChange", "tuiHintDirectionChange"] }], ngImport: i0 }); }
273
305
  }
274
306
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintDirective, decorators: [{
275
307
  type: Directive,
@@ -284,6 +316,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
284
316
  },
285
317
  ],
286
318
  hostDirectives: [
319
+ TuiHintAnchor,
287
320
  TuiHintDriver,
288
321
  {
289
322
  directive: TuiHintHover,
@@ -298,28 +331,129 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
298
331
  }]
299
332
  }] });
300
333
 
334
+ const GAP = 8;
335
+ const ARROW_OFFSET = 22;
336
+ class TuiHintAnchored {
337
+ constructor() {
338
+ this.el = tuiInjectElement();
339
+ this.hover = inject(TuiHintHover);
340
+ this.vvs = inject(TuiVisualViewportService);
341
+ this.viewport = inject(TUI_VIEWPORT);
342
+ this.accessor = inject(TuiRectAccessor);
343
+ this.directive = inject(TuiHintDirective);
344
+ this.styles$ = inject(TuiPositionService).pipe(takeWhile(() => this.directive.el.isConnected &&
345
+ this.directive.el.getClientRects().length > 0), map((point) => this.vvs.correct(point)), takeUntilDestroyed());
346
+ this.sub = inject(TuiHoveredService)
347
+ .pipe(takeUntilDestroyed())
348
+ .subscribe((hover) => this.hover.toggle(hover));
349
+ }
350
+ ngAfterViewInit() {
351
+ this.styles$.subscribe({
352
+ next: (point) => this.update(...point),
353
+ complete: () => this.directive.toggle(false),
354
+ });
355
+ }
356
+ update(left, top) {
357
+ const { clientHeight, clientWidth } = this.el;
358
+ const rect = this.accessor.getClientRect();
359
+ if (rect === EMPTY_CLIENT_RECT || !clientHeight || !clientWidth) {
360
+ return;
361
+ }
362
+ const viewport = this.viewport.getClientRect();
363
+ const max = Math.max(GAP, viewport.width + viewport.left - clientWidth - GAP);
364
+ const safeLeft = tuiClamp(Math.max(GAP, left), viewport.left + GAP, max);
365
+ const startX = Math.round(safeLeft) === Math.round(rect.left);
366
+ const startY = Math.round(top) === Math.round(rect.top);
367
+ const endX = Math.round(safeLeft + clientWidth) === Math.round(rect.right);
368
+ const endY = Math.round(top + clientHeight) === Math.round(rect.bottom);
369
+ const [beakLeft, beakTop] = this.vvs.correct([
370
+ rect.left + rect.width / 2 - safeLeft,
371
+ rect.top + rect.height / 2 - top,
372
+ ]);
373
+ /* eslint-disable no-nested-ternary */
374
+ const x = startX ? ARROW_OFFSET : endX ? clientWidth - ARROW_OFFSET : beakLeft;
375
+ const y = startY ? ARROW_OFFSET : endY ? clientHeight - ARROW_OFFSET : beakTop;
376
+ this.apply(tuiPx(Math.round(top)), tuiPx(Math.round(safeLeft)), Math.round((tuiClamp(y, 0, clientHeight) / clientHeight) * 100), Math.round((tuiClamp(x, 0, clientWidth) / clientWidth) * 100));
377
+ }
378
+ apply(top, left, beakTop, beakLeft) {
379
+ this.el.style.setProperty('top', top);
380
+ this.el.style.setProperty('left', left);
381
+ this.el.style.setProperty('--t-top', `${beakTop}%`);
382
+ this.el.style.setProperty('--t-left', `${beakLeft}%`);
383
+ this.el.style.setProperty('--t-rotate', !beakLeft || Math.ceil(beakLeft) === 100 ? '90deg' : '0deg');
384
+ }
385
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintAnchored, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
386
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.25", type: TuiHintAnchored, isStandalone: true, providers: [
387
+ TuiPositionService,
388
+ TuiHoveredService,
389
+ tuiProvideAccessor(TuiPositionAccessor, 'hint'),
390
+ tuiProvideAccessor(TuiRectAccessor, 'hint'),
391
+ ], ngImport: i0 }); }
392
+ }
393
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintAnchored, decorators: [{
394
+ type: Directive,
395
+ args: [{
396
+ providers: [
397
+ TuiPositionService,
398
+ TuiHoveredService,
399
+ tuiProvideAccessor(TuiPositionAccessor, 'hint'),
400
+ tuiProvideAccessor(TuiRectAccessor, 'hint'),
401
+ ],
402
+ }]
403
+ }] });
404
+
405
+ const STYLE = {
406
+ position: 'fixed',
407
+ blockSize: '1px',
408
+ inlineSize: '1px',
409
+ pointerEvents: 'none',
410
+ };
301
411
  class TuiHintPointer extends TuiHintHover {
302
412
  constructor() {
303
- super(...arguments);
413
+ super();
414
+ this.doc = inject(DOCUMENT);
304
415
  this.currentRect = EMPTY_CLIENT_RECT;
416
+ this.nativeElement = this.doc.createElement('div');
417
+ afterNextRender(() => {
418
+ const anchorName = `--${tuiGenerateId()}`;
419
+ const positionAnchor = this.el.getAttribute('data-tui-anchor');
420
+ const style = { ...STYLE, positionAnchor, anchorName };
421
+ Object.assign(this.nativeElement.style, style);
422
+ this.nativeElement.setAttribute('data-tui-anchor', anchorName);
423
+ this.doc.body.appendChild(this.nativeElement);
424
+ });
425
+ }
426
+ ngOnDestroy() {
427
+ this.nativeElement.parentNode?.removeChild(this.nativeElement);
305
428
  }
306
429
  getClientRect() {
307
430
  return this.currentRect;
308
431
  }
309
432
  onMove({ clientX, clientY }) {
433
+ const { top, left } = this.el.getBoundingClientRect();
310
434
  this.currentRect = tuiPointToClientRect(clientX, clientY);
311
- }
312
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintPointer, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
313
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.25", type: TuiHintPointer, isStandalone: true, selector: "[tuiHint][tuiHintPointer]", host: { listeners: { "mousemove.zoneless": "onMove($event)" } }, providers: [tuiAsRectAccessor(TuiHintPointer), tuiAsDriver(TuiHintPointer)], usesInheritance: true, ngImport: i0 }); }
435
+ this.nativeElement.style.top = `calc(anchor(top) + ${clientY - top}px)`;
436
+ this.nativeElement.style.left = `calc(anchor(left) + ${clientX - left}px)`;
437
+ }
438
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintPointer, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
439
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.25", type: TuiHintPointer, isStandalone: true, selector: "[tuiHint][tuiHintPointer]", host: { listeners: { "mousemove.zoneless": "onMove($event)" } }, providers: [
440
+ tuiAsRectAccessor(TuiHintPointer),
441
+ tuiAsDriver(TuiHintPointer),
442
+ tuiProvide(TUI_HINT_ANCHOR, TuiHintPointer),
443
+ ], usesInheritance: true, ngImport: i0 }); }
314
444
  }
315
445
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintPointer, decorators: [{
316
446
  type: Directive,
317
447
  args: [{
318
448
  selector: '[tuiHint][tuiHintPointer]',
319
- providers: [tuiAsRectAccessor(TuiHintPointer), tuiAsDriver(TuiHintPointer)],
449
+ providers: [
450
+ tuiAsRectAccessor(TuiHintPointer),
451
+ tuiAsDriver(TuiHintPointer),
452
+ tuiProvide(TUI_HINT_ANCHOR, TuiHintPointer),
453
+ ],
320
454
  host: { '(mousemove.zoneless)': 'onMove($event)' },
321
455
  }]
322
- }] });
456
+ }], ctorParameters: () => [] });
323
457
 
324
458
  class TuiHintUnstyledComponent {
325
459
  constructor() {
@@ -350,43 +484,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
350
484
  args: [{ selector: 'ng-template[tuiHint]' }]
351
485
  }], ctorParameters: () => [] });
352
486
 
353
- /** @internal */
354
- function tuiGetHintProviders() {
355
- return [
356
- TuiPositionService,
357
- TuiHoveredService,
358
- tuiPositionAccessorFor('hint', TuiHintPosition),
359
- tuiRectAccessorFor('hint', forwardRef(() => TuiHintDirective)),
360
- ];
361
- }
362
- const GAP = 8;
363
- const ARROW_OFFSET = 22;
364
487
  class TuiHintComponent {
365
488
  constructor() {
366
489
  this.el = tuiInjectElement();
367
490
  this.hover = inject(TuiHintHover);
368
- this.vvs = inject(TuiVisualViewportService);
369
- this.viewport = inject(TUI_VIEWPORT);
370
491
  this.pointer = inject(TuiHintPointer, { optional: true });
371
492
  this.accessor = inject(TuiRectAccessor);
372
493
  this.hint = inject(TuiHintDirective);
494
+ this.appearance = tuiAppearance(this.hint.appearance);
373
495
  this.content = this.hint.component.component === TuiHintUnstyledComponent
374
496
  ? signal('')
375
497
  : this.hint.content;
376
498
  this.theme = this.hint.el
377
499
  .closest('[tuiTheme]')
378
500
  ?.getAttribute('tuiTheme');
379
- this.appearance = tuiAppearance(this.hint.appearance);
380
- inject(TuiPositionService)
381
- .pipe(takeWhile(() => this.hint.el.isConnected &&
382
- this.hint.el.getClientRects().length > 0), map((point) => this.vvs.correct(point)), takeUntilDestroyed())
383
- .subscribe({
384
- next: (point) => this.update(...point),
385
- complete: () => this.hint.toggle(false),
386
- });
387
- inject(TuiHoveredService)
388
- .pipe(takeUntilDestroyed())
389
- .subscribe((hover) => this.hover.toggle(hover));
390
501
  }
391
502
  onPointerDown(target) {
392
503
  if ((!target.closest(this.el.tagName) && !this.hint.el.contains(target)) ||
@@ -394,36 +505,8 @@ class TuiHintComponent {
394
505
  this.hover.toggle(false);
395
506
  }
396
507
  }
397
- apply(top, left, beakTop, beakLeft) {
398
- this.el.style.setProperty('top', top);
399
- this.el.style.setProperty('left', left);
400
- this.el.style.setProperty('--t-top', `${beakTop}%`);
401
- this.el.style.setProperty('--t-left', `${beakLeft}%`);
402
- this.el.style.setProperty('--t-rotate', !beakLeft || Math.ceil(beakLeft) === 100 ? '90deg' : '0deg');
403
- }
404
- update(left, top) {
405
- const { clientHeight, clientWidth } = this.el;
406
- const rect = this.accessor.getClientRect();
407
- if (rect === EMPTY_CLIENT_RECT || !clientHeight || !clientWidth) {
408
- return;
409
- }
410
- const viewport = this.viewport.getClientRect();
411
- const safeLeft = tuiClamp(Math.max(GAP, left), viewport.left + GAP, Math.max(GAP, viewport.width + viewport.left - clientWidth - GAP));
412
- const startX = Math.round(safeLeft) === Math.round(rect.left);
413
- const startY = Math.round(top) === Math.round(rect.top);
414
- const endX = Math.round(safeLeft + clientWidth) === Math.round(rect.right);
415
- const endY = Math.round(top + clientHeight) === Math.round(rect.bottom);
416
- const [beakLeft, beakTop] = this.vvs.correct([
417
- rect.left + rect.width / 2 - safeLeft,
418
- rect.top + rect.height / 2 - top,
419
- ]);
420
- /* eslint-disable no-nested-ternary */
421
- const x = startX ? ARROW_OFFSET : endX ? clientWidth - ARROW_OFFSET : beakLeft;
422
- const y = startY ? ARROW_OFFSET : endY ? clientHeight - ARROW_OFFSET : beakTop;
423
- this.apply(tuiPx(Math.round(top)), tuiPx(Math.round(safeLeft)), Math.round((tuiClamp(y, 0, clientHeight) / clientHeight) * 100), Math.round((tuiClamp(x, 0, clientWidth) / clientWidth) * 100));
424
- }
425
508
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
426
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: TuiHintComponent, isStandalone: true, selector: "tui-hint", host: { attributes: { "role": "tooltip" }, listeners: { "document:pointerdown": "onPointerDown($event.target)" }, properties: { "attr.tuiTheme": "theme", "class._untouchable": "pointer" } }, providers: [tuiGetHintProviders(), tuiButtonOptionsProvider({ size: 's' })], hostDirectives: [{ directive: i1.TuiAppearance }, { directive: i2.TuiAnimated }, { directive: i3.TuiActiveZone }], ngImport: i0, template: `
509
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: TuiHintComponent, isStandalone: true, selector: "tui-hint", host: { attributes: { "role": "tooltip" }, listeners: { "document:pointerdown": "onPointerDown($event.target)" }, properties: { "attr.tuiTheme": "theme", "class._untouchable": "pointer" } }, providers: [tuiButtonOptionsProvider({ size: 's' })], hostDirectives: [{ directive: i1.TuiAppearance }, { directive: i2.TuiAnimated }, { directive: i3.TuiActiveZone }, { directive: TuiHintAnchored }], ngImport: i0, template: `
427
510
  <ng-content />
428
511
  <span
429
512
  *polymorpheusOutlet="content() as text; context: hint.context()"
@@ -439,13 +522,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
439
522
  *polymorpheusOutlet="content() as text; context: hint.context()"
440
523
  [innerHTML]="text"
441
524
  ></span>
442
- `, changeDetection: ChangeDetectionStrategy.OnPush, providers: [tuiGetHintProviders(), tuiButtonOptionsProvider({ size: 's' })], hostDirectives: [TuiAppearance, TuiAnimated, TuiActiveZone], host: {
525
+ `, changeDetection: ChangeDetectionStrategy.OnPush, providers: [tuiButtonOptionsProvider({ size: 's' })], hostDirectives: [TuiAppearance, TuiAnimated, TuiActiveZone, TuiHintAnchored], host: {
443
526
  role: 'tooltip',
444
527
  '[attr.tuiTheme]': 'theme',
445
528
  '[class._untouchable]': 'pointer',
446
529
  '(document:pointerdown)': 'onPointerDown($event.target)',
447
530
  }, styles: [":host{position:absolute;max-inline-size:min(20rem,calc(100% - 1rem));padding:.75rem 1rem;background:var(--tui-background-accent-1);border-radius:var(--tui-radius-l);color:var(--tui-text-primary-on-accent-1);box-sizing:border-box;font:var(--tui-typography-body-s);white-space:pre-line;overflow-wrap:break-word;transform-origin:var(--t-left) var(--t-top);--tui-background-elevation-2: var(--tui-background-elevation-3);--tui-scale: .5}:host.tui-enter{animation:tuiFade var(--tui-duration) var(--tui-curve-expressive-standard),tuiScale var(--tui-duration) var(--tui-curve-expressive-standard) 10ms}:host.tui-leave{animation:tuiFade calc(var(--tui-duration) / 2) var(--tui-curve-expressive-standard) reverse,tuiScale calc(var(--tui-duration) / 2) var(--tui-curve-expressive-standard) reverse}:host:before{content:\"\";position:absolute;inset-block-start:var(--t-top);inset-inline-start:var(--t-left);inline-size:.75rem;block-size:.5rem;background:inherit;-webkit-mask-image:url('data:image/svg+xml,<svg viewBox=\"0 0 12 8\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3.61336 1.69607L2.44882 2.96493C1.84795 3.61964 0.949361 3.99951 0.00053941 4C0.000359608 4 0.000179805 4 0 4C0.000179863 4 0.000359764 4 0.000539623 4C0.949362 4.00049 1.84795 4.38036 2.44882 5.03506L3.61336 6.30394C4.55981 7.33517 5.03303 7.85079 5.63254 7.96535C5.87433 8.01155 6.12436 8.01155 6.36616 7.96535C6.96567 7.85079 7.43889 7.33517 8.38534 6.30393L9.54988 5.03507C10.1511 4.37994 11.0505 4 12 4C11.0505 4 10.1511 3.62006 9.54988 2.96493L8.38534 1.69606C7.43889 0.664826 6.96567 0.149207 6.36616 0.0346517C6.12436 -0.0115506 5.87433 -0.0115506 5.63254 0.0346517C5.03303 0.149207 4.55981 0.664827 3.61336 1.69607Z\" /></svg>');mask-image:url('data:image/svg+xml,<svg viewBox=\"0 0 12 8\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M3.61336 1.69607L2.44882 2.96493C1.84795 3.61964 0.949361 3.99951 0.00053941 4C0.000359608 4 0.000179805 4 0 4C0.000179863 4 0.000359764 4 0.000539623 4C0.949362 4.00049 1.84795 4.38036 2.44882 5.03506L3.61336 6.30394C4.55981 7.33517 5.03303 7.85079 5.63254 7.96535C5.87433 8.01155 6.12436 8.01155 6.36616 7.96535C6.96567 7.85079 7.43889 7.33517 8.38534 6.30393L9.54988 5.03507C10.1511 4.37994 11.0505 4 12 4C11.0505 4 10.1511 3.62006 9.54988 2.96493L8.38534 1.69606C7.43889 0.664826 6.96567 0.149207 6.36616 0.0346517C6.12436 -0.0115506 5.87433 -0.0115506 5.63254 0.0346517C5.03303 0.149207 4.55981 0.664827 3.61336 1.69607Z\" /></svg>');transition:none;transform:translate(-50%,-50%) rotate(var(--t-rotate))}:host:not([style*=top]){visibility:hidden}:host._untouchable{pointer-events:none}:host ::ng-deep [tuiTitle]{margin-block-end:.75rem}:host ::ng-deep [tuiTitle]+footer{margin-block-start:.75rem}:host ::ng-deep [tuiIconButton][data-appearance=icon][data-size=xs]{float:right;margin-inline-end:-.25rem}@supports (float: inline-end){:host ::ng-deep [tuiIconButton][data-appearance=icon][data-size=xs]{float:inline-end}}:host ::ng-deep img{display:block;border-radius:var(--tui-radius-m)}:host ::ng-deep footer{display:flex;justify-content:flex-end;gap:.5rem;inline-size:18rem;max-inline-size:100%;margin:1rem 0 .25rem}\n"] }]
448
- }], ctorParameters: () => [] });
531
+ }] });
449
532
 
450
533
  class TuiHintDescribe extends TuiDriver {
451
534
  constructor() {
@@ -478,18 +561,25 @@ class TuiHintHost extends TuiRectAccessor {
478
561
  super(...arguments);
479
562
  this.tuiHintHost = input();
480
563
  this.type = 'hint';
564
+ this.nativeElement = tuiInjectElement();
565
+ this.sync = effect(() => {
566
+ const anchorName = `--${tuiGenerateId()}`;
567
+ this.nativeElement = this.tuiHintHost() || this.nativeElement;
568
+ this.nativeElement.setAttribute('data-tui-anchor', anchorName);
569
+ this.nativeElement.style.setProperty('anchor-name', anchorName);
570
+ });
481
571
  }
482
572
  getClientRect() {
483
- return this.tuiHintHost()?.getBoundingClientRect() || EMPTY_CLIENT_RECT;
573
+ return this.nativeElement.getBoundingClientRect();
484
574
  }
485
575
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintHost, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
486
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.25", type: TuiHintHost, isStandalone: true, selector: "[tuiHint][tuiHintHost]", inputs: { tuiHintHost: { classPropertyName: "tuiHintHost", publicName: "tuiHintHost", isSignal: true, isRequired: false, transformFunction: null } }, providers: [tuiAsRectAccessor(TuiHintHost)], usesInheritance: true, ngImport: i0 }); }
576
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.25", type: TuiHintHost, isStandalone: true, selector: "[tuiHint][tuiHintHost]", inputs: { tuiHintHost: { classPropertyName: "tuiHintHost", publicName: "tuiHintHost", isSignal: true, isRequired: false, transformFunction: null } }, providers: [tuiAsRectAccessor(TuiHintHost), tuiProvide(TUI_HINT_ANCHOR, TuiHintHost)], usesInheritance: true, ngImport: i0 }); }
487
577
  }
488
578
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiHintHost, decorators: [{
489
579
  type: Directive,
490
580
  args: [{
491
581
  selector: '[tuiHint][tuiHintHost]',
492
- providers: [tuiAsRectAccessor(TuiHintHost)],
582
+ providers: [tuiAsRectAccessor(TuiHintHost), tuiProvide(TUI_HINT_ANCHOR, TuiHintHost)],
493
583
  }]
494
584
  }] });
495
585
 
@@ -548,7 +638,6 @@ const TuiHint = [
548
638
  TuiHintDirective,
549
639
  TuiHintUnstyled,
550
640
  TuiHintDriver,
551
- TuiHintPosition,
552
641
  TuiHintHover,
553
642
  TuiHintOverflow,
554
643
  TuiHintDescribe,
@@ -561,5 +650,5 @@ const TuiHint = [
561
650
  * Generated bundle index. Do not edit.
562
651
  */
563
652
 
564
- export { TUI_HINT_COMPONENT, TUI_HINT_DEFAULT_OPTIONS, TUI_HINT_DIRECTIONS, TUI_HINT_OPTIONS, TuiHint, TuiHintComponent, TuiHintDescribe, TuiHintDirective, TuiHintDriver, TuiHintHost, TuiHintHover, TuiHintManual, TuiHintOverflow, TuiHintPointer, TuiHintPosition, TuiHintUnstyled, TuiHintUnstyledComponent, tuiGetHintProviders, tuiHintOptionsProvider };
653
+ export { TUI_HINT_ANCHOR, TUI_HINT_COMPONENT, TUI_HINT_DEFAULT_OPTIONS, TUI_HINT_DIRECTIONS, TUI_HINT_OPTIONS, TuiHint, TuiHintAnchor, TuiHintAnchored, TuiHintComponent, TuiHintDescribe, TuiHintDirective, TuiHintDriver, TuiHintHost, TuiHintHover, TuiHintManual, TuiHintOverflow, TuiHintPointer, TuiHintPosition, TuiHintUnstyled, TuiHintUnstyledComponent, tuiHintOptionsProvider };
565
654
  //# sourceMappingURL=taiga-ui-core-portals-hint.mjs.map