@taiga-ui/core 5.24.0 → 5.25.0-canary.405e17f

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 (65) 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 +145 -104
  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 +4 -4
  58. package/portals/dropdown/dropdown-anchor.directive.d.ts +5 -1
  59. package/portals/dropdown/dropdown.component.d.ts +4 -5
  60. package/portals/dropdown/dropdown.directive.d.ts +1 -0
  61. package/portals/dropdown/dropdown.providers.d.ts +1 -1
  62. package/portals/hint/hint-anchor.directive.d.ts +5 -1
  63. package/portals/hint/hint.d.ts +1 -2
  64. package/tokens/date-format.d.ts +19 -0
  65. package/tokens/number-format.d.ts +18 -8
@@ -1,20 +1,20 @@
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';
16
16
  import { TuiAnimated } from '@taiga-ui/cdk/directives/animated';
17
- import { TuiScrollbar } from '@taiga-ui/core/components/scrollbar';
17
+ import { TuiScrollbar, TuiScrollControls, TUI_SCROLL_REF } from '@taiga-ui/core/components/scrollbar';
18
18
  import { TUI_VIEWPORT, TUI_DARK_MODE, TUI_SELECTION_STREAM } from '@taiga-ui/core/tokens';
19
19
  import { EMPTY_CLIENT_RECT, TUI_TRUE_HANDLER, CHAR_ZERO_WIDTH_SPACE, CHAR_NO_BREAK_SPACE } from '@taiga-ui/cdk/constants';
20
20
  import { tuiClamp } from '@taiga-ui/cdk/utils/math';
@@ -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,35 +155,66 @@ 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
  }] });
235
163
 
236
164
  /**
237
- * @description:
238
- * This component is used to show template in a portal
239
- * using default style of white rounded box with a shadow
165
+ * TODO: Remove extends TuiScrollbar in v6 when TuiScrollable is dropped
240
166
  */
241
- class TuiDropdownComponent {
167
+ class TuiDropdownComponent extends TuiScrollbar {
242
168
  constructor() {
243
- this.options = inject(TUI_DROPDOWN_OPTIONS);
169
+ super(...arguments);
170
+ this.appearance = inject(TUI_DROPDOWN_OPTIONS).appearance;
244
171
  this.directive = inject(TuiDropdownDirective);
245
172
  this.context = inject(TUI_DROPDOWN_CONTEXT, { optional: true });
246
173
  this.darkMode = inject(TUI_DARK_MODE);
247
174
  this.theme = computed((_ = this.darkMode()) => this.directive.el.closest('[tuiTheme]')?.getAttribute('tuiTheme'));
248
175
  this.close = () => this.directive.toggle(false);
249
176
  }
250
- 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 }); }
177
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
178
+ 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": "appearance", "attr.tuiTheme": "theme()" } }, providers: [
179
+ {
180
+ provide: TUI_SCROLL_REF,
181
+ useFactory: () => inject(TuiDropdownComponent).browserScrollRef,
182
+ },
183
+ ], usesInheritance: true, hostDirectives: [{ directive: i1.TuiActiveZone }, { directive: i2.TuiAnimated }, { directive: TuiDropdownAnchored }], ngImport: i0, template: `
184
+ <tui-scroll-controls />
185
+ <div class="t-wrapper">
186
+ <div
187
+ *polymorpheusOutlet="
188
+ directive.content() as text;
189
+ context: {$implicit: close}
190
+ "
191
+ [innerHTML]="text"
192
+ ></div>
193
+ </div>
194
+ `, isInline: true, 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:auto;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));overscroll-behavior:none;position-try-fallbacks:flip-block,flip-inline,flip-block flip-inline;--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}:host._delegated{scroll-timeline:none}.t-wrapper{z-index:-1;flex:1}.t-wrapper>*{padding:1rem}\n"], dependencies: [{ kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "component", type: TuiScrollControls, selector: "tui-scroll-controls" }], changeDetection: i0.ChangeDetectionStrategy.Default }); }
252
195
  }
253
196
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownComponent, decorators: [{
254
197
  type: Component,
255
- args: [{ selector: 'tui-dropdown', imports: [PolymorpheusOutlet, TuiScrollbar], changeDetection: ChangeDetectionStrategy.Default, hostDirectives: [TuiActiveZone, TuiAnimated, TuiDropdownAnchored], host: {
256
- '[attr.data-appearance]': 'options.appearance',
198
+ args: [{ selector: 'tui-dropdown', imports: [PolymorpheusOutlet, TuiScrollControls], template: `
199
+ <tui-scroll-controls />
200
+ <div class="t-wrapper">
201
+ <div
202
+ *polymorpheusOutlet="
203
+ directive.content() as text;
204
+ context: {$implicit: close}
205
+ "
206
+ [innerHTML]="text"
207
+ ></div>
208
+ </div>
209
+ `, changeDetection: ChangeDetectionStrategy.Default, providers: [
210
+ {
211
+ provide: TUI_SCROLL_REF,
212
+ useFactory: () => inject(TuiDropdownComponent).browserScrollRef,
213
+ },
214
+ ], hostDirectives: [TuiActiveZone, TuiAnimated, TuiDropdownAnchored], host: {
215
+ '[attr.data-appearance]': 'appearance',
257
216
  '[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"] }]
217
+ }, 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:auto;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));overscroll-behavior:none;position-try-fallbacks:flip-block,flip-inline,flip-block flip-inline;--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}:host._delegated{scroll-timeline:none}.t-wrapper{z-index:-1;flex:1}.t-wrapper>*{padding:1rem}\n"] }]
259
218
  }] });
260
219
 
261
220
  /**
@@ -297,20 +256,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
297
256
  args: [{ selector: '[tuiDropdownA11y]' }]
298
257
  }] });
299
258
 
300
- class TuiDropdownAnchor {
259
+ class TuiDropdownAnchor extends TuiRectAccessor {
301
260
  constructor() {
261
+ super(...arguments);
262
+ this.el = tuiInjectElement();
302
263
  this.anchor = `--${tuiGenerateId()}`;
264
+ this.type = 'dropdown';
303
265
  }
304
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownAnchor, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
266
+ getClientRect() {
267
+ return this.el.getBoundingClientRect();
268
+ }
269
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownAnchor, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
305
270
  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: [
271
+ tuiAsRectAccessor(TuiDropdownAnchor),
306
272
  tuiProvide(TUI_DROPDOWN_HOST, ElementRef),
307
273
  tuiProvide(TUI_DROPDOWN_ANCHOR, ElementRef),
308
- ], ngImport: i0 }); }
274
+ ], usesInheritance: true, ngImport: i0 }); }
309
275
  }
310
276
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownAnchor, decorators: [{
311
277
  type: Directive,
312
278
  args: [{
313
279
  providers: [
280
+ tuiAsRectAccessor(TuiDropdownAnchor),
314
281
  tuiProvide(TUI_DROPDOWN_HOST, ElementRef),
315
282
  tuiProvide(TUI_DROPDOWN_ANCHOR, ElementRef),
316
283
  ],
@@ -321,6 +288,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
321
288
  }]
322
289
  }] });
323
290
 
291
+ class TuiDropdownPosition extends TuiPositionAccessor {
292
+ constructor() {
293
+ super(...arguments);
294
+ this.el = tuiInjectElement();
295
+ this.options = inject(TUI_DROPDOWN_OPTIONS);
296
+ this.viewport = inject(TUI_VIEWPORT);
297
+ this.direction = new Subject();
298
+ this.type = 'dropdown';
299
+ this.accessor = tuiInjectAccessor(TuiRectAccessor, 'dropdown');
300
+ this.tuiDropdownDirectionChange = outputFromObservable(this.direction.pipe(distinctUntilChanged()));
301
+ }
302
+ getPosition({ width, height }) {
303
+ if (!width && !height) {
304
+ this.previous = undefined;
305
+ }
306
+ const hostRect = this.accessor.getClientRect();
307
+ const viewportRect = this.viewport.getClientRect();
308
+ const { minHeight, direction, offset, limitWidth } = this.options;
309
+ const align = this.getAlign(this.options.align);
310
+ const viewport = {
311
+ top: viewportRect.top - offset,
312
+ bottom: viewportRect.bottom + offset,
313
+ right: viewportRect.right - offset,
314
+ left: viewportRect.left + offset,
315
+ };
316
+ const previous = this.previous || direction || 'bottom';
317
+ const available = {
318
+ top: hostRect.top - 2 * offset - viewport.top,
319
+ bottom: viewport.bottom - hostRect.bottom - 2 * offset,
320
+ };
321
+ const rectWidth = limitWidth === 'fixed' ? hostRect.width : width;
322
+ const right = Math.max(hostRect.right - rectWidth, offset);
323
+ const left = hostRect.left + width < viewport.right ? hostRect.left : right;
324
+ const position = {
325
+ top: hostRect.top - offset - height,
326
+ bottom: hostRect.bottom + offset,
327
+ right: Math.max(viewport.left, right),
328
+ center: hostRect.left + hostRect.width / 2 + width / 2 < viewport.right
329
+ ? hostRect.left + hostRect.width / 2 - width / 2
330
+ : right,
331
+ left: Math.max(viewport.left, left),
332
+ };
333
+ const better = available.top > available.bottom ? 'top' : 'bottom';
334
+ if ((available[previous] > minHeight && direction) ||
335
+ available[previous] > height) {
336
+ this.direction.next(previous);
337
+ return [position[align], position[previous]];
338
+ }
339
+ this.previous = better;
340
+ this.direction.next(better);
341
+ return [position[align], position[better]];
342
+ }
343
+ getAlign(align) {
344
+ const rtl = this.el.matches('[dir="rtl"] :scope');
345
+ if (rtl && align === 'start') {
346
+ return 'right';
347
+ }
348
+ if (rtl && align === 'end') {
349
+ return 'left';
350
+ }
351
+ if (align === 'center') {
352
+ return 'center';
353
+ }
354
+ return align === 'end' ? 'right' : 'left';
355
+ }
356
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownPosition, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
357
+ 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 }); }
358
+ }
359
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownPosition, decorators: [{
360
+ type: Directive,
361
+ args: [{ providers: [tuiAsPositionAccessor(TuiDropdownPosition)] }]
362
+ }] });
363
+
324
364
  class TuiDropdownDirective {
325
365
  constructor() {
326
366
  this.injector = inject(INJECTOR);
@@ -350,11 +390,12 @@ class TuiDropdownDirective {
350
390
  : content,
351
391
  });
352
392
  }
393
+ /** @deprecated remove in v6 */
353
394
  get accessor() {
354
395
  const accessors = this.injector.get(TuiRectAccessor, null, {
355
396
  self: true,
356
397
  });
357
- return tuiFallbackAccessor('dropdown')(accessors, this);
398
+ return ([...(accessors || [])].reverse().find(({ type }) => type === 'dropdown') || this);
358
399
  }
359
400
  get position() {
360
401
  return tuiCheckFixedPosition(this.el) ? 'fixed' : 'absolute';
@@ -770,21 +811,21 @@ class TuiDropdownPositionSided extends TuiPositionAccessor {
770
811
  super(...arguments);
771
812
  this.options = inject(TUI_DROPDOWN_OPTIONS);
772
813
  this.viewport = inject(TUI_VIEWPORT);
773
- this.vertical = inject(TuiDropdownPosition);
814
+ this.vertical = inject(TuiDropdownPosition, { optional: true });
774
815
  this.previous = this.options.direction || 'bottom';
775
816
  this.tuiDropdownSided = input('');
776
817
  this.tuiDropdownSidedOffset = input(4);
777
818
  this.type = 'dropdown';
778
819
  }
779
820
  getPosition(rect) {
780
- if (this.tuiDropdownSided() === false) {
821
+ if (this.tuiDropdownSided() === false && this.vertical) {
781
822
  return this.vertical.getPosition(rect);
782
823
  }
783
824
  const { height, width } = rect;
784
- const hostRect = this.vertical.accessor?.getClientRect() ?? EMPTY_CLIENT_RECT;
825
+ const hostRect = this.vertical?.accessor.getClientRect() ?? EMPTY_CLIENT_RECT;
785
826
  const viewport = this.viewport.getClientRect();
786
827
  const { direction, offset } = this.options;
787
- const adjusted = this.vertical.getAlign(this.options.align);
828
+ const adjusted = this.vertical?.getAlign(this.options.align) || 'center';
788
829
  const align = adjusted === 'center' ? 'left' : adjusted;
789
830
  const available = {
790
831
  top: hostRect.bottom - viewport.top,
@@ -803,21 +844,21 @@ class TuiDropdownPositionSided extends TuiPositionAccessor {
803
844
  const left = available[align] > width ? position[align] : maxLeft;
804
845
  if ((available[this.previous] > height && direction) ||
805
846
  this.previous === better) {
806
- this.vertical.direction.next(this.previous);
847
+ this.vertical?.direction.next(this.previous);
807
848
  return [left, position[this.previous]];
808
849
  }
809
850
  this.previous = better;
810
- this.vertical.direction.next(better);
851
+ this.vertical?.direction.next(better);
811
852
  return [left, position[better]];
812
853
  }
813
854
  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 }); }
855
+ 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
856
  }
816
857
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: TuiDropdownPositionSided, decorators: [{
817
858
  type: Directive,
818
859
  args: [{
819
860
  selector: '[tuiDropdownSided]',
820
- providers: [TuiDropdownPosition, tuiAsPositionAccessor(TuiDropdownPositionSided)],
861
+ providers: [tuiAsPositionAccessor(TuiDropdownPositionSided)],
821
862
  }]
822
863
  }] });
823
864