@rt-tools/ui-kit-v2 0.33.0 → 0.34.1

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 (217) hide show
  1. package/README.md +4 -3
  2. package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs +1 -0
  3. package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs.map +1 -1
  4. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs +92 -5
  5. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs.map +1 -1
  6. package/fesm2022/rt-tools-ui-kit-v2-badge.mjs +191 -0
  7. package/fesm2022/rt-tools-ui-kit-v2-badge.mjs.map +1 -0
  8. package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs +3 -2
  9. package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs.map +1 -1
  10. package/fesm2022/rt-tools-ui-kit-v2-button.mjs +6 -1
  11. package/fesm2022/rt-tools-ui-kit-v2-button.mjs.map +1 -1
  12. package/fesm2022/rt-tools-ui-kit-v2-checkbox.mjs +35 -4
  13. package/fesm2022/rt-tools-ui-kit-v2-checkbox.mjs.map +1 -1
  14. package/fesm2022/rt-tools-ui-kit-v2-color-palette.mjs +13 -4
  15. package/fesm2022/rt-tools-ui-kit-v2-color-palette.mjs.map +1 -1
  16. package/fesm2022/rt-tools-ui-kit-v2-container.mjs +245 -60
  17. package/fesm2022/rt-tools-ui-kit-v2-container.mjs.map +1 -1
  18. package/fesm2022/rt-tools-ui-kit-v2-copy-value.mjs +30 -5
  19. package/fesm2022/rt-tools-ui-kit-v2-copy-value.mjs.map +1 -1
  20. package/fesm2022/rt-tools-ui-kit-v2-core.mjs +113 -2
  21. package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -1
  22. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs +14 -3
  23. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs.map +1 -1
  24. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs +17 -3
  25. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs.map +1 -1
  26. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs +6 -3
  27. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs.map +1 -1
  28. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs +2 -2
  29. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs.map +1 -1
  30. package/fesm2022/rt-tools-ui-kit-v2-divider.mjs +112 -0
  31. package/fesm2022/rt-tools-ui-kit-v2-divider.mjs.map +1 -0
  32. package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs +1 -0
  33. package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs.map +1 -1
  34. package/fesm2022/rt-tools-ui-kit-v2-drawer.mjs +854 -0
  35. package/fesm2022/rt-tools-ui-kit-v2-drawer.mjs.map +1 -0
  36. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs +16 -5
  37. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs.map +1 -1
  38. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +580 -65
  39. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -1
  40. package/fesm2022/rt-tools-ui-kit-v2-expansion-panel.mjs +203 -15
  41. package/fesm2022/rt-tools-ui-kit-v2-expansion-panel.mjs.map +1 -1
  42. package/fesm2022/rt-tools-ui-kit-v2-field.mjs +40 -8
  43. package/fesm2022/rt-tools-ui-kit-v2-field.mjs.map +1 -1
  44. package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs +1 -0
  45. package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs.map +1 -1
  46. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs +7 -3
  47. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs.map +1 -1
  48. package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs +53 -2
  49. package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs.map +1 -1
  50. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs +14 -4
  51. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs.map +1 -1
  52. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs +6 -3
  53. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs.map +1 -1
  54. package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs +16 -5
  55. package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs.map +1 -1
  56. package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs +1 -0
  57. package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs.map +1 -1
  58. package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs +14 -4
  59. package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs.map +1 -1
  60. package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs +3 -2
  61. package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs.map +1 -1
  62. package/fesm2022/rt-tools-ui-kit-v2-input.mjs +207 -7
  63. package/fesm2022/rt-tools-ui-kit-v2-input.mjs.map +1 -1
  64. package/fesm2022/rt-tools-ui-kit-v2-menu.mjs +1 -0
  65. package/fesm2022/rt-tools-ui-kit-v2-menu.mjs.map +1 -1
  66. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs +3 -2
  67. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs.map +1 -1
  68. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +2 -0
  69. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -1
  70. package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs +3 -2
  71. package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs.map +1 -1
  72. package/fesm2022/rt-tools-ui-kit-v2-profile-menu.mjs +3 -2
  73. package/fesm2022/rt-tools-ui-kit-v2-profile-menu.mjs.map +1 -1
  74. package/fesm2022/rt-tools-ui-kit-v2-progress-bar.mjs +171 -0
  75. package/fesm2022/rt-tools-ui-kit-v2-progress-bar.mjs.map +1 -0
  76. package/fesm2022/rt-tools-ui-kit-v2-radio-button.mjs +176 -6
  77. package/fesm2022/rt-tools-ui-kit-v2-radio-button.mjs.map +1 -1
  78. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +2 -1
  79. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  80. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs +1 -0
  81. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs.map +1 -1
  82. package/fesm2022/rt-tools-ui-kit-v2-select.mjs +142 -23
  83. package/fesm2022/rt-tools-ui-kit-v2-select.mjs.map +1 -1
  84. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +22 -9
  85. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -1
  86. package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs +3 -2
  87. package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs.map +1 -1
  88. package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs +105 -8
  89. package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs.map +1 -1
  90. package/fesm2022/rt-tools-ui-kit-v2-table.mjs +13 -2
  91. package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
  92. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +654 -43
  93. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -1
  94. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +1 -0
  95. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -1
  96. package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs +45 -7
  97. package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs.map +1 -1
  98. package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs +2 -2
  99. package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs.map +1 -1
  100. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +11 -2
  101. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -1
  102. package/fesm2022/rt-tools-ui-kit-v2-toast.mjs +152 -11
  103. package/fesm2022/rt-tools-ui-kit-v2-toast.mjs.map +1 -1
  104. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs +199 -17
  105. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs.map +1 -1
  106. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs +35 -5
  107. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs.map +1 -1
  108. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs +14 -4
  109. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs.map +1 -1
  110. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs +6 -3
  111. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs.map +1 -1
  112. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs +21 -6
  113. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs.map +1 -1
  114. package/fesm2022/rt-tools-ui-kit-v2.mjs +4 -0
  115. package/package.json +17 -1
  116. package/src/assets/icons/volume-off.svg +2 -1
  117. package/src/lib/components/autocomplete/CONTEXT.md +25 -14
  118. package/src/lib/components/autocomplete/rt-autocomplete.component.scss +19 -0
  119. package/src/lib/components/badge/CONTEXT.md +33 -0
  120. package/src/lib/components/badge/rt-badge.directive.scss +104 -0
  121. package/src/lib/components/breadcrumbs/rt-breadcrumbs.component.scss +2 -2
  122. package/src/lib/components/button/CONTEXT.md +5 -0
  123. package/src/lib/components/button/rt-button.directive.scss +3 -1
  124. package/src/lib/components/checkbox/CONTEXT.md +15 -8
  125. package/src/lib/components/color-palette/rt-color-palette.component.scss +2 -2
  126. package/src/lib/components/container/CONTEXT.md +23 -6
  127. package/src/lib/components/container/rt-container.component.scss +90 -1
  128. package/src/lib/components/copy-value/CONTEXT.md +6 -5
  129. package/src/lib/components/copy-value/rt-copy-value.component.scss +16 -0
  130. package/src/lib/components/date-picker/rt-date-picker.component.scss +7 -0
  131. package/src/lib/components/date-range/rt-date-range.component.scss +7 -0
  132. package/src/lib/components/divider/CONTEXT.md +21 -0
  133. package/src/lib/components/divider/rt-divider.component.scss +34 -0
  134. package/src/lib/components/drawer/CONTEXT.md +73 -0
  135. package/src/lib/components/drawer/rt-drawer-container.component.scss +19 -0
  136. package/src/lib/components/drawer/rt-drawer.component.scss +168 -0
  137. package/src/lib/components/drawer/rt-resize-handle.component.scss +42 -0
  138. package/src/lib/components/dynamic-selector/CONTEXT.md +5 -0
  139. package/src/lib/components/expansion-panel/CONTEXT.md +32 -8
  140. package/src/lib/components/expansion-panel/rt-expansion-panel.component.scss +67 -2
  141. package/src/lib/components/field/CONTEXT.md +43 -0
  142. package/src/lib/components/field/rt-field-label-inside.scss +179 -0
  143. package/src/lib/components/field/rt-field.component.scss +51 -2
  144. package/src/lib/components/icon-button/CONTEXT.md +17 -15
  145. package/src/lib/components/icon-button/rt-icon-button.component.scss +3 -1
  146. package/src/lib/components/inline-edit/rt-inline-edit.component.scss +4 -4
  147. package/src/lib/components/input/CONTEXT.md +45 -11
  148. package/src/lib/components/input/rt-input-floating-label.scss +192 -0
  149. package/src/lib/components/input/rt-input-icons.scss +105 -0
  150. package/src/lib/components/input/rt-input.component.scss +91 -13
  151. package/src/lib/components/input-number/CONTEXT.md +7 -0
  152. package/src/lib/components/input-number/rt-input-number.component.scss +58 -1
  153. package/src/lib/components/menu/CONTEXT.md +1 -0
  154. package/src/lib/components/multiselect/CONTEXT.md +2 -1
  155. package/src/lib/components/multiselect/rt-multiselect.component.scss +7 -0
  156. package/src/lib/components/pagination/CONTEXT.md +3 -0
  157. package/src/lib/components/pagination/rt-pagination.component.scss +7 -0
  158. package/src/lib/components/progress-bar/CONTEXT.md +22 -0
  159. package/src/lib/components/progress-bar/rt-progress-bar.component.scss +77 -0
  160. package/src/lib/components/radio-button/CONTEXT.md +9 -0
  161. package/src/lib/components/radio-button/rt-radio-group.component.scss +13 -0
  162. package/src/lib/components/select/CONTEXT.md +28 -0
  163. package/src/lib/components/select/rt-select-clear.scss +88 -0
  164. package/src/lib/components/select/rt-select-floating-label.scss +155 -0
  165. package/src/lib/components/select/rt-select-material.scss +54 -0
  166. package/src/lib/components/select/rt-select.component.scss +54 -16
  167. package/src/lib/components/side-menu/CONTEXT.md +5 -0
  168. package/src/lib/components/speed-menu/rt-speed-menu.component.scss +5 -5
  169. package/src/lib/components/stepper/CONTEXT.md +13 -5
  170. package/src/lib/components/stepper/rt-stepper.component.scss +93 -0
  171. package/src/lib/components/tabs/CONTEXT.md +61 -9
  172. package/src/lib/components/tabs/rt-tabs.component.scss +201 -5
  173. package/src/lib/components/textarea/CONTEXT.md +12 -1
  174. package/src/lib/components/textarea/rt-textarea.component.scss +116 -1
  175. package/src/lib/components/toast/CONTEXT.md +23 -0
  176. package/src/lib/components/toast/rt-toast.component.scss +37 -0
  177. package/src/lib/components/toggle-button-group/CONTEXT.md +24 -4
  178. package/src/lib/components/toggle-button-group/rt-toggle-button-group-chips.scss +151 -0
  179. package/src/lib/components/toggle-button-group/rt-toggle-button-group.component.scss +35 -0
  180. package/src/lib/components/tooltip/CONTEXT.md +7 -1
  181. package/src/lib/components/tree/rt-tree.component.scss +2 -2
  182. package/src/styles/_color-scheme.scss +1 -1
  183. package/src/styles/_density.scss +48 -0
  184. package/src/styles/_index.scss +8 -0
  185. package/src/styles/_preset-material.scss +160 -70
  186. package/src/styles/_primitives.scss +1 -0
  187. package/src/styles/_semantic-navigation.scss +117 -0
  188. package/src/styles/_semantic.scss +29 -98
  189. package/src/styles/_theme-dark.scss +8 -0
  190. package/styles/tokens.css +2066 -1134
  191. package/types/rt-tools-ui-kit-v2-autocomplete.d.ts +34 -0
  192. package/types/rt-tools-ui-kit-v2-badge.d.ts +71 -0
  193. package/types/rt-tools-ui-kit-v2-checkbox.d.ts +17 -3
  194. package/types/rt-tools-ui-kit-v2-container.d.ts +65 -9
  195. package/types/rt-tools-ui-kit-v2-copy-value.d.ts +11 -1
  196. package/types/rt-tools-ui-kit-v2-core.d.ts +109 -4
  197. package/types/rt-tools-ui-kit-v2-divider.d.ts +29 -0
  198. package/types/rt-tools-ui-kit-v2-drawer.d.ts +257 -0
  199. package/types/rt-tools-ui-kit-v2-dynamic-selector.d.ts +240 -25
  200. package/types/rt-tools-ui-kit-v2-expansion-panel.d.ts +87 -3
  201. package/types/rt-tools-ui-kit-v2-field.d.ts +18 -1
  202. package/types/rt-tools-ui-kit-v2-form-control.d.ts +42 -4
  203. package/types/rt-tools-ui-kit-v2-icon-button.d.ts +2 -1
  204. package/types/rt-tools-ui-kit-v2-input-number.d.ts +1 -0
  205. package/types/rt-tools-ui-kit-v2-input.d.ts +98 -4
  206. package/types/rt-tools-ui-kit-v2-progress-bar.d.ts +53 -0
  207. package/types/rt-tools-ui-kit-v2-radio-button.d.ts +80 -1
  208. package/types/rt-tools-ui-kit-v2-select.d.ts +65 -1
  209. package/types/rt-tools-ui-kit-v2-side-menu.d.ts +3 -0
  210. package/types/rt-tools-ui-kit-v2-stepper.d.ts +57 -4
  211. package/types/rt-tools-ui-kit-v2-tabs.d.ts +337 -8
  212. package/types/rt-tools-ui-kit-v2-textarea.d.ts +16 -0
  213. package/types/rt-tools-ui-kit-v2-toast.d.ts +38 -2
  214. package/types/rt-tools-ui-kit-v2-toggle-button-group.d.ts +83 -3
  215. package/types/rt-tools-ui-kit-v2-tooltip.d.ts +17 -2
  216. package/types/rt-tools-ui-kit-v2.d.ts +4 -0
  217. package/src/lib/components/dynamic-selector/stories/component/test-dynamic-selector-popup-frame.component.scss +0 -6
@@ -1,6 +1,6 @@
1
1
  import { DOCUMENT, NgTemplateOutlet } from "@angular/common";
2
2
  import * as i0 from "@angular/core";
3
- import { ChangeDetectionStrategy, Component, DestroyRef, Directive, TemplateRef, ViewEncapsulation, afterNextRender, booleanAttribute, computed, contentChildren, inject, input, output, signal, viewChild } from "@angular/core";
3
+ import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, Injector, TemplateRef, ViewEncapsulation, afterNextRender, afterRenderEffect, booleanAttribute, computed, contentChildren, inject, input, linkedSignal, output, signal, untracked, viewChild } from "@angular/core";
4
4
  import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
5
5
  import { debounceTime, fromEvent } from "rxjs";
6
6
  import { BlockDirective, ElemDirective, ModDirective } from "@rt-tools/core";
@@ -10,6 +10,7 @@ import { rtKitLabel } from "@rt-tools/ui-kit-v2/core";
10
10
  var RtTabDirective = class RtTabDirective {
11
11
  constructor() {
12
12
  this.#t_uiTabInvalid = rtKitLabel("uiTabInvalid");
13
+ this.#t_uiClose = rtKitLabel("uiClose");
13
14
  this.templateRef = inject(TemplateRef);
14
15
  this.id = input("", {
15
16
  ...ngDevMode ? { debugName: "id" } : /* istanbul ignore next */ {},
@@ -18,6 +19,7 @@ var RtTabDirective = class RtTabDirective {
18
19
  this.label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
19
20
  this.titleTemplate = input(null, ...ngDevMode ? [{ debugName: "titleTemplate" }] : /* istanbul ignore next */ []);
20
21
  this.icon = input(null, ...ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []);
22
+ this.glyph = input(null, ...ngDevMode ? [{ debugName: "glyph" }] : /* istanbul ignore next */ []);
21
23
  this.iconColor = input("current", ...ngDevMode ? [{ debugName: "iconColor" }] : /* istanbul ignore next */ []);
22
24
  this.badge = input(null, ...ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []);
23
25
  this.badgeTitle = input("", ...ngDevMode ? [{ debugName: "badgeTitle" }] : /* istanbul ignore next */ []);
@@ -35,9 +37,25 @@ var RtTabDirective = class RtTabDirective {
35
37
  transform: booleanAttribute
36
38
  });
37
39
  this.invalidMessage = input("", ...ngDevMode ? [{ debugName: "invalidMessage" }] : /* istanbul ignore next */ []);
40
+ this.tooltip = input("", ...ngDevMode ? [{ debugName: "tooltip" }] : /* istanbul ignore next */ []);
41
+ this.closable = input(false, {
42
+ ...ngDevMode ? { debugName: "closable" } : /* istanbul ignore next */ {},
43
+ transform: booleanAttribute
44
+ });
45
+ this.closeTooltip = input("", ...ngDevMode ? [{ debugName: "closeTooltip" }] : /* istanbul ignore next */ []);
46
+ this.closeTooltipPlacement = input(null, ...ngDevMode ? [{ debugName: "closeTooltipPlacement" }] : /* istanbul ignore next */ []);
47
+ this.closeHovered = signal(false, ...ngDevMode ? [{ debugName: "closeHovered" }] : /* istanbul ignore next */ []);
38
48
  this.invalidTitle = computed(() => this.invalidMessage() || this.#t_uiTabInvalid(), ...ngDevMode ? [{ debugName: "invalidTitle" }] : /* istanbul ignore next */ []);
49
+ this.buttonTooltip = computed(() => {
50
+ if (this.closeHovered() && this.showClose()) return "";
51
+ return this.invalid() ? this.invalidTitle() : this.tooltip();
52
+ }, ...ngDevMode ? [{ debugName: "buttonTooltip" }] : /* istanbul ignore next */ []);
53
+ this.ariaLabel = computed(() => this.label() || this.titleTemplate() ? null : this.tooltip() || null, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
54
+ this.closeLabel = computed(() => this.closeTooltip() || this.#t_uiClose(), ...ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []);
55
+ this.showClose = computed(() => this.closable() && !this.disabled(), ...ngDevMode ? [{ debugName: "showClose" }] : /* istanbul ignore next */ []);
39
56
  }
40
57
  #t_uiTabInvalid;
58
+ #t_uiClose;
41
59
  static {
42
60
  this.ɵfac = i0.ɵɵngDeclareFactory({
43
61
  minVersion: "12.0.0",
@@ -84,6 +102,13 @@ var RtTabDirective = class RtTabDirective {
84
102
  isRequired: false,
85
103
  transformFunction: null
86
104
  },
105
+ glyph: {
106
+ classPropertyName: "glyph",
107
+ publicName: "glyph",
108
+ isSignal: true,
109
+ isRequired: false,
110
+ transformFunction: null
111
+ },
87
112
  iconColor: {
88
113
  classPropertyName: "iconColor",
89
114
  publicName: "iconColor",
@@ -139,6 +164,34 @@ var RtTabDirective = class RtTabDirective {
139
164
  isSignal: true,
140
165
  isRequired: false,
141
166
  transformFunction: null
167
+ },
168
+ tooltip: {
169
+ classPropertyName: "tooltip",
170
+ publicName: "tooltip",
171
+ isSignal: true,
172
+ isRequired: false,
173
+ transformFunction: null
174
+ },
175
+ closable: {
176
+ classPropertyName: "closable",
177
+ publicName: "closable",
178
+ isSignal: true,
179
+ isRequired: false,
180
+ transformFunction: null
181
+ },
182
+ closeTooltip: {
183
+ classPropertyName: "closeTooltip",
184
+ publicName: "closeTooltip",
185
+ isSignal: true,
186
+ isRequired: false,
187
+ transformFunction: null
188
+ },
189
+ closeTooltipPlacement: {
190
+ classPropertyName: "closeTooltipPlacement",
191
+ publicName: "closeTooltipPlacement",
192
+ isSignal: true,
193
+ isRequired: false,
194
+ transformFunction: null
142
195
  }
143
196
  },
144
197
  ngImport: i0
@@ -187,6 +240,14 @@ i0.ɵɵngDeclareClassMetadata({
187
240
  required: false
188
241
  }]
189
242
  }],
243
+ glyph: [{
244
+ type: i0.Input,
245
+ args: [{
246
+ isSignal: true,
247
+ alias: "glyph",
248
+ required: false
249
+ }]
250
+ }],
190
251
  iconColor: [{
191
252
  type: i0.Input,
192
253
  args: [{
@@ -250,9 +311,371 @@ i0.ɵɵngDeclareClassMetadata({
250
311
  alias: "invalidMessage",
251
312
  required: false
252
313
  }]
314
+ }],
315
+ tooltip: [{
316
+ type: i0.Input,
317
+ args: [{
318
+ isSignal: true,
319
+ alias: "tooltip",
320
+ required: false
321
+ }]
322
+ }],
323
+ closable: [{
324
+ type: i0.Input,
325
+ args: [{
326
+ isSignal: true,
327
+ alias: "closable",
328
+ required: false
329
+ }]
330
+ }],
331
+ closeTooltip: [{
332
+ type: i0.Input,
333
+ args: [{
334
+ isSignal: true,
335
+ alias: "closeTooltip",
336
+ required: false
337
+ }]
338
+ }],
339
+ closeTooltipPlacement: [{
340
+ type: i0.Input,
341
+ args: [{
342
+ isSignal: true,
343
+ alias: "closeTooltipPlacement",
344
+ required: false
345
+ }]
253
346
  }]
254
347
  }
255
348
  });
349
+ function rtTabsCssDuration(value) {
350
+ const text = value === null ? "" : String(value).trim();
351
+ if (!text) return null;
352
+ return /^\d+(\.\d+)?$/.test(text) ? `${text}ms` : text;
353
+ }
354
+ function rtTabsDurationMs(value) {
355
+ const text = value.trim();
356
+ const amount = parseFloat(text);
357
+ if (Number.isNaN(amount)) return 0;
358
+ if (text.endsWith("ms")) return amount;
359
+ return text.endsWith("s") ? amount * 1e3 : amount;
360
+ }
361
+ function withVisited(visited, id) {
362
+ return id === null || visited.has(id) ? visited : /* @__PURE__ */ new Set([...visited, id]);
363
+ }
364
+ function sameInkBox(a, b) {
365
+ if (a === null || b === null) return a === b;
366
+ return a.x === b.x && a.bottom === b.bottom && a.width === b.width;
367
+ }
368
+ function rtTabsLeavingPanel(host, win, ids, move) {
369
+ const { previous, next } = move;
370
+ if (previous === null || next === null || previous === next || !win) return null;
371
+ if (win.matchMedia?.("(prefers-reduced-motion: reduce)").matches) return null;
372
+ const duration = move.duration ?? win.getComputedStyle(host).getPropertyValue("--rt-tabs-panel-duration");
373
+ const panel = Array.from(host.querySelectorAll(":scope > .rt-tabs__content")).find((node) => node.id === `rt-tabpanel-${previous}`);
374
+ if (!panel || rtTabsDurationMs(duration) <= 0) return null;
375
+ const hostBox = host.getBoundingClientRect();
376
+ const panelBox = panel.getBoundingClientRect();
377
+ return {
378
+ id: previous,
379
+ shift: ids.indexOf(next) > ids.indexOf(previous) ? "forward" : "backward",
380
+ top: panelBox.top - hostBox.top - host.clientTop,
381
+ left: panelBox.left - hostBox.left - host.clientLeft
382
+ };
383
+ }
384
+ function rtTabsPreservedPanels(all, visited, active, leaving) {
385
+ return all.filter((tab) => tab === active || visited.has(tab.id())).map((tab) => {
386
+ if (tab === active) return {
387
+ leaving: null,
388
+ idle: false,
389
+ tab
390
+ };
391
+ const isLeaving = leaving !== null && leaving.id === tab.id();
392
+ return {
393
+ leaving: isLeaving ? leaving : null,
394
+ idle: !isLeaving,
395
+ tab
396
+ };
397
+ });
398
+ }
399
+ var RtTabsPanels = class {
400
+ #visited;
401
+ constructor(host, win, tabs, shown) {
402
+ this.duration = computed(() => rtTabsCssDuration(shown.duration()), ...ngDevMode ? [{ debugName: "duration" }] : /* istanbul ignore next */ []);
403
+ this.durations = computed(() => {
404
+ const duration = this.duration();
405
+ return duration === null ? null : {
406
+ "--rt-tabs-indicator-duration": duration,
407
+ "--rt-tabs-panel-duration": duration
408
+ };
409
+ }, ...ngDevMode ? [{ debugName: "durations" }] : /* istanbul ignore next */ []);
410
+ const ids = () => tabs.visible().map((tab) => tab.id());
411
+ this.leaving = linkedSignal({
412
+ ...ngDevMode ? { debugName: "leaving" } : /* istanbul ignore next */ {},
413
+ source: tabs.selectedId,
414
+ computation: (id, previous) => untracked(() => rtTabsLeavingPanel(host, win, ids(), {
415
+ previous: previous?.source ?? null,
416
+ next: id,
417
+ duration: this.duration()
418
+ }))
419
+ });
420
+ this.#visited = linkedSignal({
421
+ ...ngDevMode ? { debugName: "#visited" } : /* istanbul ignore next */ {},
422
+ source: tabs.selectedId,
423
+ computation: (id, previous) => withVisited(previous?.value ?? /* @__PURE__ */ new Set(), id)
424
+ });
425
+ this.list = computed(() => {
426
+ const active = shown.active();
427
+ const leaving = this.leaving();
428
+ if (!active) return [];
429
+ if (shown.preserve()) return rtTabsPreservedPanels(tabs.all(), this.#visited(), active, leaving);
430
+ const current = {
431
+ tab: active,
432
+ leaving: null,
433
+ idle: false
434
+ };
435
+ const leavingTab = leaving === null || leaving.id === active.id() ? void 0 : tabs.visible().find((tab) => tab.id() === leaving.id);
436
+ return leaving && leavingTab ? [{
437
+ leaving,
438
+ idle: false,
439
+ tab: leavingTab
440
+ }, current] : [current];
441
+ }, ...ngDevMode ? [{ debugName: "list" }] : /* istanbul ignore next */ []);
442
+ this.shift = computed(() => this.list().some((panel) => panel.leaving !== null) ? this.leaving()?.shift ?? null : null, ...ngDevMode ? [{ debugName: "shift" }] : /* istanbul ignore next */ []);
443
+ }
444
+ animationEnd(event) {
445
+ if (event.target === event.currentTarget) this.leaving.set(null);
446
+ }
447
+ };
448
+ var RtTabsInk = class {
449
+ #win;
450
+ #list;
451
+ #active;
452
+ #watch;
453
+ constructor(win, list, tabs) {
454
+ this.#watch = null;
455
+ this.box = signal(null, {
456
+ ...ngDevMode ? { debugName: "box" } : /* istanbul ignore next */ {},
457
+ equal: sameInkBox
458
+ });
459
+ this.animated = signal(false, ...ngDevMode ? [{ debugName: "animated" }] : /* istanbul ignore next */ []);
460
+ this.translate = computed(() => {
461
+ const box = this.box();
462
+ return box ? `${box.x}px ${box.bottom}px` : null;
463
+ }, ...ngDevMode ? [{ debugName: "translate" }] : /* istanbul ignore next */ []);
464
+ this.invalid = computed(() => this.#active()?.invalid() ?? false, ...ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []);
465
+ this.#win = win;
466
+ this.#list = list;
467
+ this.#active = tabs.active;
468
+ afterRenderEffect(() => {
469
+ tabs.visible();
470
+ this.#active();
471
+ this.#watchSizes();
472
+ this.#place();
473
+ });
474
+ inject(DestroyRef).onDestroy(() => this.#watch?.disconnect());
475
+ }
476
+ #watchSizes() {
477
+ const list = this.#list()?.nativeElement;
478
+ if (!list || typeof ResizeObserver === "undefined") return;
479
+ if (!this.#watch) this.#watch = new ResizeObserver(() => this.#place());
480
+ const watch = this.#watch;
481
+ watch.disconnect();
482
+ watch.observe(list);
483
+ list.querySelectorAll("[data-tabitem]").forEach((node) => watch.observe(node));
484
+ }
485
+ #place() {
486
+ const list = this.#list()?.nativeElement;
487
+ const id = this.#active()?.id();
488
+ const tab = id === void 0 ? null : list?.querySelector(`[data-tabitem="${id}"]`);
489
+ if (!list || !tab) {
490
+ this.box.set(null);
491
+ return;
492
+ }
493
+ const listBox = list.getBoundingClientRect();
494
+ const tabBox = tab.getBoundingClientRect();
495
+ this.box.set({
496
+ x: tabBox.left - listBox.left - list.clientLeft + list.scrollLeft,
497
+ bottom: tabBox.bottom - listBox.top - list.clientTop + list.scrollTop,
498
+ width: tabBox.width
499
+ });
500
+ if (!untracked(this.animated)) this.#win?.requestAnimationFrame(() => this.animated.set(true));
501
+ }
502
+ };
503
+ const EASE_OUT = [
504
+ 0,
505
+ 0,
506
+ .58,
507
+ 1
508
+ ];
509
+ const NAMED_EASINGS = /* @__PURE__ */ new Map([
510
+ ["linear", [
511
+ 0,
512
+ 0,
513
+ 1,
514
+ 1
515
+ ]],
516
+ ["ease", [
517
+ .25,
518
+ .1,
519
+ .25,
520
+ 1
521
+ ]],
522
+ ["ease-in", [
523
+ .42,
524
+ 0,
525
+ 1,
526
+ 1
527
+ ]],
528
+ ["ease-out", EASE_OUT],
529
+ ["ease-in-out", [
530
+ .42,
531
+ 0,
532
+ .58,
533
+ 1
534
+ ]]
535
+ ]);
536
+ const HOLD_STEP = 12;
537
+ const FIXED_STEP = 80;
538
+ const STEP_SHARE = {
539
+ page: 1,
540
+ third: 1 / 3
541
+ };
542
+ function bezierAt(t, p1, p2) {
543
+ const u = 1 - t;
544
+ return 3 * u * u * t * p1 + 3 * u * t * t * p2 + t * t * t;
545
+ }
546
+ function rtTabsEasing(value) {
547
+ const text = value.trim();
548
+ const match = /^cubic-bezier\(([^)]*)\)$/.exec(text);
549
+ const parsed = match ? match[1].split(",").map((part) => parseFloat(part)) : [];
550
+ const [x1, y1, x2, y2] = parsed.length === 4 && parsed.every((point) => Number.isFinite(point)) ? parsed : NAMED_EASINGS.get(text) ?? EASE_OUT;
551
+ return (progress) => {
552
+ if (progress <= 0 || progress >= 1) return Math.min(1, Math.max(0, progress));
553
+ let low = 0;
554
+ let high = 1;
555
+ for (let step = 0; step < 30; step++) {
556
+ const mid = (low + high) / 2;
557
+ if (bezierAt(mid, x1, x2) < progress) low = mid;
558
+ else high = mid;
559
+ }
560
+ return bezierAt((low + high) / 2, y1, y2);
561
+ };
562
+ }
563
+ function rtTabsPageTarget(list, from, back, step) {
564
+ const max = Math.max(0, list.scrollWidth - list.clientWidth);
565
+ const shift = step === "fixed" ? FIXED_STEP : list.clientWidth * STEP_SHARE[step];
566
+ return Math.min(max, Math.max(0, from + (back ? -shift : shift)));
567
+ }
568
+ function rtTabsIntoViewTarget(list, tab, inset = 0) {
569
+ const left = tab.offsetLeft;
570
+ const right = left + tab.offsetWidth;
571
+ const before = left > 0 ? inset : 0;
572
+ const after = list.scrollWidth - right > 1 ? inset : 0;
573
+ if (left - before < list.scrollLeft) return Math.max(left - before, 0);
574
+ if (right + after > list.scrollLeft + list.clientWidth) return right + after - list.clientWidth;
575
+ return null;
576
+ }
577
+ var RtTabsScroller = class {
578
+ #win;
579
+ #host;
580
+ #list;
581
+ #frame = null;
582
+ #target = null;
583
+ constructor(win, host, list) {
584
+ this.#win = win;
585
+ this.#host = host;
586
+ this.#list = list;
587
+ }
588
+ from() {
589
+ return this.#target ?? this.#list()?.nativeElement.scrollLeft ?? 0;
590
+ }
591
+ to(left) {
592
+ const list = this.#list()?.nativeElement;
593
+ const win = this.#win;
594
+ this.stop();
595
+ if (!list || !win) return;
596
+ const style = win.getComputedStyle(this.#host);
597
+ const duration = win.matchMedia?.("(prefers-reduced-motion: reduce)").matches ? 0 : rtTabsDurationMs(style.getPropertyValue("--rt-tabs-scroll-duration"));
598
+ const start = list.scrollLeft;
599
+ if (duration <= 0 || start === left) {
600
+ list.scrollLeft = left;
601
+ return;
602
+ }
603
+ const ease = rtTabsEasing(style.getPropertyValue("--rt-tabs-scroll-easing"));
604
+ const startedAt = win.performance.now();
605
+ this.#target = left;
606
+ const tick = (now) => {
607
+ const progress = Math.min(1, (now - startedAt) / duration);
608
+ list.scrollLeft = start + (left - start) * ease(progress);
609
+ this.#frame = progress < 1 ? win.requestAnimationFrame(tick) : null;
610
+ if (this.#frame === null) this.#target = null;
611
+ };
612
+ this.#frame = win.requestAnimationFrame(tick);
613
+ }
614
+ nudge(back) {
615
+ this.stop();
616
+ const list = this.#list()?.nativeElement;
617
+ if (!list) return false;
618
+ const remaining = back ? list.scrollLeft : list.scrollWidth - list.scrollLeft - list.clientWidth;
619
+ if (remaining > 0) list.scrollLeft += (back ? -1 : 1) * Math.min(HOLD_STEP, remaining);
620
+ return remaining - HOLD_STEP > 0;
621
+ }
622
+ stop() {
623
+ if (this.#frame !== null) this.#win?.cancelAnimationFrame(this.#frame);
624
+ this.#frame = null;
625
+ this.#target = null;
626
+ }
627
+ };
628
+ const SCROLL_TICK_MS = 15;
629
+ const HOLD_DELAY_MS = 300;
630
+ var RtTabsArrowPress = class {
631
+ #win;
632
+ #scroller;
633
+ #list;
634
+ #step;
635
+ #moved;
636
+ #scrollIntervalId = null;
637
+ #holdTimeoutId = null;
638
+ #pressed = null;
639
+ constructor(win, scroller, list, step, moved) {
640
+ this.#win = win;
641
+ this.#scroller = scroller;
642
+ this.#list = list;
643
+ this.#step = step;
644
+ this.#moved = moved;
645
+ }
646
+ down(direction) {
647
+ if (this.#pressed !== null || !this.#win) return;
648
+ this.#pressed = direction;
649
+ this.#holdTimeoutId = this.#win.setTimeout(() => {
650
+ this.#holdTimeoutId = null;
651
+ this.#scrollIntervalId = this.#win?.setInterval(() => {
652
+ if (!this.#scroller.nudge(direction === "before")) this.stop();
653
+ this.#moved();
654
+ }, SCROLL_TICK_MS) ?? null;
655
+ }, HOLD_DELAY_MS);
656
+ }
657
+ up() {
658
+ const direction = this.#pressed;
659
+ const shortPress = this.#holdTimeoutId !== null;
660
+ const list = this.#list();
661
+ this.stop();
662
+ if (direction !== null && shortPress && list) {
663
+ this.#scroller.to(rtTabsPageTarget(list, this.#scroller.from(), direction === "before", this.#step()));
664
+ this.#moved();
665
+ }
666
+ }
667
+ stop() {
668
+ this.#pressed = null;
669
+ if (this.#win && this.#holdTimeoutId !== null) {
670
+ this.#win.clearTimeout(this.#holdTimeoutId);
671
+ this.#holdTimeoutId = null;
672
+ }
673
+ if (this.#win && this.#scrollIntervalId !== null) {
674
+ this.#win.clearInterval(this.#scrollIntervalId);
675
+ this.#scrollIntervalId = null;
676
+ }
677
+ }
678
+ };
256
679
  var RtTabsControlDirective = class RtTabsControlDirective {
257
680
  constructor() {
258
681
  this.templateRef = inject(TemplateRef);
@@ -308,16 +731,20 @@ i0.ɵɵngDeclareClassMetadata({
308
731
  }]
309
732
  }] }
310
733
  });
311
- const SCROLL_STEP = 12;
312
- const SCROLL_TICK_MS = 15;
313
734
  const REST_DEBOUNCE_MS = 50;
314
735
  const BEM_BLOCK = "rt-tabs";
315
736
  var RtTabsComponent = class RtTabsComponent {
316
737
  #win;
738
+ #host;
739
+ #injector;
740
+ #scroller;
317
741
  #internalId;
318
- #scrollIntervalId;
742
+ #focusedId;
743
+ #press;
744
+ #scrolledId;
319
745
  constructor() {
320
746
  this.#win = inject(DOCUMENT).defaultView;
747
+ this.#host = inject(ElementRef).nativeElement;
321
748
  this.tabs = contentChildren(RtTabDirective, ...ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []);
322
749
  this.controls = contentChildren(RtTabsControlDirective, ...ngDevMode ? [{ debugName: "controls" }] : /* istanbul ignore next */ []);
323
750
  this.visibleTabs = computed(() => this.tabs().filter((tab) => !tab.hidden()), ...ngDevMode ? [{ debugName: "visibleTabs" }] : /* istanbul ignore next */ []);
@@ -334,9 +761,27 @@ var RtTabsComponent = class RtTabsComponent {
334
761
  return result;
335
762
  }, ...ngDevMode ? [{ debugName: "selectedId" }] : /* istanbul ignore next */ []);
336
763
  this.activeTab = computed(() => this.visibleTabs().find((tab) => tab.id() === this.selectedId()) ?? null, ...ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []);
764
+ this.focusId = computed(() => {
765
+ const focused = this.#focusedId();
766
+ return focused !== null && this.visibleTabs().some((tab) => tab.id() === focused && !tab.disabled()) ? focused : this.selectedId();
767
+ }, ...ngDevMode ? [{ debugName: "focusId" }] : /* istanbul ignore next */ []);
337
768
  this.restBeforeVisible = signal(false, ...ngDevMode ? [{ debugName: "restBeforeVisible" }] : /* istanbul ignore next */ []);
338
769
  this.restAfterVisible = signal(false, ...ngDevMode ? [{ debugName: "restAfterVisible" }] : /* istanbul ignore next */ []);
770
+ this.overflowing = computed(() => this.restBeforeVisible() || this.restAfterVisible(), ...ngDevMode ? [{ debugName: "overflowing" }] : /* istanbul ignore next */ []);
339
771
  this.tabListRef = viewChild("tabList", ...ngDevMode ? [{ debugName: "tabListRef" }] : /* istanbul ignore next */ []);
772
+ this.panels = new RtTabsPanels(this.#host, this.#win, {
773
+ all: this.tabs,
774
+ visible: this.visibleTabs,
775
+ selectedId: this.selectedId
776
+ }, {
777
+ active: computed(() => this.headerOnly() ? null : this.activeTab()),
778
+ duration: () => this.animationDuration(),
779
+ preserve: () => this.preserveContent()
780
+ });
781
+ this.ink = new RtTabsInk(this.#win, this.tabListRef, {
782
+ visible: this.visibleTabs,
783
+ active: this.activeTab
784
+ });
340
785
  this.activeId = input(null, ...ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []);
341
786
  this.direction = input("horizontal", ...ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []);
342
787
  this.stretch = input(false, {
@@ -347,27 +792,61 @@ var RtTabsComponent = class RtTabsComponent {
347
792
  ...ngDevMode ? { debugName: "contentScrollable" } : /* istanbul ignore next */ {},
348
793
  transform: booleanAttribute
349
794
  });
795
+ this.headerOnly = input(false, {
796
+ ...ngDevMode ? { debugName: "headerOnly" } : /* istanbul ignore next */ {},
797
+ transform: booleanAttribute
798
+ });
799
+ this.preserveContent = input(false, {
800
+ ...ngDevMode ? { debugName: "preserveContent" } : /* istanbul ignore next */ {},
801
+ transform: booleanAttribute
802
+ });
803
+ this.activation = input("auto", ...ngDevMode ? [{ debugName: "activation" }] : /* istanbul ignore next */ []);
804
+ this.scrollArrows = input("overlay", ...ngDevMode ? [{ debugName: "scrollArrows" }] : /* istanbul ignore next */ []);
805
+ this.scrollStep = input("fixed", ...ngDevMode ? [{ debugName: "scrollStep" }] : /* istanbul ignore next */ []);
806
+ this.animationDuration = input(null, ...ngDevMode ? [{ debugName: "animationDuration" }] : /* istanbul ignore next */ []);
807
+ this.contentTabIndex = input(0, ...ngDevMode ? [{ debugName: "contentTabIndex" }] : /* istanbul ignore next */ []);
350
808
  this.activeIdChange = output();
809
+ this.tabClose = output();
810
+ this.#injector = inject(Injector);
811
+ this.#scroller = new RtTabsScroller(this.#win, this.#host, () => this.tabListRef());
351
812
  this.#internalId = signal(null, ...ngDevMode ? [{ debugName: "#internalId" }] : /* istanbul ignore next */ []);
352
- this.#scrollIntervalId = null;
813
+ this.#focusedId = signal(null, ...ngDevMode ? [{ debugName: "#focusedId" }] : /* istanbul ignore next */ []);
814
+ this.#press = new RtTabsArrowPress(this.#win, this.#scroller, () => this.tabListRef()?.nativeElement, () => this.scrollStep(), () => this.#updateRestVisibility());
815
+ this.#scrolledId = null;
353
816
  if (this.#win) fromEvent(this.#win, "resize").pipe(debounceTime(REST_DEBOUNCE_MS), takeUntilDestroyed()).subscribe(() => this.#updateRestVisibility());
354
- afterNextRender(() => this.#updateRestVisibility());
355
- inject(DestroyRef).onDestroy(() => this.#clearScrollInterval());
817
+ afterNextRender(() => {
818
+ this.#scrollToSelected();
819
+ this.#updateRestVisibility();
820
+ });
821
+ afterRenderEffect(() => this.#scrollToSelected());
822
+ inject(DestroyRef).onDestroy(() => {
823
+ this.#press.stop();
824
+ this.#scroller.stop();
825
+ });
356
826
  }
357
827
  selectTab(id) {
358
828
  const target = this.visibleTabs().find((tab) => tab.id() === id);
359
829
  if (!target || target.disabled()) return;
360
830
  this.#internalId.set(id);
831
+ this.#focusedId.set(null);
361
832
  this.activeIdChange.emit(id);
362
833
  this.#scrollTabIntoView(id);
363
834
  }
364
- onTabKeydown(event) {
365
- const enabled = this.visibleTabs().filter((tab) => !tab.disabled());
835
+ onCloseClick(event, tab) {
836
+ event.stopPropagation();
837
+ this.#close(tab, event.currentTarget instanceof HTMLElement && event.currentTarget.matches(":focus"));
838
+ }
839
+ onTabKeydown(event, tab) {
840
+ if (event.key === "Delete") {
841
+ this.#closeByKey(event, tab);
842
+ return;
843
+ }
844
+ const enabled = this.visibleTabs().filter((item) => !item.disabled());
366
845
  if (!enabled.length) return;
367
846
  const isVertical = this.direction() === "vertical";
368
847
  const nextKey = isVertical ? "ArrowDown" : "ArrowRight";
369
848
  const prevKey = isVertical ? "ArrowUp" : "ArrowLeft";
370
- const currentIndex = enabled.findIndex((tab) => tab.id() === this.selectedId());
849
+ const currentIndex = enabled.findIndex((item) => item.id() === tab.id());
371
850
  const targetIndex = (/* @__PURE__ */ new Map([
372
851
  [nextKey, (currentIndex + 1) % enabled.length],
373
852
  [prevKey, (currentIndex - 1 + enabled.length) % enabled.length],
@@ -377,36 +856,42 @@ var RtTabsComponent = class RtTabsComponent {
377
856
  if (targetIndex === void 0) return;
378
857
  event.preventDefault();
379
858
  const targetId = enabled[targetIndex].id();
380
- this.selectTab(targetId);
859
+ if (this.activation() === "manual") {
860
+ this.#focusedId.set(targetId);
861
+ this.#scrollTabIntoView(targetId);
862
+ } else this.selectTab(targetId);
381
863
  this.#focusTab(targetId);
382
864
  }
383
865
  onRestPointerDown(direction, event) {
384
- if (event.button !== 0 || this.#scrollIntervalId !== null || !this.#win) return;
385
- this.#scrollIntervalId = this.#win.setInterval(() => {
386
- this.#scrollStep(direction);
387
- this.#updateRestVisibility();
388
- }, SCROLL_TICK_MS);
866
+ if (event.button === 0) this.#press.down(direction);
389
867
  }
390
868
  onRestPointerUp() {
391
- this.#clearScrollInterval();
869
+ this.#press.up();
870
+ }
871
+ onRestPointerLeave() {
872
+ this.#press.stop();
392
873
  }
393
874
  onTabListScroll() {
394
875
  this.#updateRestVisibility();
395
876
  }
396
- #clearScrollInterval() {
397
- if (this.#win && this.#scrollIntervalId !== null) {
398
- this.#win.clearInterval(this.#scrollIntervalId);
399
- this.#scrollIntervalId = null;
400
- }
877
+ #closeByKey(event, tab) {
878
+ if (!tab.showClose()) return;
879
+ event.preventDefault();
880
+ this.#close(tab, true);
401
881
  }
402
- #scrollStep(direction) {
403
- const list = this.tabListRef()?.nativeElement;
404
- if (!list) return;
405
- const scrolledLeft = list.scrollLeft;
406
- const scrolledRight = list.scrollWidth - list.scrollLeft - list.clientWidth;
407
- const remaining = direction === "before" ? scrolledLeft : scrolledRight;
408
- if (remaining > 0) list.scrollBy(direction === "before" ? -12 : SCROLL_STEP, 0);
409
- if (remaining - SCROLL_STEP <= 0) this.#clearScrollInterval();
882
+ #close(tab, focus) {
883
+ const closedId = tab.id();
884
+ const wasActive = this.selectedId() === closedId;
885
+ this.tabClose.emit(closedId);
886
+ afterNextRender(() => {
887
+ const id = this.selectedId();
888
+ if (id === null) return;
889
+ if (wasActive && id !== closedId) {
890
+ this.#internalId.set(id);
891
+ this.activeIdChange.emit(id);
892
+ }
893
+ if (focus) this.#focusTab(id);
894
+ }, { injector: this.#injector });
410
895
  }
411
896
  #updateRestVisibility() {
412
897
  const list = this.tabListRef()?.nativeElement;
@@ -419,17 +904,26 @@ var RtTabsComponent = class RtTabsComponent {
419
904
  this.restBeforeVisible.set(list.scrollLeft > 0);
420
905
  this.restAfterVisible.set(scrolledRight > 1);
421
906
  }
907
+ #scrollToSelected() {
908
+ const id = this.selectedId();
909
+ if (id !== null && id !== this.#scrolledId) this.#scrollTabIntoView(id);
910
+ }
422
911
  #scrollTabIntoView(id) {
423
912
  const list = this.tabListRef()?.nativeElement;
424
- const tab = list?.querySelector(`[data-tabid="${id}"]`);
913
+ const tab = list?.querySelector(`[data-tabitem="${id}"]`);
425
914
  if (!list || !tab) return;
426
- const viewLeft = list.scrollLeft;
427
- const viewRight = list.scrollLeft + list.clientWidth;
428
- if (tab.offsetLeft < viewLeft) list.scrollTo({ left: tab.offsetLeft });
429
- else if (tab.offsetLeft + tab.offsetWidth > viewRight) list.scrollTo({ left: tab.offsetLeft + tab.offsetWidth - list.clientWidth });
915
+ const first = this.#scrolledId === null;
916
+ const rest = list.parentElement?.querySelector(".rt-tabs__rest");
917
+ const target = rtTabsIntoViewTarget(list, tab, this.scrollArrows() === "overlay" ? rest?.offsetWidth ?? 0 : 0);
918
+ this.#scrolledId = id;
919
+ if (target !== null && first) {
920
+ this.#scroller.stop();
921
+ list.scrollLeft = target;
922
+ } else if (target !== null) this.#scroller.to(target);
923
+ this.#updateRestVisibility();
430
924
  }
431
925
  #focusTab(id) {
432
- (this.tabListRef()?.nativeElement)?.querySelector(`[data-tabid="${id}"]`)?.focus();
926
+ (this.tabListRef()?.nativeElement)?.querySelector(`[data-tabid="${id}"]`)?.focus({ preventScroll: true });
433
927
  }
434
928
  static {
435
929
  this.ɵfac = i0.ɵɵngDeclareFactory({
@@ -476,13 +970,67 @@ var RtTabsComponent = class RtTabsComponent {
476
970
  isSignal: true,
477
971
  isRequired: false,
478
972
  transformFunction: null
973
+ },
974
+ headerOnly: {
975
+ classPropertyName: "headerOnly",
976
+ publicName: "headerOnly",
977
+ isSignal: true,
978
+ isRequired: false,
979
+ transformFunction: null
980
+ },
981
+ preserveContent: {
982
+ classPropertyName: "preserveContent",
983
+ publicName: "preserveContent",
984
+ isSignal: true,
985
+ isRequired: false,
986
+ transformFunction: null
987
+ },
988
+ activation: {
989
+ classPropertyName: "activation",
990
+ publicName: "activation",
991
+ isSignal: true,
992
+ isRequired: false,
993
+ transformFunction: null
994
+ },
995
+ scrollArrows: {
996
+ classPropertyName: "scrollArrows",
997
+ publicName: "scrollArrows",
998
+ isSignal: true,
999
+ isRequired: false,
1000
+ transformFunction: null
1001
+ },
1002
+ scrollStep: {
1003
+ classPropertyName: "scrollStep",
1004
+ publicName: "scrollStep",
1005
+ isSignal: true,
1006
+ isRequired: false,
1007
+ transformFunction: null
1008
+ },
1009
+ animationDuration: {
1010
+ classPropertyName: "animationDuration",
1011
+ publicName: "animationDuration",
1012
+ isSignal: true,
1013
+ isRequired: false,
1014
+ transformFunction: null
1015
+ },
1016
+ contentTabIndex: {
1017
+ classPropertyName: "contentTabIndex",
1018
+ publicName: "contentTabIndex",
1019
+ isSignal: true,
1020
+ isRequired: false,
1021
+ transformFunction: null
479
1022
  }
480
1023
  },
481
- outputs: { activeIdChange: "activeIdChange" },
1024
+ outputs: {
1025
+ activeIdChange: "activeIdChange",
1026
+ tabClose: "tabClose"
1027
+ },
482
1028
  host: {
483
1029
  properties: {
484
1030
  "class.rt-tabs--direction--horizontal": "direction() === 'horizontal'",
485
- "class.rt-tabs--direction--vertical": "direction() === 'vertical'"
1031
+ "class.rt-tabs--direction--vertical": "direction() === 'vertical'",
1032
+ "class.rt-tabs--animating": "panels.shift() !== null",
1033
+ "style": "panels.durations()"
486
1034
  },
487
1035
  classAttribute: "rt-tabs"
488
1036
  },
@@ -503,8 +1051,8 @@ var RtTabsComponent = class RtTabsComponent {
503
1051
  isSignal: true
504
1052
  }],
505
1053
  ngImport: i0,
506
- template: "<ng-container rtBlock=\"rt-tabs\">\n <div rtElem=\"header\">\n @if (leftControls().length) {\n <div rtElem=\"controls\" [rtMod]=\"{ before: true }\">\n @for (control of leftControls(); track $index) {\n <ng-container [ngTemplateOutlet]=\"control.templateRef\" />\n }\n </div>\n }\n\n <div rtElem=\"tab-list-wrapper\">\n <div\n rtElem=\"rest\"\n qa-dataid=\"tabs-scroll-prev\"\n [rtMod]=\"{ before: true, visible: restBeforeVisible() }\"\n (mousedown)=\"onRestPointerDown('before', $event)\"\n (mouseup)=\"onRestPointerUp()\"\n (mouseleave)=\"onRestPointerUp()\">\n <rt-icon name=\"chevron-left\" color=\"current\" size=\"sm\" />\n </div>\n\n <div\n #tabList\n rtElem=\"tab-list\"\n qa-dataid=\"tabs-tab-list\"\n role=\"tablist\"\n [rtMod]=\"{ stretch: stretch(), direction: direction() }\"\n [attr.aria-orientation]=\"direction()\"\n (scroll)=\"onTabListScroll()\">\n @for (tab of visibleTabs(); track tab.id()) {\n <button\n rtBlock=\"rt-tab-item\"\n qa-dataid=\"tabs-tab\"\n type=\"button\"\n role=\"tab\"\n [rtMod]=\"{\n selected: tab.id() === selectedId(),\n disabled: tab.disabled(),\n invalid: tab.invalid(),\n stretch: stretch(),\n }\"\n [id]=\"'rt-tab-' + tab.id()\"\n [disabled]=\"tab.disabled()\"\n [attr.data-tabid]=\"tab.id()\"\n [attr.aria-selected]=\"tab.id() === selectedId()\"\n [attr.aria-controls]=\"'rt-tabpanel-' + tab.id()\"\n [attr.tabindex]=\"tab.id() === selectedId() ? 0 : -1\"\n [rtTooltip]=\"tab.invalid() ? tab.invalidTitle() : ''\"\n (click)=\"selectTab(tab.id())\"\n (keydown)=\"onTabKeydown($event)\">\n @if (tab.icon(); as icon) {\n <rt-icon rtElem=\"icon\" size=\"sm\" [name]=\"icon\" [color]=\"tab.iconColor()\" />\n }\n\n @if (tab.titleTemplate(); as titleTpl) {\n <ng-container [ngTemplateOutlet]=\"titleTpl\" />\n } @else {\n <span rtElem=\"title\">{{ tab.label() }}</span>\n }\n\n @if (tab.badge() !== null) {\n <!-- В одну строку: перенос внутри добавил бы пробел в текст кнопки. -->\n <!-- prettier-ignore -->\n <span rtElem=\"badge\" [rtTooltip]=\"tab.badgeTitle()\" [attr.aria-label]=\"tab.badgeAriaLabel() || null\">{{ tab.badge() }}</span>\n }\n </button>\n }\n </div>\n\n <div\n rtElem=\"rest\"\n qa-dataid=\"tabs-scroll-next\"\n [rtMod]=\"{ after: true, visible: restAfterVisible() }\"\n (mousedown)=\"onRestPointerDown('after', $event)\"\n (mouseup)=\"onRestPointerUp()\"\n (mouseleave)=\"onRestPointerUp()\">\n <rt-icon name=\"chevron-right\" color=\"current\" size=\"sm\" />\n </div>\n </div>\n\n @if (rightControls().length) {\n <div rtElem=\"controls\" [rtMod]=\"{ after: true }\">\n @for (control of rightControls(); track $index) {\n <ng-container [ngTemplateOutlet]=\"control.templateRef\" />\n }\n </div>\n }\n </div>\n\n @if (activeTab(); as tab) {\n <div\n rtElem=\"content\"\n qa-dataid=\"tabs-panel\"\n role=\"tabpanel\"\n tabindex=\"0\"\n [rtMod]=\"{ scrollable: contentScrollable() }\"\n [id]=\"'rt-tabpanel-' + tab.id()\"\n [attr.aria-labelledby]=\"'rt-tab-' + tab.id()\">\n <ng-container [ngTemplateOutlet]=\"tab.templateRef\" />\n </div>\n }\n</ng-container>\n",
507
- styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-tabs{--rt-tabs-border-width: var(--rt-border-width-thin);--rt-tabs-transition-duration: var(--rt-duration-fast);display:flex;-webkit-tap-highlight-color:transparent}.rt-tabs--direction--horizontal{flex-direction:column}.rt-tabs--direction--vertical{flex-direction:row}.rt-tabs__header{display:flex;align-items:center}.rt-tabs__tab-list-wrapper{position:relative;display:flex;overflow:hidden;flex:1 1 auto;align-items:center}.rt-tabs__tab-list{display:flex;border-bottom:var(--rt-tabs-border-width) solid var(--rt-color-border-default);margin:0;-ms-overflow-style:none;overflow-x:auto;scrollbar-width:none;white-space:nowrap}.rt-tabs__tab-list::-webkit-scrollbar{display:none}.rt-tabs__tab-list--direction--horizontal{width:100%;flex-direction:row}.rt-tabs__tab-list--direction--vertical{flex-direction:column;border-right:var(--rt-tabs-border-width) solid var(--rt-color-border-default);border-bottom:0}.rt-tabs__tab-list--stretch{justify-content:space-between}.rt-tabs__rest{position:absolute;z-index:1;top:0;bottom:0;display:flex;width:var(--rt-control-height-lg);align-items:center;justify-content:center;background-color:var(--rt-color-bg-surface);color:var(--rt-color-text-muted);cursor:pointer;transition:color var(--rt-tabs-transition-duration) linear;visibility:hidden}.rt-tabs__rest:hover{color:var(--rt-color-text-primary)}.rt-tabs__rest--before{left:0;border-right:var(--rt-tabs-border-width) solid var(--rt-color-border-default)}.rt-tabs__rest--after{right:0;border-left:var(--rt-tabs-border-width) solid var(--rt-color-border-default)}.rt-tabs__rest--visible{visibility:visible}.rt-tabs__controls{display:flex;flex-shrink:0;align-items:center}.rt-tabs__controls--before{padding-right:var(--rt-space-md)}.rt-tabs__controls--after{padding-left:var(--rt-space-md)}.rt-tabs__content{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;padding-top:var(--rt-space-md);gap:var(--rt-space-md);line-height:var(--rt-leading-relaxed)}.rt-tabs__content--scrollable{overflow:auto}.rt-tab-item{--rt-tab-item-border-width: var(--rt-border-width-thin);--rt-tab-item-badge-radius: var(--rt-radius-full);--rt-tab-item-transition-duration: var(--rt-duration-fast);position:relative;display:inline-flex;align-items:center;justify-content:center;padding:var(--rt-space-2) var(--rt-space-4);border:0;margin:0;background-color:transparent;color:var(--rt-color-text-muted);cursor:pointer;font-family:inherit;font-size:var(--rt-text-sm);font-weight:var(--rt-font-weight-semibold);gap:var(--rt-space-sm);line-height:var(--rt-leading-none);transition:color var(--rt-tab-item-transition-duration) linear,background-color var(--rt-tab-item-transition-duration) linear;white-space:nowrap}.rt-tab-item:after{position:absolute;bottom:calc(-1 * var(--rt-tab-item-border-width));height:2px;background-color:transparent;content:\"\";inset-inline:0;pointer-events:none}.rt-tab-item:hover:not(.rt-tab-item--disabled,.rt-tab-item--selected){background-color:var(--rt-color-bg-hover);color:var(--rt-color-text-primary)}.rt-tab-item:focus-visible{outline:2px solid var(--rt-color-action-primary);outline-offset:-3px}.rt-tab-item__title{overflow:hidden;max-width:200px;text-overflow:ellipsis}.rt-tab-item__icon{flex-shrink:0}.rt-tab-item__badge{display:inline-flex;min-width:18px;height:18px;align-items:center;justify-content:center;padding:0 var(--rt-space-2);border-radius:var(--rt-tab-item-badge-radius);background-color:var(--rt-color-bg-surface-subtle);color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-medium);line-height:var(--rt-leading-none)}.rt-tab-item--selected{color:var(--rt-color-action-primary);cursor:default}.rt-tab-item--selected:after{background-color:var(--rt-color-action-primary)}.rt-tab-item--selected .rt-tab-item__badge{background-color:var(--rt-color-action-primary-soft);color:var(--rt-color-action-primary)}.rt-tab-item--invalid{color:var(--rt-color-state-danger)}.rt-tab-item--invalid:after{background-color:var(--rt-color-state-danger)}.rt-tab-item--disabled{color:var(--rt-color-text-disabled);cursor:not-allowed}.rt-tab-item--stretch{max-width:100%;flex:1 1 auto}}\n"],
1054
+ template: "<ng-container rtBlock=\"rt-tabs\">\n <div rtElem=\"header\">\n @if (leftControls().length) {\n <div rtElem=\"controls\" [rtMod]=\"{ before: true }\">\n @for (control of leftControls(); track $index) {\n <ng-container [ngTemplateOutlet]=\"control.templateRef\" />\n }\n </div>\n }\n\n <div rtElem=\"tab-list-wrapper\" [rtMod]=\"{ inline: scrollArrows() === 'inline', overflowing: overflowing() }\">\n <div\n rtElem=\"rest\"\n qa-dataid=\"tabs-scroll-prev\"\n [rtMod]=\"{ before: true, visible: restBeforeVisible(), inactive: !restBeforeVisible() }\"\n (mousedown)=\"onRestPointerDown('before', $event)\"\n (mouseup)=\"onRestPointerUp()\"\n (mouseleave)=\"onRestPointerLeave()\">\n <rt-icon name=\"chevron-left\" color=\"current\" size=\"sm\" />\n </div>\n\n <div\n #tabList\n rtElem=\"tab-list\"\n qa-dataid=\"tabs-tab-list\"\n role=\"tablist\"\n [rtMod]=\"{ stretch: stretch(), direction: direction(), ink: ink.box() !== null }\"\n [attr.aria-orientation]=\"direction()\"\n (scroll)=\"onTabListScroll()\">\n @for (tab of visibleTabs(); track tab.id()) {\n @let focusable = tab.id() === focusId();\n <!-- Вкладка — обёртка из двух кнопок: самой вкладки и крестика рядом с ней, не внутри,\n потому что кнопка в кнопке недопустима. Нажатие в любом месте обёртки выбирает\n вкладку; крестик своё нажатие дальше не пускает. -->\n <div\n rtBlock=\"rt-tab-item\"\n role=\"presentation\"\n [rtMod]=\"{\n selected: tab.id() === selectedId(),\n disabled: tab.disabled(),\n invalid: tab.invalid(),\n stretch: stretch(),\n }\"\n [attr.data-tabitem]=\"tab.id()\"\n (click)=\"selectTab(tab.id())\">\n <button\n rtElem=\"trigger\"\n qa-dataid=\"tabs-tab\"\n type=\"button\"\n role=\"tab\"\n [rtMod]=\"{ closable: tab.showClose() }\"\n [id]=\"'rt-tab-' + tab.id()\"\n [attr.aria-disabled]=\"tab.disabled() || null\"\n [attr.aria-label]=\"tab.ariaLabel()\"\n [attr.aria-keyshortcuts]=\"tab.showClose() ? 'Delete' : null\"\n [attr.data-tabid]=\"tab.id()\"\n [attr.aria-selected]=\"tab.id() === selectedId()\"\n [attr.aria-controls]=\"headerOnly() ? null : 'rt-tabpanel-' + tab.id()\"\n [attr.tabindex]=\"focusable ? 0 : -1\"\n [rtTooltip]=\"tab.buttonTooltip()\"\n (keydown)=\"onTabKeydown($event, tab)\">\n @if (tab.icon() || tab.glyph()) {\n <rt-icon rtElem=\"icon\" size=\"sm\" [name]=\"tab.icon()\" [glyph]=\"tab.glyph()\" [color]=\"tab.iconColor()\" />\n }\n\n @if (tab.titleTemplate(); as titleTpl) {\n <ng-container [ngTemplateOutlet]=\"titleTpl\" />\n } @else {\n <span rtElem=\"title\">{{ tab.label() }}</span>\n }\n\n @if (tab.badge() !== null) {\n <!-- В одну строку: перенос внутри добавил бы пробел в текст кнопки. -->\n <!-- prettier-ignore -->\n <span rtElem=\"badge\" [rtTooltip]=\"tab.badgeTitle()\" [attr.aria-label]=\"tab.badgeAriaLabel() || null\">{{ tab.badge() }}</span>\n }\n </button>\n\n @if (tab.showClose()) {\n <!-- В таб-порядке только у вкладки в фокусе: Tab с неё идёт на её крестик, дальше — из полосы. -->\n <button\n rtElem=\"close\"\n qa-dataid=\"tabs-tab-close\"\n type=\"button\"\n [attr.aria-label]=\"tab.closeLabel()\"\n [attr.tabindex]=\"focusable ? 0 : -1\"\n [rtTooltip]=\"tab.closeTooltip()\"\n [rtTooltipPlacement]=\"tab.closeTooltipPlacement()\"\n (mouseenter)=\"tab.closeHovered.set(true)\"\n (mouseleave)=\"tab.closeHovered.set(false)\"\n (click)=\"onCloseClick($event, tab)\">\n <rt-icon name=\"close\" color=\"current\" size=\"xs\" />\n </button>\n }\n </div>\n }\n\n <!-- Полоса выбранной вкладки — одна на всю полосу: так она переезжает между вкладками. -->\n <span\n rtElem=\"ink\"\n aria-hidden=\"true\"\n [rtMod]=\"{ placed: ink.box() !== null, animated: ink.animated(), invalid: ink.invalid() }\"\n [style.width.px]=\"ink.box()?.width\"\n [style.translate]=\"ink.translate()\"></span>\n </div>\n\n <div\n rtElem=\"rest\"\n qa-dataid=\"tabs-scroll-next\"\n [rtMod]=\"{ after: true, visible: restAfterVisible(), inactive: !restAfterVisible() }\"\n (mousedown)=\"onRestPointerDown('after', $event)\"\n (mouseup)=\"onRestPointerUp()\"\n (mouseleave)=\"onRestPointerLeave()\">\n <rt-icon name=\"chevron-right\" color=\"current\" size=\"sm\" />\n </div>\n </div>\n\n @if (rightControls().length) {\n <div rtElem=\"controls\" [rtMod]=\"{ after: true }\">\n @for (control of rightControls(); track $index) {\n <ng-container [ngTemplateOutlet]=\"control.templateRef\" />\n }\n </div>\n }\n </div>\n\n <!-- Уходящая панель стоит поверх: место ей задаёт замер, сделанный до смены. Сохранённые\n тела посещённых вкладок скрыты и вне таб-порядка. -->\n @for (panel of panels.list(); track panel.tab.id()) {\n @let current = panel.leaving === null && !panel.idle;\n <div\n rtElem=\"content\"\n role=\"tabpanel\"\n [attr.qa-dataid]=\"current ? 'tabs-panel' : panel.idle ? 'tabs-panel-idle' : 'tabs-panel-leaving'\"\n [attr.tabindex]=\"current ? contentTabIndex() : -1\"\n [attr.aria-hidden]=\"current ? null : 'true'\"\n [attr.inert]=\"current ? null : ''\"\n [hidden]=\"panel.idle\"\n [rtMod]=\"{\n scrollable: contentScrollable(),\n idle: panel.idle,\n leaving: panel.leaving !== null,\n entering: current && panels.shift() !== null,\n shift: panels.shift(),\n }\"\n [style.top.px]=\"panel.leaving?.top\"\n [style.left.px]=\"panel.leaving?.left\"\n [id]=\"'rt-tabpanel-' + panel.tab.id()\"\n [attr.aria-labelledby]=\"'rt-tab-' + panel.tab.id()\"\n (animationend)=\"panels.animationEnd($event)\"\n (animationcancel)=\"panels.animationEnd($event)\">\n <ng-container [ngTemplateOutlet]=\"panel.tab.templateRef\" />\n </div>\n }\n</ng-container>\n",
1055
+ styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-tabs{--rt-tabs-border-width: var(--rt-border-width-thin);--rt-tabs-transition-duration: var(--rt-duration-fast);display:flex;-webkit-tap-highlight-color:transparent}.rt-tabs--direction--horizontal{flex-direction:column}.rt-tabs--direction--vertical{flex-direction:row}.rt-tabs--animating{position:relative;overflow-x:clip}.rt-tabs__header{display:flex;align-items:center}.rt-tabs__tab-list-wrapper{position:relative;display:flex;overflow:hidden;flex:1 1 auto;align-items:center}.rt-tabs__tab-list{position:relative;display:flex;border-bottom:var(--rt-tabs-border-width) solid var(--rt-color-border-default);margin:0;-ms-overflow-style:none;overflow-x:auto;scrollbar-width:none;white-space:nowrap}.rt-tabs__tab-list::-webkit-scrollbar{display:none}.rt-tabs__tab-list--direction--horizontal{width:100%;flex-direction:row}.rt-tabs__tab-list--direction--vertical{flex-direction:column;border-right:var(--rt-tabs-border-width) solid var(--rt-color-border-default);border-bottom:0}.rt-tabs__tab-list--stretch{justify-content:space-between}.rt-tabs__tab-list--ink .rt-tab-item--selected:not(.rt-tab-item--invalid):after{background-color:transparent}.rt-tabs__ink{position:absolute;top:0;left:0;display:none;height:2px;margin-top:var(--rt-tabs-border-width);background-color:var(--rt-color-action-primary);pointer-events:none;transform:translateY(-100%)}.rt-tabs__ink--placed{display:block}.rt-tabs__ink--animated{transition:translate var(--rt-tabs-indicator-duration) var(--rt-tabs-indicator-easing),width var(--rt-tabs-indicator-duration) var(--rt-tabs-indicator-easing)}.rt-tabs__ink--invalid{background-color:var(--rt-color-state-danger)}.rt-tabs__rest{position:absolute;z-index:1;top:0;bottom:0;display:flex;width:var(--rt-control-height-lg);align-items:center;justify-content:center;background-color:var(--rt-color-bg-surface);color:var(--rt-color-text-muted);cursor:pointer;transition:color var(--rt-tabs-transition-duration) linear;visibility:hidden}.rt-tabs__rest:hover{color:var(--rt-color-text-primary)}.rt-tabs__rest--before{left:0;border-right:var(--rt-tabs-border-width) solid var(--rt-color-border-default)}.rt-tabs__rest--after{right:0;border-left:var(--rt-tabs-border-width) solid var(--rt-color-border-default)}.rt-tabs__rest--visible{visibility:visible}.rt-tabs__tab-list-wrapper--inline{align-items:stretch}.rt-tabs__tab-list-wrapper--inline .rt-tabs__rest{position:static;display:none;flex-shrink:0;border:0;border-bottom:var(--rt-tabs-border-width) solid var(--rt-color-border-default);background-color:transparent}.rt-tabs__tab-list-wrapper--inline.rt-tabs__tab-list-wrapper--overflowing .rt-tabs__rest{display:flex;visibility:visible}.rt-tabs__tab-list-wrapper--inline .rt-tabs__rest--inactive{color:var(--rt-color-text-disabled);cursor:default;pointer-events:none}.rt-tabs__controls{display:flex;flex-shrink:0;align-items:center}.rt-tabs__controls--before{padding-right:var(--rt-space-md)}.rt-tabs__controls--after{padding-left:var(--rt-space-md)}.rt-tabs__content{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;padding-top:var(--rt-space-md);gap:var(--rt-space-md);line-height:var(--rt-leading-relaxed)}.rt-tabs__content--scrollable{overflow:auto}.rt-tabs__content--idle{display:none}.rt-tabs__content--leaving{position:absolute;right:0;bottom:0;animation:rt-tabs-panel-leave var(--rt-tabs-panel-duration) var(--rt-tabs-panel-easing) forwards;pointer-events:none}.rt-tabs__content--entering{animation:rt-tabs-panel-enter var(--rt-tabs-panel-duration) var(--rt-tabs-panel-easing)}.rt-tabs__content--shift--forward{--rt-tabs-panel-leave-to: -100%;--rt-tabs-panel-enter-from: 100%}.rt-tabs__content--shift--backward{--rt-tabs-panel-leave-to: 100%;--rt-tabs-panel-enter-from: -100%}@keyframes rt-tabs-panel-leave{to{translate:var(--rt-tabs-panel-leave-to) 0}}@keyframes rt-tabs-panel-enter{0%{translate:var(--rt-tabs-panel-enter-from) 0}}@media(prefers-reduced-motion:reduce){.rt-tabs__ink--animated{transition:none}.rt-tabs__content--leaving,.rt-tabs__content--entering{animation:none}}.rt-tab-item{--rt-tab-item-border-width: var(--rt-border-width-thin);--rt-tab-item-badge-radius: var(--rt-radius-full);--rt-tab-item-transition-duration: var(--rt-duration-fast);--rt-tab-item-close-size: var(--rt-size-5);--rt-tab-item-close-radius: var(--rt-radius-full);--rt-tab-item-close-bg: transparent;--rt-tab-item-close-bg-hover: var(--rt-color-bg-hover);--rt-tab-item-close-color: var(--rt-color-text-muted);--rt-tab-item-close-color-hover: var(--rt-color-text-primary);--rt-tab-item-close-icon-size: var(--rt-icon-step-xs);--rt-tab-item-close-margin-inline-start: 0;--rt-tab-item-close-margin-inline-end: calc(-1 * var(--rt-space-2));position:relative;display:inline-flex;align-items:center;justify-content:center;margin:0;background-color:transparent;color:var(--rt-color-text-muted);cursor:pointer;font-family:inherit;font-size:var(--rt-text-sm);font-weight:var(--rt-font-weight-semibold);gap:var(--rt-space-sm);line-height:var(--rt-leading-none);transition:color var(--rt-tab-item-transition-duration) linear,background-color var(--rt-tab-item-transition-duration) linear;white-space:nowrap}.rt-tab-item:after{position:absolute;bottom:0;height:2px;background-color:transparent;content:\"\";inset-inline:0;pointer-events:none;translate:0 var(--rt-tab-item-border-width)}.rt-tab-item:hover:not(.rt-tab-item--disabled,.rt-tab-item--selected){background-color:var(--rt-color-bg-hover);color:var(--rt-color-text-primary)}.rt-tab-item:has(>.rt-tab-item__trigger:focus-visible){outline:2px solid var(--rt-color-action-primary);outline-offset:-3px}.rt-tab-item__trigger{display:inline-flex;min-width:0;align-items:center;justify-content:center;padding:var(--rt-space-2) var(--rt-space-4);border:0;margin:0;background:none;color:inherit;cursor:inherit;font:inherit;gap:inherit;line-height:inherit;outline:none}.rt-tab-item__trigger--closable{padding-inline-end:0}.rt-tab-item__title{overflow:hidden;max-width:200px;text-overflow:ellipsis}.rt-tab-item__icon{flex-shrink:0}.rt-tab-item__badge{display:inline-flex;min-width:18px;height:18px;align-items:center;justify-content:center;padding:0 var(--rt-space-2);border-radius:var(--rt-tab-item-badge-radius);background-color:var(--rt-color-bg-surface-subtle);color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-medium);line-height:var(--rt-leading-none)}.rt-tab-item__close{--rt-icon-step-xs: var(--rt-tab-item-close-icon-size);display:inline-flex;width:var(--rt-tab-item-close-size);height:var(--rt-tab-item-close-size);flex-shrink:0;align-items:center;justify-content:center;padding:0;border:0;border-radius:var(--rt-tab-item-close-radius);background-color:var(--rt-tab-item-close-bg);color:var(--rt-tab-item-close-color);cursor:pointer;font:inherit;margin-block:calc(-1 * var(--rt-space-1));margin-inline:var(--rt-tab-item-close-margin-inline-start) calc(var(--rt-space-4) + var(--rt-tab-item-close-margin-inline-end));transition:color var(--rt-tab-item-transition-duration) linear,background-color var(--rt-tab-item-transition-duration) linear}.rt-tab-item__close:hover{background-color:var(--rt-tab-item-close-bg-hover);color:var(--rt-tab-item-close-color-hover)}.rt-tab-item__close:focus-visible{outline:2px solid var(--rt-color-action-primary);outline-offset:0}.rt-tab-item--selected{color:var(--rt-color-action-primary);cursor:default}.rt-tab-item--selected:after{background-color:var(--rt-color-action-primary)}.rt-tab-item--selected .rt-tab-item__badge{background-color:var(--rt-color-action-primary-soft);color:var(--rt-color-action-primary)}.rt-tab-item--invalid{color:var(--rt-color-state-danger)}.rt-tab-item--invalid:after{background-color:var(--rt-color-state-danger)}.rt-tab-item--disabled{color:var(--rt-color-text-disabled);cursor:not-allowed}.rt-tab-item--stretch{max-width:100%;flex:1 1 auto}}\n"],
508
1056
  dependencies: [
509
1057
  {
510
1058
  kind: "directive",
@@ -538,6 +1086,7 @@ var RtTabsComponent = class RtTabsComponent {
538
1086
  inputs: [
539
1087
  "rtTooltip",
540
1088
  "rtTooltipPlacement",
1089
+ "rtTooltipShowDelay",
541
1090
  "rtTooltipWhenTruncated",
542
1091
  "rtTooltipHideOnClick"
543
1092
  ],
@@ -588,10 +1137,12 @@ i0.ɵɵngDeclareClassMetadata({
588
1137
  host: {
589
1138
  class: BEM_BLOCK,
590
1139
  "[class.rt-tabs--direction--horizontal]": "direction() === 'horizontal'",
591
- "[class.rt-tabs--direction--vertical]": "direction() === 'vertical'"
1140
+ "[class.rt-tabs--direction--vertical]": "direction() === 'vertical'",
1141
+ "[class.rt-tabs--animating]": "panels.shift() !== null",
1142
+ "[style]": "panels.durations()"
592
1143
  },
593
- template: "<ng-container rtBlock=\"rt-tabs\">\n <div rtElem=\"header\">\n @if (leftControls().length) {\n <div rtElem=\"controls\" [rtMod]=\"{ before: true }\">\n @for (control of leftControls(); track $index) {\n <ng-container [ngTemplateOutlet]=\"control.templateRef\" />\n }\n </div>\n }\n\n <div rtElem=\"tab-list-wrapper\">\n <div\n rtElem=\"rest\"\n qa-dataid=\"tabs-scroll-prev\"\n [rtMod]=\"{ before: true, visible: restBeforeVisible() }\"\n (mousedown)=\"onRestPointerDown('before', $event)\"\n (mouseup)=\"onRestPointerUp()\"\n (mouseleave)=\"onRestPointerUp()\">\n <rt-icon name=\"chevron-left\" color=\"current\" size=\"sm\" />\n </div>\n\n <div\n #tabList\n rtElem=\"tab-list\"\n qa-dataid=\"tabs-tab-list\"\n role=\"tablist\"\n [rtMod]=\"{ stretch: stretch(), direction: direction() }\"\n [attr.aria-orientation]=\"direction()\"\n (scroll)=\"onTabListScroll()\">\n @for (tab of visibleTabs(); track tab.id()) {\n <button\n rtBlock=\"rt-tab-item\"\n qa-dataid=\"tabs-tab\"\n type=\"button\"\n role=\"tab\"\n [rtMod]=\"{\n selected: tab.id() === selectedId(),\n disabled: tab.disabled(),\n invalid: tab.invalid(),\n stretch: stretch(),\n }\"\n [id]=\"'rt-tab-' + tab.id()\"\n [disabled]=\"tab.disabled()\"\n [attr.data-tabid]=\"tab.id()\"\n [attr.aria-selected]=\"tab.id() === selectedId()\"\n [attr.aria-controls]=\"'rt-tabpanel-' + tab.id()\"\n [attr.tabindex]=\"tab.id() === selectedId() ? 0 : -1\"\n [rtTooltip]=\"tab.invalid() ? tab.invalidTitle() : ''\"\n (click)=\"selectTab(tab.id())\"\n (keydown)=\"onTabKeydown($event)\">\n @if (tab.icon(); as icon) {\n <rt-icon rtElem=\"icon\" size=\"sm\" [name]=\"icon\" [color]=\"tab.iconColor()\" />\n }\n\n @if (tab.titleTemplate(); as titleTpl) {\n <ng-container [ngTemplateOutlet]=\"titleTpl\" />\n } @else {\n <span rtElem=\"title\">{{ tab.label() }}</span>\n }\n\n @if (tab.badge() !== null) {\n <!-- В одну строку: перенос внутри добавил бы пробел в текст кнопки. -->\n <!-- prettier-ignore -->\n <span rtElem=\"badge\" [rtTooltip]=\"tab.badgeTitle()\" [attr.aria-label]=\"tab.badgeAriaLabel() || null\">{{ tab.badge() }}</span>\n }\n </button>\n }\n </div>\n\n <div\n rtElem=\"rest\"\n qa-dataid=\"tabs-scroll-next\"\n [rtMod]=\"{ after: true, visible: restAfterVisible() }\"\n (mousedown)=\"onRestPointerDown('after', $event)\"\n (mouseup)=\"onRestPointerUp()\"\n (mouseleave)=\"onRestPointerUp()\">\n <rt-icon name=\"chevron-right\" color=\"current\" size=\"sm\" />\n </div>\n </div>\n\n @if (rightControls().length) {\n <div rtElem=\"controls\" [rtMod]=\"{ after: true }\">\n @for (control of rightControls(); track $index) {\n <ng-container [ngTemplateOutlet]=\"control.templateRef\" />\n }\n </div>\n }\n </div>\n\n @if (activeTab(); as tab) {\n <div\n rtElem=\"content\"\n qa-dataid=\"tabs-panel\"\n role=\"tabpanel\"\n tabindex=\"0\"\n [rtMod]=\"{ scrollable: contentScrollable() }\"\n [id]=\"'rt-tabpanel-' + tab.id()\"\n [attr.aria-labelledby]=\"'rt-tab-' + tab.id()\">\n <ng-container [ngTemplateOutlet]=\"tab.templateRef\" />\n </div>\n }\n</ng-container>\n",
594
- styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-tabs{--rt-tabs-border-width: var(--rt-border-width-thin);--rt-tabs-transition-duration: var(--rt-duration-fast);display:flex;-webkit-tap-highlight-color:transparent}.rt-tabs--direction--horizontal{flex-direction:column}.rt-tabs--direction--vertical{flex-direction:row}.rt-tabs__header{display:flex;align-items:center}.rt-tabs__tab-list-wrapper{position:relative;display:flex;overflow:hidden;flex:1 1 auto;align-items:center}.rt-tabs__tab-list{display:flex;border-bottom:var(--rt-tabs-border-width) solid var(--rt-color-border-default);margin:0;-ms-overflow-style:none;overflow-x:auto;scrollbar-width:none;white-space:nowrap}.rt-tabs__tab-list::-webkit-scrollbar{display:none}.rt-tabs__tab-list--direction--horizontal{width:100%;flex-direction:row}.rt-tabs__tab-list--direction--vertical{flex-direction:column;border-right:var(--rt-tabs-border-width) solid var(--rt-color-border-default);border-bottom:0}.rt-tabs__tab-list--stretch{justify-content:space-between}.rt-tabs__rest{position:absolute;z-index:1;top:0;bottom:0;display:flex;width:var(--rt-control-height-lg);align-items:center;justify-content:center;background-color:var(--rt-color-bg-surface);color:var(--rt-color-text-muted);cursor:pointer;transition:color var(--rt-tabs-transition-duration) linear;visibility:hidden}.rt-tabs__rest:hover{color:var(--rt-color-text-primary)}.rt-tabs__rest--before{left:0;border-right:var(--rt-tabs-border-width) solid var(--rt-color-border-default)}.rt-tabs__rest--after{right:0;border-left:var(--rt-tabs-border-width) solid var(--rt-color-border-default)}.rt-tabs__rest--visible{visibility:visible}.rt-tabs__controls{display:flex;flex-shrink:0;align-items:center}.rt-tabs__controls--before{padding-right:var(--rt-space-md)}.rt-tabs__controls--after{padding-left:var(--rt-space-md)}.rt-tabs__content{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;padding-top:var(--rt-space-md);gap:var(--rt-space-md);line-height:var(--rt-leading-relaxed)}.rt-tabs__content--scrollable{overflow:auto}.rt-tab-item{--rt-tab-item-border-width: var(--rt-border-width-thin);--rt-tab-item-badge-radius: var(--rt-radius-full);--rt-tab-item-transition-duration: var(--rt-duration-fast);position:relative;display:inline-flex;align-items:center;justify-content:center;padding:var(--rt-space-2) var(--rt-space-4);border:0;margin:0;background-color:transparent;color:var(--rt-color-text-muted);cursor:pointer;font-family:inherit;font-size:var(--rt-text-sm);font-weight:var(--rt-font-weight-semibold);gap:var(--rt-space-sm);line-height:var(--rt-leading-none);transition:color var(--rt-tab-item-transition-duration) linear,background-color var(--rt-tab-item-transition-duration) linear;white-space:nowrap}.rt-tab-item:after{position:absolute;bottom:calc(-1 * var(--rt-tab-item-border-width));height:2px;background-color:transparent;content:\"\";inset-inline:0;pointer-events:none}.rt-tab-item:hover:not(.rt-tab-item--disabled,.rt-tab-item--selected){background-color:var(--rt-color-bg-hover);color:var(--rt-color-text-primary)}.rt-tab-item:focus-visible{outline:2px solid var(--rt-color-action-primary);outline-offset:-3px}.rt-tab-item__title{overflow:hidden;max-width:200px;text-overflow:ellipsis}.rt-tab-item__icon{flex-shrink:0}.rt-tab-item__badge{display:inline-flex;min-width:18px;height:18px;align-items:center;justify-content:center;padding:0 var(--rt-space-2);border-radius:var(--rt-tab-item-badge-radius);background-color:var(--rt-color-bg-surface-subtle);color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-medium);line-height:var(--rt-leading-none)}.rt-tab-item--selected{color:var(--rt-color-action-primary);cursor:default}.rt-tab-item--selected:after{background-color:var(--rt-color-action-primary)}.rt-tab-item--selected .rt-tab-item__badge{background-color:var(--rt-color-action-primary-soft);color:var(--rt-color-action-primary)}.rt-tab-item--invalid{color:var(--rt-color-state-danger)}.rt-tab-item--invalid:after{background-color:var(--rt-color-state-danger)}.rt-tab-item--disabled{color:var(--rt-color-text-disabled);cursor:not-allowed}.rt-tab-item--stretch{max-width:100%;flex:1 1 auto}}\n"]
1144
+ template: "<ng-container rtBlock=\"rt-tabs\">\n <div rtElem=\"header\">\n @if (leftControls().length) {\n <div rtElem=\"controls\" [rtMod]=\"{ before: true }\">\n @for (control of leftControls(); track $index) {\n <ng-container [ngTemplateOutlet]=\"control.templateRef\" />\n }\n </div>\n }\n\n <div rtElem=\"tab-list-wrapper\" [rtMod]=\"{ inline: scrollArrows() === 'inline', overflowing: overflowing() }\">\n <div\n rtElem=\"rest\"\n qa-dataid=\"tabs-scroll-prev\"\n [rtMod]=\"{ before: true, visible: restBeforeVisible(), inactive: !restBeforeVisible() }\"\n (mousedown)=\"onRestPointerDown('before', $event)\"\n (mouseup)=\"onRestPointerUp()\"\n (mouseleave)=\"onRestPointerLeave()\">\n <rt-icon name=\"chevron-left\" color=\"current\" size=\"sm\" />\n </div>\n\n <div\n #tabList\n rtElem=\"tab-list\"\n qa-dataid=\"tabs-tab-list\"\n role=\"tablist\"\n [rtMod]=\"{ stretch: stretch(), direction: direction(), ink: ink.box() !== null }\"\n [attr.aria-orientation]=\"direction()\"\n (scroll)=\"onTabListScroll()\">\n @for (tab of visibleTabs(); track tab.id()) {\n @let focusable = tab.id() === focusId();\n <!-- Вкладка — обёртка из двух кнопок: самой вкладки и крестика рядом с ней, не внутри,\n потому что кнопка в кнопке недопустима. Нажатие в любом месте обёртки выбирает\n вкладку; крестик своё нажатие дальше не пускает. -->\n <div\n rtBlock=\"rt-tab-item\"\n role=\"presentation\"\n [rtMod]=\"{\n selected: tab.id() === selectedId(),\n disabled: tab.disabled(),\n invalid: tab.invalid(),\n stretch: stretch(),\n }\"\n [attr.data-tabitem]=\"tab.id()\"\n (click)=\"selectTab(tab.id())\">\n <button\n rtElem=\"trigger\"\n qa-dataid=\"tabs-tab\"\n type=\"button\"\n role=\"tab\"\n [rtMod]=\"{ closable: tab.showClose() }\"\n [id]=\"'rt-tab-' + tab.id()\"\n [attr.aria-disabled]=\"tab.disabled() || null\"\n [attr.aria-label]=\"tab.ariaLabel()\"\n [attr.aria-keyshortcuts]=\"tab.showClose() ? 'Delete' : null\"\n [attr.data-tabid]=\"tab.id()\"\n [attr.aria-selected]=\"tab.id() === selectedId()\"\n [attr.aria-controls]=\"headerOnly() ? null : 'rt-tabpanel-' + tab.id()\"\n [attr.tabindex]=\"focusable ? 0 : -1\"\n [rtTooltip]=\"tab.buttonTooltip()\"\n (keydown)=\"onTabKeydown($event, tab)\">\n @if (tab.icon() || tab.glyph()) {\n <rt-icon rtElem=\"icon\" size=\"sm\" [name]=\"tab.icon()\" [glyph]=\"tab.glyph()\" [color]=\"tab.iconColor()\" />\n }\n\n @if (tab.titleTemplate(); as titleTpl) {\n <ng-container [ngTemplateOutlet]=\"titleTpl\" />\n } @else {\n <span rtElem=\"title\">{{ tab.label() }}</span>\n }\n\n @if (tab.badge() !== null) {\n <!-- В одну строку: перенос внутри добавил бы пробел в текст кнопки. -->\n <!-- prettier-ignore -->\n <span rtElem=\"badge\" [rtTooltip]=\"tab.badgeTitle()\" [attr.aria-label]=\"tab.badgeAriaLabel() || null\">{{ tab.badge() }}</span>\n }\n </button>\n\n @if (tab.showClose()) {\n <!-- В таб-порядке только у вкладки в фокусе: Tab с неё идёт на её крестик, дальше — из полосы. -->\n <button\n rtElem=\"close\"\n qa-dataid=\"tabs-tab-close\"\n type=\"button\"\n [attr.aria-label]=\"tab.closeLabel()\"\n [attr.tabindex]=\"focusable ? 0 : -1\"\n [rtTooltip]=\"tab.closeTooltip()\"\n [rtTooltipPlacement]=\"tab.closeTooltipPlacement()\"\n (mouseenter)=\"tab.closeHovered.set(true)\"\n (mouseleave)=\"tab.closeHovered.set(false)\"\n (click)=\"onCloseClick($event, tab)\">\n <rt-icon name=\"close\" color=\"current\" size=\"xs\" />\n </button>\n }\n </div>\n }\n\n <!-- Полоса выбранной вкладки — одна на всю полосу: так она переезжает между вкладками. -->\n <span\n rtElem=\"ink\"\n aria-hidden=\"true\"\n [rtMod]=\"{ placed: ink.box() !== null, animated: ink.animated(), invalid: ink.invalid() }\"\n [style.width.px]=\"ink.box()?.width\"\n [style.translate]=\"ink.translate()\"></span>\n </div>\n\n <div\n rtElem=\"rest\"\n qa-dataid=\"tabs-scroll-next\"\n [rtMod]=\"{ after: true, visible: restAfterVisible(), inactive: !restAfterVisible() }\"\n (mousedown)=\"onRestPointerDown('after', $event)\"\n (mouseup)=\"onRestPointerUp()\"\n (mouseleave)=\"onRestPointerLeave()\">\n <rt-icon name=\"chevron-right\" color=\"current\" size=\"sm\" />\n </div>\n </div>\n\n @if (rightControls().length) {\n <div rtElem=\"controls\" [rtMod]=\"{ after: true }\">\n @for (control of rightControls(); track $index) {\n <ng-container [ngTemplateOutlet]=\"control.templateRef\" />\n }\n </div>\n }\n </div>\n\n <!-- Уходящая панель стоит поверх: место ей задаёт замер, сделанный до смены. Сохранённые\n тела посещённых вкладок скрыты и вне таб-порядка. -->\n @for (panel of panels.list(); track panel.tab.id()) {\n @let current = panel.leaving === null && !panel.idle;\n <div\n rtElem=\"content\"\n role=\"tabpanel\"\n [attr.qa-dataid]=\"current ? 'tabs-panel' : panel.idle ? 'tabs-panel-idle' : 'tabs-panel-leaving'\"\n [attr.tabindex]=\"current ? contentTabIndex() : -1\"\n [attr.aria-hidden]=\"current ? null : 'true'\"\n [attr.inert]=\"current ? null : ''\"\n [hidden]=\"panel.idle\"\n [rtMod]=\"{\n scrollable: contentScrollable(),\n idle: panel.idle,\n leaving: panel.leaving !== null,\n entering: current && panels.shift() !== null,\n shift: panels.shift(),\n }\"\n [style.top.px]=\"panel.leaving?.top\"\n [style.left.px]=\"panel.leaving?.left\"\n [id]=\"'rt-tabpanel-' + panel.tab.id()\"\n [attr.aria-labelledby]=\"'rt-tab-' + panel.tab.id()\"\n (animationend)=\"panels.animationEnd($event)\"\n (animationcancel)=\"panels.animationEnd($event)\">\n <ng-container [ngTemplateOutlet]=\"panel.tab.templateRef\" />\n </div>\n }\n</ng-container>\n",
1145
+ styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-tabs{--rt-tabs-border-width: var(--rt-border-width-thin);--rt-tabs-transition-duration: var(--rt-duration-fast);display:flex;-webkit-tap-highlight-color:transparent}.rt-tabs--direction--horizontal{flex-direction:column}.rt-tabs--direction--vertical{flex-direction:row}.rt-tabs--animating{position:relative;overflow-x:clip}.rt-tabs__header{display:flex;align-items:center}.rt-tabs__tab-list-wrapper{position:relative;display:flex;overflow:hidden;flex:1 1 auto;align-items:center}.rt-tabs__tab-list{position:relative;display:flex;border-bottom:var(--rt-tabs-border-width) solid var(--rt-color-border-default);margin:0;-ms-overflow-style:none;overflow-x:auto;scrollbar-width:none;white-space:nowrap}.rt-tabs__tab-list::-webkit-scrollbar{display:none}.rt-tabs__tab-list--direction--horizontal{width:100%;flex-direction:row}.rt-tabs__tab-list--direction--vertical{flex-direction:column;border-right:var(--rt-tabs-border-width) solid var(--rt-color-border-default);border-bottom:0}.rt-tabs__tab-list--stretch{justify-content:space-between}.rt-tabs__tab-list--ink .rt-tab-item--selected:not(.rt-tab-item--invalid):after{background-color:transparent}.rt-tabs__ink{position:absolute;top:0;left:0;display:none;height:2px;margin-top:var(--rt-tabs-border-width);background-color:var(--rt-color-action-primary);pointer-events:none;transform:translateY(-100%)}.rt-tabs__ink--placed{display:block}.rt-tabs__ink--animated{transition:translate var(--rt-tabs-indicator-duration) var(--rt-tabs-indicator-easing),width var(--rt-tabs-indicator-duration) var(--rt-tabs-indicator-easing)}.rt-tabs__ink--invalid{background-color:var(--rt-color-state-danger)}.rt-tabs__rest{position:absolute;z-index:1;top:0;bottom:0;display:flex;width:var(--rt-control-height-lg);align-items:center;justify-content:center;background-color:var(--rt-color-bg-surface);color:var(--rt-color-text-muted);cursor:pointer;transition:color var(--rt-tabs-transition-duration) linear;visibility:hidden}.rt-tabs__rest:hover{color:var(--rt-color-text-primary)}.rt-tabs__rest--before{left:0;border-right:var(--rt-tabs-border-width) solid var(--rt-color-border-default)}.rt-tabs__rest--after{right:0;border-left:var(--rt-tabs-border-width) solid var(--rt-color-border-default)}.rt-tabs__rest--visible{visibility:visible}.rt-tabs__tab-list-wrapper--inline{align-items:stretch}.rt-tabs__tab-list-wrapper--inline .rt-tabs__rest{position:static;display:none;flex-shrink:0;border:0;border-bottom:var(--rt-tabs-border-width) solid var(--rt-color-border-default);background-color:transparent}.rt-tabs__tab-list-wrapper--inline.rt-tabs__tab-list-wrapper--overflowing .rt-tabs__rest{display:flex;visibility:visible}.rt-tabs__tab-list-wrapper--inline .rt-tabs__rest--inactive{color:var(--rt-color-text-disabled);cursor:default;pointer-events:none}.rt-tabs__controls{display:flex;flex-shrink:0;align-items:center}.rt-tabs__controls--before{padding-right:var(--rt-space-md)}.rt-tabs__controls--after{padding-left:var(--rt-space-md)}.rt-tabs__content{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;padding-top:var(--rt-space-md);gap:var(--rt-space-md);line-height:var(--rt-leading-relaxed)}.rt-tabs__content--scrollable{overflow:auto}.rt-tabs__content--idle{display:none}.rt-tabs__content--leaving{position:absolute;right:0;bottom:0;animation:rt-tabs-panel-leave var(--rt-tabs-panel-duration) var(--rt-tabs-panel-easing) forwards;pointer-events:none}.rt-tabs__content--entering{animation:rt-tabs-panel-enter var(--rt-tabs-panel-duration) var(--rt-tabs-panel-easing)}.rt-tabs__content--shift--forward{--rt-tabs-panel-leave-to: -100%;--rt-tabs-panel-enter-from: 100%}.rt-tabs__content--shift--backward{--rt-tabs-panel-leave-to: 100%;--rt-tabs-panel-enter-from: -100%}@keyframes rt-tabs-panel-leave{to{translate:var(--rt-tabs-panel-leave-to) 0}}@keyframes rt-tabs-panel-enter{0%{translate:var(--rt-tabs-panel-enter-from) 0}}@media(prefers-reduced-motion:reduce){.rt-tabs__ink--animated{transition:none}.rt-tabs__content--leaving,.rt-tabs__content--entering{animation:none}}.rt-tab-item{--rt-tab-item-border-width: var(--rt-border-width-thin);--rt-tab-item-badge-radius: var(--rt-radius-full);--rt-tab-item-transition-duration: var(--rt-duration-fast);--rt-tab-item-close-size: var(--rt-size-5);--rt-tab-item-close-radius: var(--rt-radius-full);--rt-tab-item-close-bg: transparent;--rt-tab-item-close-bg-hover: var(--rt-color-bg-hover);--rt-tab-item-close-color: var(--rt-color-text-muted);--rt-tab-item-close-color-hover: var(--rt-color-text-primary);--rt-tab-item-close-icon-size: var(--rt-icon-step-xs);--rt-tab-item-close-margin-inline-start: 0;--rt-tab-item-close-margin-inline-end: calc(-1 * var(--rt-space-2));position:relative;display:inline-flex;align-items:center;justify-content:center;margin:0;background-color:transparent;color:var(--rt-color-text-muted);cursor:pointer;font-family:inherit;font-size:var(--rt-text-sm);font-weight:var(--rt-font-weight-semibold);gap:var(--rt-space-sm);line-height:var(--rt-leading-none);transition:color var(--rt-tab-item-transition-duration) linear,background-color var(--rt-tab-item-transition-duration) linear;white-space:nowrap}.rt-tab-item:after{position:absolute;bottom:0;height:2px;background-color:transparent;content:\"\";inset-inline:0;pointer-events:none;translate:0 var(--rt-tab-item-border-width)}.rt-tab-item:hover:not(.rt-tab-item--disabled,.rt-tab-item--selected){background-color:var(--rt-color-bg-hover);color:var(--rt-color-text-primary)}.rt-tab-item:has(>.rt-tab-item__trigger:focus-visible){outline:2px solid var(--rt-color-action-primary);outline-offset:-3px}.rt-tab-item__trigger{display:inline-flex;min-width:0;align-items:center;justify-content:center;padding:var(--rt-space-2) var(--rt-space-4);border:0;margin:0;background:none;color:inherit;cursor:inherit;font:inherit;gap:inherit;line-height:inherit;outline:none}.rt-tab-item__trigger--closable{padding-inline-end:0}.rt-tab-item__title{overflow:hidden;max-width:200px;text-overflow:ellipsis}.rt-tab-item__icon{flex-shrink:0}.rt-tab-item__badge{display:inline-flex;min-width:18px;height:18px;align-items:center;justify-content:center;padding:0 var(--rt-space-2);border-radius:var(--rt-tab-item-badge-radius);background-color:var(--rt-color-bg-surface-subtle);color:var(--rt-color-text-muted);font-size:var(--rt-text-xs);font-weight:var(--rt-font-weight-medium);line-height:var(--rt-leading-none)}.rt-tab-item__close{--rt-icon-step-xs: var(--rt-tab-item-close-icon-size);display:inline-flex;width:var(--rt-tab-item-close-size);height:var(--rt-tab-item-close-size);flex-shrink:0;align-items:center;justify-content:center;padding:0;border:0;border-radius:var(--rt-tab-item-close-radius);background-color:var(--rt-tab-item-close-bg);color:var(--rt-tab-item-close-color);cursor:pointer;font:inherit;margin-block:calc(-1 * var(--rt-space-1));margin-inline:var(--rt-tab-item-close-margin-inline-start) calc(var(--rt-space-4) + var(--rt-tab-item-close-margin-inline-end));transition:color var(--rt-tab-item-transition-duration) linear,background-color var(--rt-tab-item-transition-duration) linear}.rt-tab-item__close:hover{background-color:var(--rt-tab-item-close-bg-hover);color:var(--rt-tab-item-close-color-hover)}.rt-tab-item__close:focus-visible{outline:2px solid var(--rt-color-action-primary);outline-offset:0}.rt-tab-item--selected{color:var(--rt-color-action-primary);cursor:default}.rt-tab-item--selected:after{background-color:var(--rt-color-action-primary)}.rt-tab-item--selected .rt-tab-item__badge{background-color:var(--rt-color-action-primary-soft);color:var(--rt-color-action-primary)}.rt-tab-item--invalid{color:var(--rt-color-state-danger)}.rt-tab-item--invalid:after{background-color:var(--rt-color-state-danger)}.rt-tab-item--disabled{color:var(--rt-color-text-disabled);cursor:not-allowed}.rt-tab-item--stretch{max-width:100%;flex:1 1 auto}}\n"]
595
1146
  }]
596
1147
  }],
597
1148
  ctorParameters: () => [],
@@ -640,9 +1191,69 @@ i0.ɵɵngDeclareClassMetadata({
640
1191
  required: false
641
1192
  }]
642
1193
  }],
1194
+ headerOnly: [{
1195
+ type: i0.Input,
1196
+ args: [{
1197
+ isSignal: true,
1198
+ alias: "headerOnly",
1199
+ required: false
1200
+ }]
1201
+ }],
1202
+ preserveContent: [{
1203
+ type: i0.Input,
1204
+ args: [{
1205
+ isSignal: true,
1206
+ alias: "preserveContent",
1207
+ required: false
1208
+ }]
1209
+ }],
1210
+ activation: [{
1211
+ type: i0.Input,
1212
+ args: [{
1213
+ isSignal: true,
1214
+ alias: "activation",
1215
+ required: false
1216
+ }]
1217
+ }],
1218
+ scrollArrows: [{
1219
+ type: i0.Input,
1220
+ args: [{
1221
+ isSignal: true,
1222
+ alias: "scrollArrows",
1223
+ required: false
1224
+ }]
1225
+ }],
1226
+ scrollStep: [{
1227
+ type: i0.Input,
1228
+ args: [{
1229
+ isSignal: true,
1230
+ alias: "scrollStep",
1231
+ required: false
1232
+ }]
1233
+ }],
1234
+ animationDuration: [{
1235
+ type: i0.Input,
1236
+ args: [{
1237
+ isSignal: true,
1238
+ alias: "animationDuration",
1239
+ required: false
1240
+ }]
1241
+ }],
1242
+ contentTabIndex: [{
1243
+ type: i0.Input,
1244
+ args: [{
1245
+ isSignal: true,
1246
+ alias: "contentTabIndex",
1247
+ required: false
1248
+ }]
1249
+ }],
643
1250
  activeIdChange: [{
644
1251
  type: i0.Output,
645
1252
  args: ["activeIdChange"]
1253
+ }],
1254
+ tabClose: [{
1255
+ type: i0.Output,
1256
+ args: ["tabClose"]
646
1257
  }]
647
1258
  }
648
1259
  });