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

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 +609 -33
  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 +57 -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 +291 -6
  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,6 +311,38 @@ 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
  });
@@ -308,16 +401,298 @@ i0.ɵɵngDeclareClassMetadata({
308
401
  }]
309
402
  }] }
310
403
  });
311
- const SCROLL_STEP = 12;
404
+ function rtTabsCssDuration(value) {
405
+ const text = value === null ? "" : String(value).trim();
406
+ if (!text) return null;
407
+ return /^\d+(\.\d+)?$/.test(text) ? `${text}ms` : text;
408
+ }
409
+ function rtTabsDurationMs(value) {
410
+ const text = value.trim();
411
+ const amount = parseFloat(text);
412
+ if (Number.isNaN(amount)) return 0;
413
+ if (text.endsWith("ms")) return amount;
414
+ return text.endsWith("s") ? amount * 1e3 : amount;
415
+ }
416
+ function withVisited(visited, id) {
417
+ return id === null || visited.has(id) ? visited : /* @__PURE__ */ new Set([...visited, id]);
418
+ }
419
+ function sameInkBox(a, b) {
420
+ if (a === null || b === null) return a === b;
421
+ return a.x === b.x && a.bottom === b.bottom && a.width === b.width;
422
+ }
423
+ function rtTabsLeavingPanel(host, win, ids, move) {
424
+ const { previous, next } = move;
425
+ if (previous === null || next === null || previous === next || !win) return null;
426
+ if (win.matchMedia?.("(prefers-reduced-motion: reduce)").matches) return null;
427
+ const duration = move.duration ?? win.getComputedStyle(host).getPropertyValue("--rt-tabs-panel-duration");
428
+ const panel = Array.from(host.querySelectorAll(":scope > .rt-tabs__content")).find((node) => node.id === `rt-tabpanel-${previous}`);
429
+ if (!panel || rtTabsDurationMs(duration) <= 0) return null;
430
+ const hostBox = host.getBoundingClientRect();
431
+ const panelBox = panel.getBoundingClientRect();
432
+ return {
433
+ id: previous,
434
+ shift: ids.indexOf(next) > ids.indexOf(previous) ? "forward" : "backward",
435
+ top: panelBox.top - hostBox.top - host.clientTop,
436
+ left: panelBox.left - hostBox.left - host.clientLeft
437
+ };
438
+ }
439
+ function rtTabsPreservedPanels(all, visited, active, leaving) {
440
+ return all.filter((tab) => tab === active || visited.has(tab.id())).map((tab) => {
441
+ if (tab === active) return {
442
+ leaving: null,
443
+ idle: false,
444
+ tab
445
+ };
446
+ const isLeaving = leaving !== null && leaving.id === tab.id();
447
+ return {
448
+ leaving: isLeaving ? leaving : null,
449
+ idle: !isLeaving,
450
+ tab
451
+ };
452
+ });
453
+ }
454
+ var RtTabsPanels = class {
455
+ #visited;
456
+ constructor(host, win, tabs, shown) {
457
+ this.duration = computed(() => rtTabsCssDuration(shown.duration()), ...ngDevMode ? [{ debugName: "duration" }] : /* istanbul ignore next */ []);
458
+ this.durations = computed(() => {
459
+ const duration = this.duration();
460
+ return duration === null ? null : {
461
+ "--rt-tabs-indicator-duration": duration,
462
+ "--rt-tabs-panel-duration": duration
463
+ };
464
+ }, ...ngDevMode ? [{ debugName: "durations" }] : /* istanbul ignore next */ []);
465
+ const ids = () => tabs.visible().map((tab) => tab.id());
466
+ this.leaving = linkedSignal({
467
+ ...ngDevMode ? { debugName: "leaving" } : /* istanbul ignore next */ {},
468
+ source: tabs.selectedId,
469
+ computation: (id, previous) => untracked(() => rtTabsLeavingPanel(host, win, ids(), {
470
+ previous: previous?.source ?? null,
471
+ next: id,
472
+ duration: this.duration()
473
+ }))
474
+ });
475
+ this.#visited = linkedSignal({
476
+ ...ngDevMode ? { debugName: "#visited" } : /* istanbul ignore next */ {},
477
+ source: tabs.selectedId,
478
+ computation: (id, previous) => withVisited(previous?.value ?? /* @__PURE__ */ new Set(), id)
479
+ });
480
+ this.list = computed(() => {
481
+ const active = shown.active();
482
+ const leaving = this.leaving();
483
+ if (!active) return [];
484
+ if (shown.preserve()) return rtTabsPreservedPanels(tabs.all(), this.#visited(), active, leaving);
485
+ const current = {
486
+ tab: active,
487
+ leaving: null,
488
+ idle: false
489
+ };
490
+ const leavingTab = leaving === null || leaving.id === active.id() ? void 0 : tabs.visible().find((tab) => tab.id() === leaving.id);
491
+ return leaving && leavingTab ? [{
492
+ leaving,
493
+ idle: false,
494
+ tab: leavingTab
495
+ }, current] : [current];
496
+ }, ...ngDevMode ? [{ debugName: "list" }] : /* istanbul ignore next */ []);
497
+ this.shift = computed(() => this.list().some((panel) => panel.leaving !== null) ? this.leaving()?.shift ?? null : null, ...ngDevMode ? [{ debugName: "shift" }] : /* istanbul ignore next */ []);
498
+ }
499
+ animationEnd(event) {
500
+ if (event.target === event.currentTarget) this.leaving.set(null);
501
+ }
502
+ };
503
+ var RtTabsInk = class {
504
+ #win;
505
+ #list;
506
+ #active;
507
+ #watch;
508
+ constructor(win, list, tabs) {
509
+ this.#watch = null;
510
+ this.box = signal(null, {
511
+ ...ngDevMode ? { debugName: "box" } : /* istanbul ignore next */ {},
512
+ equal: sameInkBox
513
+ });
514
+ this.animated = signal(false, ...ngDevMode ? [{ debugName: "animated" }] : /* istanbul ignore next */ []);
515
+ this.translate = computed(() => {
516
+ const box = this.box();
517
+ return box ? `${box.x}px ${box.bottom}px` : null;
518
+ }, ...ngDevMode ? [{ debugName: "translate" }] : /* istanbul ignore next */ []);
519
+ this.invalid = computed(() => this.#active()?.invalid() ?? false, ...ngDevMode ? [{ debugName: "invalid" }] : /* istanbul ignore next */ []);
520
+ this.#win = win;
521
+ this.#list = list;
522
+ this.#active = tabs.active;
523
+ afterRenderEffect(() => {
524
+ tabs.visible();
525
+ this.#active();
526
+ this.#watchSizes();
527
+ this.#place();
528
+ });
529
+ inject(DestroyRef).onDestroy(() => this.#watch?.disconnect());
530
+ }
531
+ #watchSizes() {
532
+ const list = this.#list()?.nativeElement;
533
+ if (!list || typeof ResizeObserver === "undefined") return;
534
+ if (!this.#watch) this.#watch = new ResizeObserver(() => this.#place());
535
+ const watch = this.#watch;
536
+ watch.disconnect();
537
+ watch.observe(list);
538
+ list.querySelectorAll("[data-tabitem]").forEach((node) => watch.observe(node));
539
+ }
540
+ #place() {
541
+ const list = this.#list()?.nativeElement;
542
+ const id = this.#active()?.id();
543
+ const tab = id === void 0 ? null : list?.querySelector(`[data-tabitem="${id}"]`);
544
+ if (!list || !tab) {
545
+ this.box.set(null);
546
+ return;
547
+ }
548
+ const listBox = list.getBoundingClientRect();
549
+ const tabBox = tab.getBoundingClientRect();
550
+ this.box.set({
551
+ x: tabBox.left - listBox.left - list.clientLeft + list.scrollLeft,
552
+ bottom: tabBox.bottom - listBox.top - list.clientTop + list.scrollTop,
553
+ width: tabBox.width
554
+ });
555
+ if (!untracked(this.animated)) this.#win?.requestAnimationFrame(() => this.animated.set(true));
556
+ }
557
+ };
558
+ const EASE_OUT = [
559
+ 0,
560
+ 0,
561
+ .58,
562
+ 1
563
+ ];
564
+ const NAMED_EASINGS = /* @__PURE__ */ new Map([
565
+ ["linear", [
566
+ 0,
567
+ 0,
568
+ 1,
569
+ 1
570
+ ]],
571
+ ["ease", [
572
+ .25,
573
+ .1,
574
+ .25,
575
+ 1
576
+ ]],
577
+ ["ease-in", [
578
+ .42,
579
+ 0,
580
+ 1,
581
+ 1
582
+ ]],
583
+ ["ease-out", EASE_OUT],
584
+ ["ease-in-out", [
585
+ .42,
586
+ 0,
587
+ .58,
588
+ 1
589
+ ]]
590
+ ]);
591
+ const HOLD_STEP = 12;
592
+ const FIXED_STEP = 80;
593
+ const STEP_SHARE = {
594
+ page: 1,
595
+ third: 1 / 3
596
+ };
597
+ function bezierAt(t, p1, p2) {
598
+ const u = 1 - t;
599
+ return 3 * u * u * t * p1 + 3 * u * t * t * p2 + t * t * t;
600
+ }
601
+ function rtTabsEasing(value) {
602
+ const text = value.trim();
603
+ const match = /^cubic-bezier\(([^)]*)\)$/.exec(text);
604
+ const parsed = match ? match[1].split(",").map((part) => parseFloat(part)) : [];
605
+ const [x1, y1, x2, y2] = parsed.length === 4 && parsed.every((point) => Number.isFinite(point)) ? parsed : NAMED_EASINGS.get(text) ?? EASE_OUT;
606
+ return (progress) => {
607
+ if (progress <= 0 || progress >= 1) return Math.min(1, Math.max(0, progress));
608
+ let low = 0;
609
+ let high = 1;
610
+ for (let step = 0; step < 30; step++) {
611
+ const mid = (low + high) / 2;
612
+ if (bezierAt(mid, x1, x2) < progress) low = mid;
613
+ else high = mid;
614
+ }
615
+ return bezierAt((low + high) / 2, y1, y2);
616
+ };
617
+ }
618
+ function rtTabsPageTarget(list, from, back, step) {
619
+ const max = Math.max(0, list.scrollWidth - list.clientWidth);
620
+ const shift = step === "fixed" ? FIXED_STEP : list.clientWidth * STEP_SHARE[step];
621
+ return Math.min(max, Math.max(0, from + (back ? -shift : shift)));
622
+ }
623
+ function rtTabsIntoViewTarget(list, tab) {
624
+ if (tab.offsetLeft < list.scrollLeft) return tab.offsetLeft;
625
+ if (tab.offsetLeft + tab.offsetWidth > list.scrollLeft + list.clientWidth) return tab.offsetLeft + tab.offsetWidth - list.clientWidth;
626
+ return null;
627
+ }
628
+ var RtTabsScroller = class {
629
+ #win;
630
+ #host;
631
+ #list;
632
+ #frame = null;
633
+ #target = null;
634
+ constructor(win, host, list) {
635
+ this.#win = win;
636
+ this.#host = host;
637
+ this.#list = list;
638
+ }
639
+ from() {
640
+ return this.#target ?? this.#list()?.nativeElement.scrollLeft ?? 0;
641
+ }
642
+ to(left) {
643
+ const list = this.#list()?.nativeElement;
644
+ const win = this.#win;
645
+ this.stop();
646
+ if (!list || !win) return;
647
+ const style = win.getComputedStyle(this.#host);
648
+ const duration = win.matchMedia?.("(prefers-reduced-motion: reduce)").matches ? 0 : rtTabsDurationMs(style.getPropertyValue("--rt-tabs-scroll-duration"));
649
+ const start = list.scrollLeft;
650
+ if (duration <= 0 || start === left) {
651
+ list.scrollLeft = left;
652
+ return;
653
+ }
654
+ const ease = rtTabsEasing(style.getPropertyValue("--rt-tabs-scroll-easing"));
655
+ const startedAt = win.performance.now();
656
+ this.#target = left;
657
+ const tick = (now) => {
658
+ const progress = Math.min(1, (now - startedAt) / duration);
659
+ list.scrollLeft = start + (left - start) * ease(progress);
660
+ this.#frame = progress < 1 ? win.requestAnimationFrame(tick) : null;
661
+ if (this.#frame === null) this.#target = null;
662
+ };
663
+ this.#frame = win.requestAnimationFrame(tick);
664
+ }
665
+ nudge(back) {
666
+ this.stop();
667
+ const list = this.#list()?.nativeElement;
668
+ if (!list) return false;
669
+ const remaining = back ? list.scrollLeft : list.scrollWidth - list.scrollLeft - list.clientWidth;
670
+ if (remaining > 0) list.scrollLeft += (back ? -1 : 1) * Math.min(HOLD_STEP, remaining);
671
+ return remaining - HOLD_STEP > 0;
672
+ }
673
+ stop() {
674
+ if (this.#frame !== null) this.#win?.cancelAnimationFrame(this.#frame);
675
+ this.#frame = null;
676
+ this.#target = null;
677
+ }
678
+ };
312
679
  const SCROLL_TICK_MS = 15;
680
+ const HOLD_DELAY_MS = 300;
313
681
  const REST_DEBOUNCE_MS = 50;
314
682
  const BEM_BLOCK = "rt-tabs";
315
683
  var RtTabsComponent = class RtTabsComponent {
316
684
  #win;
685
+ #host;
686
+ #injector;
687
+ #scroller;
317
688
  #internalId;
689
+ #focusedId;
318
690
  #scrollIntervalId;
691
+ #holdTimeoutId;
692
+ #pressed;
319
693
  constructor() {
320
694
  this.#win = inject(DOCUMENT).defaultView;
695
+ this.#host = inject(ElementRef).nativeElement;
321
696
  this.tabs = contentChildren(RtTabDirective, ...ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []);
322
697
  this.controls = contentChildren(RtTabsControlDirective, ...ngDevMode ? [{ debugName: "controls" }] : /* istanbul ignore next */ []);
323
698
  this.visibleTabs = computed(() => this.tabs().filter((tab) => !tab.hidden()), ...ngDevMode ? [{ debugName: "visibleTabs" }] : /* istanbul ignore next */ []);
@@ -334,9 +709,27 @@ var RtTabsComponent = class RtTabsComponent {
334
709
  return result;
335
710
  }, ...ngDevMode ? [{ debugName: "selectedId" }] : /* istanbul ignore next */ []);
336
711
  this.activeTab = computed(() => this.visibleTabs().find((tab) => tab.id() === this.selectedId()) ?? null, ...ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []);
712
+ this.focusId = computed(() => {
713
+ const focused = this.#focusedId();
714
+ return focused !== null && this.visibleTabs().some((tab) => tab.id() === focused && !tab.disabled()) ? focused : this.selectedId();
715
+ }, ...ngDevMode ? [{ debugName: "focusId" }] : /* istanbul ignore next */ []);
337
716
  this.restBeforeVisible = signal(false, ...ngDevMode ? [{ debugName: "restBeforeVisible" }] : /* istanbul ignore next */ []);
338
717
  this.restAfterVisible = signal(false, ...ngDevMode ? [{ debugName: "restAfterVisible" }] : /* istanbul ignore next */ []);
718
+ this.overflowing = computed(() => this.restBeforeVisible() || this.restAfterVisible(), ...ngDevMode ? [{ debugName: "overflowing" }] : /* istanbul ignore next */ []);
339
719
  this.tabListRef = viewChild("tabList", ...ngDevMode ? [{ debugName: "tabListRef" }] : /* istanbul ignore next */ []);
720
+ this.panels = new RtTabsPanels(this.#host, this.#win, {
721
+ all: this.tabs,
722
+ visible: this.visibleTabs,
723
+ selectedId: this.selectedId
724
+ }, {
725
+ active: computed(() => this.headerOnly() ? null : this.activeTab()),
726
+ duration: () => this.animationDuration(),
727
+ preserve: () => this.preserveContent()
728
+ });
729
+ this.ink = new RtTabsInk(this.#win, this.tabListRef, {
730
+ visible: this.visibleTabs,
731
+ active: this.activeTab
732
+ });
340
733
  this.activeId = input(null, ...ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []);
341
734
  this.direction = input("horizontal", ...ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []);
342
735
  this.stretch = input(false, {
@@ -347,27 +740,58 @@ var RtTabsComponent = class RtTabsComponent {
347
740
  ...ngDevMode ? { debugName: "contentScrollable" } : /* istanbul ignore next */ {},
348
741
  transform: booleanAttribute
349
742
  });
743
+ this.headerOnly = input(false, {
744
+ ...ngDevMode ? { debugName: "headerOnly" } : /* istanbul ignore next */ {},
745
+ transform: booleanAttribute
746
+ });
747
+ this.preserveContent = input(false, {
748
+ ...ngDevMode ? { debugName: "preserveContent" } : /* istanbul ignore next */ {},
749
+ transform: booleanAttribute
750
+ });
751
+ this.activation = input("auto", ...ngDevMode ? [{ debugName: "activation" }] : /* istanbul ignore next */ []);
752
+ this.scrollArrows = input("overlay", ...ngDevMode ? [{ debugName: "scrollArrows" }] : /* istanbul ignore next */ []);
753
+ this.scrollStep = input("fixed", ...ngDevMode ? [{ debugName: "scrollStep" }] : /* istanbul ignore next */ []);
754
+ this.animationDuration = input(null, ...ngDevMode ? [{ debugName: "animationDuration" }] : /* istanbul ignore next */ []);
755
+ this.contentTabIndex = input(0, ...ngDevMode ? [{ debugName: "contentTabIndex" }] : /* istanbul ignore next */ []);
350
756
  this.activeIdChange = output();
757
+ this.tabClose = output();
758
+ this.#injector = inject(Injector);
759
+ this.#scroller = new RtTabsScroller(this.#win, this.#host, () => this.tabListRef());
351
760
  this.#internalId = signal(null, ...ngDevMode ? [{ debugName: "#internalId" }] : /* istanbul ignore next */ []);
761
+ this.#focusedId = signal(null, ...ngDevMode ? [{ debugName: "#focusedId" }] : /* istanbul ignore next */ []);
352
762
  this.#scrollIntervalId = null;
763
+ this.#holdTimeoutId = null;
764
+ this.#pressed = null;
353
765
  if (this.#win) fromEvent(this.#win, "resize").pipe(debounceTime(REST_DEBOUNCE_MS), takeUntilDestroyed()).subscribe(() => this.#updateRestVisibility());
354
766
  afterNextRender(() => this.#updateRestVisibility());
355
- inject(DestroyRef).onDestroy(() => this.#clearScrollInterval());
767
+ inject(DestroyRef).onDestroy(() => {
768
+ this.#clearScrollInterval();
769
+ this.#scroller.stop();
770
+ });
356
771
  }
357
772
  selectTab(id) {
358
773
  const target = this.visibleTabs().find((tab) => tab.id() === id);
359
774
  if (!target || target.disabled()) return;
360
775
  this.#internalId.set(id);
776
+ this.#focusedId.set(null);
361
777
  this.activeIdChange.emit(id);
362
778
  this.#scrollTabIntoView(id);
363
779
  }
364
- onTabKeydown(event) {
365
- const enabled = this.visibleTabs().filter((tab) => !tab.disabled());
780
+ onCloseClick(event, tab) {
781
+ event.stopPropagation();
782
+ this.#close(tab, event.currentTarget instanceof HTMLElement && event.currentTarget.matches(":focus"));
783
+ }
784
+ onTabKeydown(event, tab) {
785
+ if (event.key === "Delete") {
786
+ this.#closeByKey(event, tab);
787
+ return;
788
+ }
789
+ const enabled = this.visibleTabs().filter((item) => !item.disabled());
366
790
  if (!enabled.length) return;
367
791
  const isVertical = this.direction() === "vertical";
368
792
  const nextKey = isVertical ? "ArrowDown" : "ArrowRight";
369
793
  const prevKey = isVertical ? "ArrowUp" : "ArrowLeft";
370
- const currentIndex = enabled.findIndex((tab) => tab.id() === this.selectedId());
794
+ const currentIndex = enabled.findIndex((item) => item.id() === tab.id());
371
795
  const targetIndex = (/* @__PURE__ */ new Map([
372
796
  [nextKey, (currentIndex + 1) % enabled.length],
373
797
  [prevKey, (currentIndex - 1 + enabled.length) % enabled.length],
@@ -377,36 +801,74 @@ var RtTabsComponent = class RtTabsComponent {
377
801
  if (targetIndex === void 0) return;
378
802
  event.preventDefault();
379
803
  const targetId = enabled[targetIndex].id();
380
- this.selectTab(targetId);
804
+ if (this.activation() === "manual") {
805
+ this.#focusedId.set(targetId);
806
+ this.#scrollTabIntoView(targetId);
807
+ } else this.selectTab(targetId);
381
808
  this.#focusTab(targetId);
382
809
  }
383
810
  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);
811
+ if (event.button !== 0 || this.#pressed !== null || !this.#win) return;
812
+ this.#pressed = direction;
813
+ this.#holdTimeoutId = this.#win.setTimeout(() => {
814
+ this.#holdTimeoutId = null;
815
+ this.#scrollIntervalId = this.#win?.setInterval(() => {
816
+ this.#scrollStep(direction);
817
+ this.#updateRestVisibility();
818
+ }, SCROLL_TICK_MS) ?? null;
819
+ }, HOLD_DELAY_MS);
389
820
  }
390
821
  onRestPointerUp() {
822
+ const direction = this.#pressed;
823
+ const shortPress = this.#holdTimeoutId !== null;
824
+ this.#clearScrollInterval();
825
+ if (direction !== null && shortPress) this.#scrollPage(direction);
826
+ }
827
+ onRestPointerLeave() {
391
828
  this.#clearScrollInterval();
392
829
  }
393
830
  onTabListScroll() {
394
831
  this.#updateRestVisibility();
395
832
  }
833
+ #closeByKey(event, tab) {
834
+ if (!tab.showClose()) return;
835
+ event.preventDefault();
836
+ this.#close(tab, true);
837
+ }
838
+ #close(tab, focus) {
839
+ const closedId = tab.id();
840
+ const wasActive = this.selectedId() === closedId;
841
+ this.tabClose.emit(closedId);
842
+ afterNextRender(() => {
843
+ const id = this.selectedId();
844
+ if (id === null) return;
845
+ if (wasActive && id !== closedId) {
846
+ this.#internalId.set(id);
847
+ this.activeIdChange.emit(id);
848
+ }
849
+ if (focus) this.#focusTab(id);
850
+ }, { injector: this.#injector });
851
+ }
396
852
  #clearScrollInterval() {
853
+ this.#pressed = null;
854
+ if (this.#win && this.#holdTimeoutId !== null) {
855
+ this.#win.clearTimeout(this.#holdTimeoutId);
856
+ this.#holdTimeoutId = null;
857
+ }
397
858
  if (this.#win && this.#scrollIntervalId !== null) {
398
859
  this.#win.clearInterval(this.#scrollIntervalId);
399
860
  this.#scrollIntervalId = null;
400
861
  }
401
862
  }
402
- #scrollStep(direction) {
863
+ #scrollPage(direction) {
403
864
  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();
865
+ if (list) {
866
+ this.#scroller.to(rtTabsPageTarget(list, this.#scroller.from(), direction === "before", this.scrollStep()));
867
+ this.#updateRestVisibility();
868
+ }
869
+ }
870
+ #scrollStep(direction) {
871
+ if (!this.#scroller.nudge(direction === "before")) this.#clearScrollInterval();
410
872
  }
411
873
  #updateRestVisibility() {
412
874
  const list = this.tabListRef()?.nativeElement;
@@ -421,15 +883,12 @@ var RtTabsComponent = class RtTabsComponent {
421
883
  }
422
884
  #scrollTabIntoView(id) {
423
885
  const list = this.tabListRef()?.nativeElement;
424
- const tab = list?.querySelector(`[data-tabid="${id}"]`);
425
- 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 });
886
+ const tab = list?.querySelector(`[data-tabitem="${id}"]`);
887
+ const target = list && tab ? rtTabsIntoViewTarget(list, tab) : null;
888
+ if (target !== null) this.#scroller.to(target);
430
889
  }
431
890
  #focusTab(id) {
432
- (this.tabListRef()?.nativeElement)?.querySelector(`[data-tabid="${id}"]`)?.focus();
891
+ (this.tabListRef()?.nativeElement)?.querySelector(`[data-tabid="${id}"]`)?.focus({ preventScroll: true });
433
892
  }
434
893
  static {
435
894
  this.ɵfac = i0.ɵɵngDeclareFactory({
@@ -476,13 +935,67 @@ var RtTabsComponent = class RtTabsComponent {
476
935
  isSignal: true,
477
936
  isRequired: false,
478
937
  transformFunction: null
938
+ },
939
+ headerOnly: {
940
+ classPropertyName: "headerOnly",
941
+ publicName: "headerOnly",
942
+ isSignal: true,
943
+ isRequired: false,
944
+ transformFunction: null
945
+ },
946
+ preserveContent: {
947
+ classPropertyName: "preserveContent",
948
+ publicName: "preserveContent",
949
+ isSignal: true,
950
+ isRequired: false,
951
+ transformFunction: null
952
+ },
953
+ activation: {
954
+ classPropertyName: "activation",
955
+ publicName: "activation",
956
+ isSignal: true,
957
+ isRequired: false,
958
+ transformFunction: null
959
+ },
960
+ scrollArrows: {
961
+ classPropertyName: "scrollArrows",
962
+ publicName: "scrollArrows",
963
+ isSignal: true,
964
+ isRequired: false,
965
+ transformFunction: null
966
+ },
967
+ scrollStep: {
968
+ classPropertyName: "scrollStep",
969
+ publicName: "scrollStep",
970
+ isSignal: true,
971
+ isRequired: false,
972
+ transformFunction: null
973
+ },
974
+ animationDuration: {
975
+ classPropertyName: "animationDuration",
976
+ publicName: "animationDuration",
977
+ isSignal: true,
978
+ isRequired: false,
979
+ transformFunction: null
980
+ },
981
+ contentTabIndex: {
982
+ classPropertyName: "contentTabIndex",
983
+ publicName: "contentTabIndex",
984
+ isSignal: true,
985
+ isRequired: false,
986
+ transformFunction: null
479
987
  }
480
988
  },
481
- outputs: { activeIdChange: "activeIdChange" },
989
+ outputs: {
990
+ activeIdChange: "activeIdChange",
991
+ tabClose: "tabClose"
992
+ },
482
993
  host: {
483
994
  properties: {
484
995
  "class.rt-tabs--direction--horizontal": "direction() === 'horizontal'",
485
- "class.rt-tabs--direction--vertical": "direction() === 'vertical'"
996
+ "class.rt-tabs--direction--vertical": "direction() === 'vertical'",
997
+ "class.rt-tabs--animating": "panels.shift() !== null",
998
+ "style": "panels.durations()"
486
999
  },
487
1000
  classAttribute: "rt-tabs"
488
1001
  },
@@ -503,8 +1016,8 @@ var RtTabsComponent = class RtTabsComponent {
503
1016
  isSignal: true
504
1017
  }],
505
1018
  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"],
1019
+ 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",
1020
+ 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
1021
  dependencies: [
509
1022
  {
510
1023
  kind: "directive",
@@ -538,6 +1051,7 @@ var RtTabsComponent = class RtTabsComponent {
538
1051
  inputs: [
539
1052
  "rtTooltip",
540
1053
  "rtTooltipPlacement",
1054
+ "rtTooltipShowDelay",
541
1055
  "rtTooltipWhenTruncated",
542
1056
  "rtTooltipHideOnClick"
543
1057
  ],
@@ -588,10 +1102,12 @@ i0.ɵɵngDeclareClassMetadata({
588
1102
  host: {
589
1103
  class: BEM_BLOCK,
590
1104
  "[class.rt-tabs--direction--horizontal]": "direction() === 'horizontal'",
591
- "[class.rt-tabs--direction--vertical]": "direction() === 'vertical'"
1105
+ "[class.rt-tabs--direction--vertical]": "direction() === 'vertical'",
1106
+ "[class.rt-tabs--animating]": "panels.shift() !== null",
1107
+ "[style]": "panels.durations()"
592
1108
  },
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"]
1109
+ 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",
1110
+ 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
1111
  }]
596
1112
  }],
597
1113
  ctorParameters: () => [],
@@ -640,9 +1156,69 @@ i0.ɵɵngDeclareClassMetadata({
640
1156
  required: false
641
1157
  }]
642
1158
  }],
1159
+ headerOnly: [{
1160
+ type: i0.Input,
1161
+ args: [{
1162
+ isSignal: true,
1163
+ alias: "headerOnly",
1164
+ required: false
1165
+ }]
1166
+ }],
1167
+ preserveContent: [{
1168
+ type: i0.Input,
1169
+ args: [{
1170
+ isSignal: true,
1171
+ alias: "preserveContent",
1172
+ required: false
1173
+ }]
1174
+ }],
1175
+ activation: [{
1176
+ type: i0.Input,
1177
+ args: [{
1178
+ isSignal: true,
1179
+ alias: "activation",
1180
+ required: false
1181
+ }]
1182
+ }],
1183
+ scrollArrows: [{
1184
+ type: i0.Input,
1185
+ args: [{
1186
+ isSignal: true,
1187
+ alias: "scrollArrows",
1188
+ required: false
1189
+ }]
1190
+ }],
1191
+ scrollStep: [{
1192
+ type: i0.Input,
1193
+ args: [{
1194
+ isSignal: true,
1195
+ alias: "scrollStep",
1196
+ required: false
1197
+ }]
1198
+ }],
1199
+ animationDuration: [{
1200
+ type: i0.Input,
1201
+ args: [{
1202
+ isSignal: true,
1203
+ alias: "animationDuration",
1204
+ required: false
1205
+ }]
1206
+ }],
1207
+ contentTabIndex: [{
1208
+ type: i0.Input,
1209
+ args: [{
1210
+ isSignal: true,
1211
+ alias: "contentTabIndex",
1212
+ required: false
1213
+ }]
1214
+ }],
643
1215
  activeIdChange: [{
644
1216
  type: i0.Output,
645
1217
  args: ["activeIdChange"]
1218
+ }],
1219
+ tabClose: [{
1220
+ type: i0.Output,
1221
+ args: ["tabClose"]
646
1222
  }]
647
1223
  }
648
1224
  });