@taiga-ui/core 5.24.0 → 5.25.0-canary.5ab31f9

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 (64) 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/scrollbar/scroll-controls.component.d.ts +1 -1
  5. package/components/scrollbar/scroll-ref.directive.d.ts +2 -0
  6. package/components/scrollbar/scrollbar.component.d.ts +0 -1
  7. package/fesm2022/taiga-ui-core-classes.mjs +23 -7
  8. package/fesm2022/taiga-ui-core-classes.mjs.map +1 -1
  9. package/fesm2022/taiga-ui-core-components-button.mjs +2 -2
  10. package/fesm2022/taiga-ui-core-components-button.mjs.map +1 -1
  11. package/fesm2022/taiga-ui-core-components-calendar.mjs +1 -1
  12. package/fesm2022/taiga-ui-core-components-calendar.mjs.map +1 -1
  13. package/fesm2022/taiga-ui-core-components-carousel.mjs +2 -2
  14. package/fesm2022/taiga-ui-core-components-carousel.mjs.map +1 -1
  15. package/fesm2022/taiga-ui-core-components-cell.mjs +6 -9
  16. package/fesm2022/taiga-ui-core-components-cell.mjs.map +1 -1
  17. package/fesm2022/taiga-ui-core-components-checkbox.mjs +2 -2
  18. package/fesm2022/taiga-ui-core-components-checkbox.mjs.map +1 -1
  19. package/fesm2022/taiga-ui-core-components-data-list.mjs +7 -7
  20. package/fesm2022/taiga-ui-core-components-data-list.mjs.map +1 -1
  21. package/fesm2022/taiga-ui-core-components-icon.mjs +2 -2
  22. package/fesm2022/taiga-ui-core-components-icon.mjs.map +1 -1
  23. package/fesm2022/taiga-ui-core-components-label.mjs +3 -3
  24. package/fesm2022/taiga-ui-core-components-label.mjs.map +1 -1
  25. package/fesm2022/taiga-ui-core-components-link.mjs +2 -2
  26. package/fesm2022/taiga-ui-core-components-link.mjs.map +1 -1
  27. package/fesm2022/taiga-ui-core-components-notification.mjs +2 -2
  28. package/fesm2022/taiga-ui-core-components-notification.mjs.map +1 -1
  29. package/fesm2022/taiga-ui-core-components-radio.mjs +2 -2
  30. package/fesm2022/taiga-ui-core-components-radio.mjs.map +1 -1
  31. package/fesm2022/taiga-ui-core-components-root.mjs +3 -3
  32. package/fesm2022/taiga-ui-core-components-root.mjs.map +1 -1
  33. package/fesm2022/taiga-ui-core-components-scrollbar.mjs +31 -47
  34. package/fesm2022/taiga-ui-core-components-scrollbar.mjs.map +1 -1
  35. package/fesm2022/taiga-ui-core-components-textfield.mjs +6 -5
  36. package/fesm2022/taiga-ui-core-components-textfield.mjs.map +1 -1
  37. package/fesm2022/taiga-ui-core-components-title.mjs +3 -3
  38. package/fesm2022/taiga-ui-core-components-title.mjs.map +1 -1
  39. package/fesm2022/taiga-ui-core-directives-appearance.mjs +3 -3
  40. package/fesm2022/taiga-ui-core-directives-appearance.mjs.map +1 -1
  41. package/fesm2022/taiga-ui-core-directives-group.mjs +3 -3
  42. package/fesm2022/taiga-ui-core-directives-group.mjs.map +1 -1
  43. package/fesm2022/taiga-ui-core-directives-icons.mjs +3 -3
  44. package/fesm2022/taiga-ui-core-directives-icons.mjs.map +1 -1
  45. package/fesm2022/taiga-ui-core-portals-alert.mjs +3 -3
  46. package/fesm2022/taiga-ui-core-portals-alert.mjs.map +1 -1
  47. package/fesm2022/taiga-ui-core-portals-dialog.mjs +2 -2
  48. package/fesm2022/taiga-ui-core-portals-dialog.mjs.map +1 -1
  49. package/fesm2022/taiga-ui-core-portals-dropdown.mjs +105 -95
  50. package/fesm2022/taiga-ui-core-portals-dropdown.mjs.map +1 -1
  51. package/fesm2022/taiga-ui-core-portals-hint.mjs +26 -14
  52. package/fesm2022/taiga-ui-core-portals-hint.mjs.map +1 -1
  53. package/fesm2022/taiga-ui-core-portals-modal.mjs +3 -3
  54. package/fesm2022/taiga-ui-core-portals-modal.mjs.map +1 -1
  55. package/fesm2022/taiga-ui-core-tokens.mjs +30 -8
  56. package/fesm2022/taiga-ui-core-tokens.mjs.map +1 -1
  57. package/package.json +8 -8
  58. package/portals/dropdown/dropdown-anchor.directive.d.ts +5 -1
  59. package/portals/dropdown/dropdown.directive.d.ts +1 -0
  60. package/portals/dropdown/dropdown.providers.d.ts +1 -1
  61. package/portals/hint/hint-anchor.directive.d.ts +5 -1
  62. package/portals/hint/hint.d.ts +1 -2
  63. package/tokens/date-format.d.ts +19 -0
  64. package/tokens/number-format.d.ts +18 -8
@@ -1,15 +1,15 @@
1
1
  import { tuiProvide, tuiDirectiveBinding, tuiCreateOptions } from '@taiga-ui/cdk/utils/di';
2
2
  import { coerceArray } from '@angular/cdk/coercion';
3
3
  import * as i0 from '@angular/core';
4
- import { Injectable, Directive, InjectionToken, Optional, Self, SkipSelf, inject, forwardRef, computed, ChangeDetectionStrategy, Component, input, effect, ElementRef, INJECTOR, ChangeDetectorRef, signal, TemplateRef, contentChild, model, PLATFORM_ID, ViewContainerRef, afterNextRender } from '@angular/core';
5
- import { outputFromObservable, takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
4
+ import { Injectable, Directive, InjectionToken, Optional, Self, SkipSelf, inject, computed, ChangeDetectionStrategy, Component, input, effect, ElementRef, INJECTOR, ChangeDetectorRef, signal, TemplateRef, contentChild, model, PLATFORM_ID, ViewContainerRef, afterNextRender } from '@angular/core';
5
+ import { takeUntilDestroyed, outputFromObservable, toObservable } from '@angular/core/rxjs-interop';
6
6
  import { tuiZonefreeScheduler, tuiIfMap, tuiCloseWatcher, tuiTypedFromEvent, tuiStopPropagation, tuiZoneOptimized } from '@taiga-ui/cdk/observables';
7
7
  import { tuiInjectElement, tuiGetActualTarget, tuiIsElement, tuiIsElementEditable, tuiIsHTMLElement, tuiPointToClientRect, tuiIsTextNode, tuiIsTextfield } from '@taiga-ui/cdk/utils/dom';
8
- import { TuiDriverDirective, TuiPositionAccessor, tuiFallbackAccessor, TuiRectAccessor, tuiPositionAccessorFor, tuiRectAccessorFor, tuiAsVehicle, tuiAsDriver, tuiAsRectAccessor, TuiDriver, tuiAsPositionAccessor } from '@taiga-ui/core/classes';
8
+ import { TuiDriverDirective, TuiRectAccessor, tuiProvideAccessor, TuiPositionAccessor, tuiAsRectAccessor, tuiInjectAccessor, tuiAsPositionAccessor, tuiAsVehicle, tuiAsDriver, TuiDriver } from '@taiga-ui/core/classes';
9
9
  import { TuiPopupService } from '@taiga-ui/core/portals/popup';
10
10
  import { tuiCheckFixedPosition, tuiGetWordRange } from '@taiga-ui/core/utils/dom';
11
11
  import { PolymorpheusOutlet, PolymorpheusComponent, PolymorpheusTemplate } from '@taiga-ui/polymorpheus';
12
- import { BehaviorSubject, Subject, distinctUntilChanged, takeWhile, map, throttleTime, merge, filter, EMPTY, switchMap, delay, startWith, takeUntil, fromEvent, of, tap, share, combineLatest } from 'rxjs';
12
+ import { BehaviorSubject, takeWhile, map, Subject, distinctUntilChanged, throttleTime, merge, filter, EMPTY, switchMap, delay, startWith, takeUntil, fromEvent, of, tap, share, combineLatest } from 'rxjs';
13
13
  import * as i1 from '@taiga-ui/cdk/directives/active-zone';
14
14
  import { TuiActiveZone } from '@taiga-ui/cdk/directives/active-zone';
15
15
  import * as i2 from '@taiga-ui/cdk/directives/animated';
@@ -99,84 +99,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
99
99
  }]
100
100
  }] });
101
101
 
102
- class TuiDropdownPosition extends TuiPositionAccessor {
103
- constructor() {
104
- super(...arguments);
105
- this.el = tuiInjectElement();
106
- this.options = inject(TUI_DROPDOWN_OPTIONS);
107
- this.viewport = inject(TUI_VIEWPORT);
108
- this.direction = new Subject();
109
- this.type = 'dropdown';
110
- this.accessor = tuiFallbackAccessor('dropdown')(inject(TuiRectAccessor, { self: true, optional: true }), { getClientRect: () => this.el.getBoundingClientRect() });
111
- this.tuiDropdownDirectionChange = outputFromObservable(this.direction.pipe(distinctUntilChanged()));
112
- }
113
- getPosition({ width, height }) {
114
- if (!width && !height) {
115
- this.previous = undefined;
116
- }
117
- const hostRect = this.accessor.getClientRect();
118
- const viewportRect = this.viewport.getClientRect();
119
- const { minHeight, direction, offset, limitWidth } = this.options;
120
- const align = this.getAlign(this.options.align);
121
- const viewport = {
122
- top: viewportRect.top - offset,
123
- bottom: viewportRect.bottom + offset,
124
- right: viewportRect.right - offset,
125
- left: viewportRect.left + offset,
126
- };
127
- const previous = this.previous || direction || 'bottom';
128
- const available = {
129
- top: hostRect.top - 2 * offset - viewport.top,
130
- bottom: viewport.bottom - hostRect.bottom - 2 * offset,
131
- };
132
- const rectWidth = limitWidth === 'fixed' ? hostRect.width : width;
133
- const right = Math.max(hostRect.right - rectWidth, offset);
134
- const left = hostRect.left + width < viewport.right ? hostRect.left : right;
135
- const position = {
136
- top: hostRect.top - offset - height,
137
- bottom: hostRect.bottom + offset,
138
- right: Math.max(viewport.left, right),
139
- center: hostRect.left + hostRect.width / 2 + width / 2 < viewport.right
140
- ? hostRect.left + hostRect.width / 2 - width / 2
141
- : right,
142
- left: Math.max(viewport.left, left),
143
- };
144
- const better = available.top > available.bottom ? 'top' : 'bottom';
145
- if ((available[previous] > minHeight && direction) ||
146
- available[previous] > height) {
147
- this.direction.next(previous);
148
- return [position[align], position[previous]];
149
- }
150
- this.previous = better;
151
- this.direction.next(better);
152
- return [position[align], position[better]];
153
- }
154
- getAlign(align) {
155
- const rtl = this.el.matches('[dir="rtl"] :scope');
156
- if (rtl && align === 'start') {
157
- return 'right';
158
- }
159
- if (rtl && align === 'end') {
160
- return 'left';
161
- }
162
- if (align === 'center') {
163
- return 'center';
164
- }
165
- return align === 'end' ? 'right' : 'left';
166
- }
167
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownPosition, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
168
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.25", type: TuiDropdownPosition, isStandalone: true, outputs: { tuiDropdownDirectionChange: "tuiDropdownDirectionChange" }, usesInheritance: true, ngImport: i0 }); }
169
- }
170
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownPosition, decorators: [{
171
- type: Directive
172
- }] });
173
-
174
102
  const MAX_WIDTH_GAP = 16; // 8px min gap from each side
175
103
  class TuiDropdownAnchored {
176
104
  constructor() {
177
105
  this.el = tuiInjectElement();
178
106
  this.directive = inject(TuiDropdownDirective);
179
- this.accessor = this.directive.accessor;
107
+ this.accessor = inject(TuiRectAccessor);
180
108
  this.viewport = inject(TUI_VIEWPORT);
181
109
  this.vvs = inject(TuiVisualViewportService);
182
110
  this.options = inject(TUI_DROPDOWN_OPTIONS);
@@ -218,8 +146,8 @@ class TuiDropdownAnchored {
218
146
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownAnchored, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
219
147
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.25", type: TuiDropdownAnchored, isStandalone: true, providers: [
220
148
  TuiPositionService,
221
- tuiPositionAccessorFor('dropdown', TuiDropdownPosition),
222
- tuiRectAccessorFor('dropdown', forwardRef(() => TuiDropdownDirective)),
149
+ tuiProvideAccessor(TuiPositionAccessor, 'dropdown'),
150
+ tuiProvideAccessor(TuiRectAccessor, 'dropdown'),
223
151
  ], ngImport: i0 }); }
224
152
  }
225
153
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownAnchored, decorators: [{
@@ -227,8 +155,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
227
155
  args: [{
228
156
  providers: [
229
157
  TuiPositionService,
230
- tuiPositionAccessorFor('dropdown', TuiDropdownPosition),
231
- tuiRectAccessorFor('dropdown', forwardRef(() => TuiDropdownDirective)),
158
+ tuiProvideAccessor(TuiPositionAccessor, 'dropdown'),
159
+ tuiProvideAccessor(TuiRectAccessor, 'dropdown'),
232
160
  ],
233
161
  }]
234
162
  }] });
@@ -248,14 +176,14 @@ class TuiDropdownComponent {
248
176
  this.close = () => this.directive.toggle(false);
249
177
  }
250
178
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
251
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: TuiDropdownComponent, isStandalone: true, selector: "tui-dropdown", host: { properties: { "attr.data-appearance": "options.appearance", "attr.tuiTheme": "theme()" } }, hostDirectives: [{ directive: i1.TuiActiveZone }, { directive: i2.TuiAnimated }, { directive: TuiDropdownAnchored }], ngImport: i0, template: "<tui-scrollbar class=\"t-scroll\">\n <div\n *polymorpheusOutlet=\"directive.content() as text; context: {$implicit: close}\"\n class=\"t-primitive\"\n >\n {{ text }}\n </div>\n</tui-scrollbar>\n", styles: [":host{position:absolute;display:flex;box-shadow:var(--tui-shadow-medium);color:var(--tui-text-primary);background:var(--tui-background-elevation-1);border-radius:var(--tui-radius-m);overflow:hidden;border:1px solid var(--tui-border-normal);box-sizing:border-box;isolation:isolate;pointer-events:auto;--tui-from: translateY(-1rem)}:host:has(tui-data-list[data-size=l]){border-radius:var(--tui-radius-l)}:host.tui-enter,:host.tui-leave{animation-name:tuiFade,tuiSlide;animation-duration:calc(var(--tui-duration) / 2);pointer-events:none}:host:not([style*=top]){visibility:hidden}.t-scroll{flex-grow:1;max-inline-size:calc(100% + 2px);inline-size:max-content;overscroll-behavior:none;margin:-1px}.t-primitive{padding:1rem}\n"], dependencies: [{ kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "component", type: TuiScrollbar, selector: "tui-scrollbar" }], changeDetection: i0.ChangeDetectionStrategy.Default }); }
179
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.25", type: TuiDropdownComponent, isStandalone: true, selector: "tui-dropdown", host: { properties: { "attr.data-appearance": "options.appearance", "attr.tuiTheme": "theme()" } }, hostDirectives: [{ directive: i1.TuiActiveZone }, { directive: i2.TuiAnimated }, { directive: TuiDropdownAnchored }], ngImport: i0, template: "<tui-scrollbar class=\"t-scroll\">\n <div\n *polymorpheusOutlet=\"directive.content() as text; context: {$implicit: close}\"\n class=\"t-primitive\"\n >\n {{ text }}\n </div>\n</tui-scrollbar>\n", styles: [":host{position:absolute;display:flex;box-shadow:var(--tui-shadow-medium);color:var(--tui-text-primary);background:var(--tui-background-elevation-1);border-radius:var(--tui-radius-m);overflow:hidden;isolation:isolate;pointer-events:auto;outline-offset:-1px;outline:1px solid color-mix(in srgb,rgb(from var(--tui-border-normal) r g b / 1) 12%,var(--tui-background-elevation-1));--tui-from: translateY(-1rem)}:host:has(tui-data-list[data-size=l]){border-radius:var(--tui-radius-l)}:host.tui-enter,:host.tui-leave{animation-name:tuiFade,tuiSlide;animation-duration:calc(var(--tui-duration) / 2);pointer-events:none}:host:not([style*=top]){visibility:hidden}.t-scroll{z-index:-1;flex-grow:1;max-inline-size:100%;inline-size:max-content;overscroll-behavior:none}.t-primitive{padding:1rem}\n"], dependencies: [{ kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "component", type: TuiScrollbar, selector: "tui-scrollbar" }], changeDetection: i0.ChangeDetectionStrategy.Default }); }
252
180
  }
253
181
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownComponent, decorators: [{
254
182
  type: Component,
255
183
  args: [{ selector: 'tui-dropdown', imports: [PolymorpheusOutlet, TuiScrollbar], changeDetection: ChangeDetectionStrategy.Default, hostDirectives: [TuiActiveZone, TuiAnimated, TuiDropdownAnchored], host: {
256
184
  '[attr.data-appearance]': 'options.appearance',
257
185
  '[attr.tuiTheme]': 'theme()',
258
- }, template: "<tui-scrollbar class=\"t-scroll\">\n <div\n *polymorpheusOutlet=\"directive.content() as text; context: {$implicit: close}\"\n class=\"t-primitive\"\n >\n {{ text }}\n </div>\n</tui-scrollbar>\n", styles: [":host{position:absolute;display:flex;box-shadow:var(--tui-shadow-medium);color:var(--tui-text-primary);background:var(--tui-background-elevation-1);border-radius:var(--tui-radius-m);overflow:hidden;border:1px solid var(--tui-border-normal);box-sizing:border-box;isolation:isolate;pointer-events:auto;--tui-from: translateY(-1rem)}:host:has(tui-data-list[data-size=l]){border-radius:var(--tui-radius-l)}:host.tui-enter,:host.tui-leave{animation-name:tuiFade,tuiSlide;animation-duration:calc(var(--tui-duration) / 2);pointer-events:none}:host:not([style*=top]){visibility:hidden}.t-scroll{flex-grow:1;max-inline-size:calc(100% + 2px);inline-size:max-content;overscroll-behavior:none;margin:-1px}.t-primitive{padding:1rem}\n"] }]
186
+ }, template: "<tui-scrollbar class=\"t-scroll\">\n <div\n *polymorpheusOutlet=\"directive.content() as text; context: {$implicit: close}\"\n class=\"t-primitive\"\n >\n {{ text }}\n </div>\n</tui-scrollbar>\n", styles: [":host{position:absolute;display:flex;box-shadow:var(--tui-shadow-medium);color:var(--tui-text-primary);background:var(--tui-background-elevation-1);border-radius:var(--tui-radius-m);overflow:hidden;isolation:isolate;pointer-events:auto;outline-offset:-1px;outline:1px solid color-mix(in srgb,rgb(from var(--tui-border-normal) r g b / 1) 12%,var(--tui-background-elevation-1));--tui-from: translateY(-1rem)}:host:has(tui-data-list[data-size=l]){border-radius:var(--tui-radius-l)}:host.tui-enter,:host.tui-leave{animation-name:tuiFade,tuiSlide;animation-duration:calc(var(--tui-duration) / 2);pointer-events:none}:host:not([style*=top]){visibility:hidden}.t-scroll{z-index:-1;flex-grow:1;max-inline-size:100%;inline-size:max-content;overscroll-behavior:none}.t-primitive{padding:1rem}\n"] }]
259
187
  }] });
260
188
 
261
189
  /**
@@ -297,20 +225,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
297
225
  args: [{ selector: '[tuiDropdownA11y]' }]
298
226
  }] });
299
227
 
300
- class TuiDropdownAnchor {
228
+ class TuiDropdownAnchor extends TuiRectAccessor {
301
229
  constructor() {
230
+ super(...arguments);
231
+ this.el = tuiInjectElement();
302
232
  this.anchor = `--${tuiGenerateId()}`;
233
+ this.type = 'dropdown';
234
+ }
235
+ getClientRect() {
236
+ return this.el.getBoundingClientRect();
303
237
  }
304
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownAnchor, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
238
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownAnchor, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
305
239
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.25", type: TuiDropdownAnchor, isStandalone: true, host: { properties: { "attr.data-tui-anchor": "anchor", "style.anchor-name": "anchor" } }, providers: [
240
+ tuiAsRectAccessor(TuiDropdownAnchor),
306
241
  tuiProvide(TUI_DROPDOWN_HOST, ElementRef),
307
242
  tuiProvide(TUI_DROPDOWN_ANCHOR, ElementRef),
308
- ], ngImport: i0 }); }
243
+ ], usesInheritance: true, ngImport: i0 }); }
309
244
  }
310
245
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownAnchor, decorators: [{
311
246
  type: Directive,
312
247
  args: [{
313
248
  providers: [
249
+ tuiAsRectAccessor(TuiDropdownAnchor),
314
250
  tuiProvide(TUI_DROPDOWN_HOST, ElementRef),
315
251
  tuiProvide(TUI_DROPDOWN_ANCHOR, ElementRef),
316
252
  ],
@@ -321,6 +257,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
321
257
  }]
322
258
  }] });
323
259
 
260
+ class TuiDropdownPosition extends TuiPositionAccessor {
261
+ constructor() {
262
+ super(...arguments);
263
+ this.el = tuiInjectElement();
264
+ this.options = inject(TUI_DROPDOWN_OPTIONS);
265
+ this.viewport = inject(TUI_VIEWPORT);
266
+ this.direction = new Subject();
267
+ this.type = 'dropdown';
268
+ this.accessor = tuiInjectAccessor(TuiRectAccessor, 'dropdown');
269
+ this.tuiDropdownDirectionChange = outputFromObservable(this.direction.pipe(distinctUntilChanged()));
270
+ }
271
+ getPosition({ width, height }) {
272
+ if (!width && !height) {
273
+ this.previous = undefined;
274
+ }
275
+ const hostRect = this.accessor.getClientRect();
276
+ const viewportRect = this.viewport.getClientRect();
277
+ const { minHeight, direction, offset, limitWidth } = this.options;
278
+ const align = this.getAlign(this.options.align);
279
+ const viewport = {
280
+ top: viewportRect.top - offset,
281
+ bottom: viewportRect.bottom + offset,
282
+ right: viewportRect.right - offset,
283
+ left: viewportRect.left + offset,
284
+ };
285
+ const previous = this.previous || direction || 'bottom';
286
+ const available = {
287
+ top: hostRect.top - 2 * offset - viewport.top,
288
+ bottom: viewport.bottom - hostRect.bottom - 2 * offset,
289
+ };
290
+ const rectWidth = limitWidth === 'fixed' ? hostRect.width : width;
291
+ const right = Math.max(hostRect.right - rectWidth, offset);
292
+ const left = hostRect.left + width < viewport.right ? hostRect.left : right;
293
+ const position = {
294
+ top: hostRect.top - offset - height,
295
+ bottom: hostRect.bottom + offset,
296
+ right: Math.max(viewport.left, right),
297
+ center: hostRect.left + hostRect.width / 2 + width / 2 < viewport.right
298
+ ? hostRect.left + hostRect.width / 2 - width / 2
299
+ : right,
300
+ left: Math.max(viewport.left, left),
301
+ };
302
+ const better = available.top > available.bottom ? 'top' : 'bottom';
303
+ if ((available[previous] > minHeight && direction) ||
304
+ available[previous] > height) {
305
+ this.direction.next(previous);
306
+ return [position[align], position[previous]];
307
+ }
308
+ this.previous = better;
309
+ this.direction.next(better);
310
+ return [position[align], position[better]];
311
+ }
312
+ getAlign(align) {
313
+ const rtl = this.el.matches('[dir="rtl"] :scope');
314
+ if (rtl && align === 'start') {
315
+ return 'right';
316
+ }
317
+ if (rtl && align === 'end') {
318
+ return 'left';
319
+ }
320
+ if (align === 'center') {
321
+ return 'center';
322
+ }
323
+ return align === 'end' ? 'right' : 'left';
324
+ }
325
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownPosition, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
326
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.25", type: TuiDropdownPosition, isStandalone: true, outputs: { tuiDropdownDirectionChange: "tuiDropdownDirectionChange" }, providers: [tuiAsPositionAccessor(TuiDropdownPosition)], usesInheritance: true, ngImport: i0 }); }
327
+ }
328
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownPosition, decorators: [{
329
+ type: Directive,
330
+ args: [{ providers: [tuiAsPositionAccessor(TuiDropdownPosition)] }]
331
+ }] });
332
+
324
333
  class TuiDropdownDirective {
325
334
  constructor() {
326
335
  this.injector = inject(INJECTOR);
@@ -350,11 +359,12 @@ class TuiDropdownDirective {
350
359
  : content,
351
360
  });
352
361
  }
362
+ /** @deprecated remove in v6 */
353
363
  get accessor() {
354
364
  const accessors = this.injector.get(TuiRectAccessor, null, {
355
365
  self: true,
356
366
  });
357
- return tuiFallbackAccessor('dropdown')(accessors, this);
367
+ return ([...(accessors || [])].reverse().find(({ type }) => type === 'dropdown') || this);
358
368
  }
359
369
  get position() {
360
370
  return tuiCheckFixedPosition(this.el) ? 'fixed' : 'absolute';
@@ -770,21 +780,21 @@ class TuiDropdownPositionSided extends TuiPositionAccessor {
770
780
  super(...arguments);
771
781
  this.options = inject(TUI_DROPDOWN_OPTIONS);
772
782
  this.viewport = inject(TUI_VIEWPORT);
773
- this.vertical = inject(TuiDropdownPosition);
783
+ this.vertical = inject(TuiDropdownPosition, { optional: true });
774
784
  this.previous = this.options.direction || 'bottom';
775
785
  this.tuiDropdownSided = input('');
776
786
  this.tuiDropdownSidedOffset = input(4);
777
787
  this.type = 'dropdown';
778
788
  }
779
789
  getPosition(rect) {
780
- if (this.tuiDropdownSided() === false) {
790
+ if (this.tuiDropdownSided() === false && this.vertical) {
781
791
  return this.vertical.getPosition(rect);
782
792
  }
783
793
  const { height, width } = rect;
784
- const hostRect = this.vertical.accessor?.getClientRect() ?? EMPTY_CLIENT_RECT;
794
+ const hostRect = this.vertical?.accessor.getClientRect() ?? EMPTY_CLIENT_RECT;
785
795
  const viewport = this.viewport.getClientRect();
786
796
  const { direction, offset } = this.options;
787
- const adjusted = this.vertical.getAlign(this.options.align);
797
+ const adjusted = this.vertical?.getAlign(this.options.align) || 'center';
788
798
  const align = adjusted === 'center' ? 'left' : adjusted;
789
799
  const available = {
790
800
  top: hostRect.bottom - viewport.top,
@@ -803,21 +813,21 @@ class TuiDropdownPositionSided extends TuiPositionAccessor {
803
813
  const left = available[align] > width ? position[align] : maxLeft;
804
814
  if ((available[this.previous] > height && direction) ||
805
815
  this.previous === better) {
806
- this.vertical.direction.next(this.previous);
816
+ this.vertical?.direction.next(this.previous);
807
817
  return [left, position[this.previous]];
808
818
  }
809
819
  this.previous = better;
810
- this.vertical.direction.next(better);
820
+ this.vertical?.direction.next(better);
811
821
  return [left, position[better]];
812
822
  }
813
823
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownPositionSided, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
814
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.25", type: TuiDropdownPositionSided, isStandalone: true, selector: "[tuiDropdownSided]", inputs: { tuiDropdownSided: { classPropertyName: "tuiDropdownSided", publicName: "tuiDropdownSided", isSignal: true, isRequired: false, transformFunction: null }, tuiDropdownSidedOffset: { classPropertyName: "tuiDropdownSidedOffset", publicName: "tuiDropdownSidedOffset", isSignal: true, isRequired: false, transformFunction: null } }, providers: [TuiDropdownPosition, tuiAsPositionAccessor(TuiDropdownPositionSided)], usesInheritance: true, ngImport: i0 }); }
824
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.25", type: TuiDropdownPositionSided, isStandalone: true, selector: "[tuiDropdownSided]", inputs: { tuiDropdownSided: { classPropertyName: "tuiDropdownSided", publicName: "tuiDropdownSided", isSignal: true, isRequired: false, transformFunction: null }, tuiDropdownSidedOffset: { classPropertyName: "tuiDropdownSidedOffset", publicName: "tuiDropdownSidedOffset", isSignal: true, isRequired: false, transformFunction: null } }, providers: [tuiAsPositionAccessor(TuiDropdownPositionSided)], usesInheritance: true, ngImport: i0 }); }
815
825
  }
816
826
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownPositionSided, decorators: [{
817
827
  type: Directive,
818
828
  args: [{
819
829
  selector: '[tuiDropdownSided]',
820
- providers: [TuiDropdownPosition, tuiAsPositionAccessor(TuiDropdownPositionSided)],
830
+ providers: [tuiAsPositionAccessor(TuiDropdownPositionSided)],
821
831
  }]
822
832
  }] });
823
833