@rt-tools/ui-kit-v2 0.35.0 → 0.35.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.
- package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs +4 -2
- package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +4 -2
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +4 -2
- package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +20 -4
- package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +4 -2
- package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-table.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +52 -5
- package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs +37 -0
- package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tree.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-tree.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-usage-ring.mjs +4 -3
- package/fesm2022/rt-tools-ui-kit-v2-usage-ring.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/components/thread-list/rt-thread-list.component.scss +7 -0
- package/src/lib/components/tooltip/CONTEXT.md +4 -0
- package/src/rich-editor/lib/components/chat/rt-chat.component.scss +25 -0
- package/types/rt-tools-ui-kit-v2-rich-editor.d.ts +7 -0
- package/types/rt-tools-ui-kit-v2-thread-list.d.ts +7 -1
- package/types/rt-tools-ui-kit-v2-tooltip.d.ts +12 -0
|
@@ -1140,7 +1140,8 @@ var RtTabsComponent = class RtTabsComponent {
|
|
|
1140
1140
|
"rtTooltipPlacement",
|
|
1141
1141
|
"rtTooltipShowDelay",
|
|
1142
1142
|
"rtTooltipWhenTruncated",
|
|
1143
|
-
"rtTooltipHideOnClick"
|
|
1143
|
+
"rtTooltipHideOnClick",
|
|
1144
|
+
"rtTooltipShowOnTap"
|
|
1144
1145
|
],
|
|
1145
1146
|
exportAs: ["rtTooltip"]
|
|
1146
1147
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-tabs.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tab.directive.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.motion.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.scroll.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.arrow-press.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.follow.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs-control.directive.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.component.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n computed,\n Directive,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n Signal,\n signal,\n TemplateRef,\n WritableSignal,\n} from '@angular/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { IRtTooltip } from '@rt-tools/ui-kit-v2/tooltip';\nimport { IRtTabs } from './rt-tabs.model';\n\n/**\n * Декларирует одну вкладку `<rt-tabs>`. Ставится на `<ng-template>`: контент\n * шаблона становится телом панели и рендерится только когда вкладка активна.\n *\n * Метаданные (label, icon, disabled, badge, invalid) — signal-inputs, поэтому\n * шапка вкладки реагирует на их изменение без ручной перерегистрации. Сам\n * список вкладок `rt-tabs` собирает через `contentChildren`.\n */\n@Directive({\n selector: '[rtTab]',\n})\nexport class RtTabDirective {\n readonly #t_uiTabInvalid: Signal<string> = rtKitLabel('uiTabInvalid');\n readonly #t_uiClose: Signal<string> = rtKitLabel('uiClose');\n\n /** Шаблон тела панели — рендерится в области контента при активной вкладке. */\n public readonly templateRef: TemplateRef<unknown> = inject<TemplateRef<unknown>>(TemplateRef);\n\n /** Стабильный идентификатор вкладки (значение атрибута `rtTab`). */\n public readonly id: InputSignal<IRtTabs.Id> = input<IRtTabs.Id>('', { alias: 'rtTab' });\n\n /** Текстовый заголовок. Игнорируется, если задан `titleTemplate`. */\n public readonly label: InputSignal<string> = input<string>('');\n\n /** Кастомный шаблон заголовка — замещает `label`. */\n public readonly titleTemplate: InputSignal<TemplateRef<unknown> | null> = input<TemplateRef<unknown> | null>(null);\n\n /** Иконка слева от заголовка. */\n public readonly icon: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /**\n * Имя значка Material вместо `icon` — рисуется так же, как вход `glyph` у `rt-icon`.\n * Задан вместе с `icon` — решает `rt-icon`.\n */\n public readonly glyph: InputSignal<string | null> = input<string | null>(null);\n\n /** Семантический цвет иконки заголовка. */\n public readonly iconColor: InputSignal<IRtTabs.TitleColor> = input<IRtTabs.TitleColor>('current');\n\n /** Значение бейджа справа от заголовка (число/строка). `null` — без бейджа. */\n public readonly badge: InputSignal<string | number | null> = input<string | number | null>(null);\n\n /**\n * Подсказка при наведении на бейдж. Подсказка самой кнопки занята неверной вкладкой,\n * поэтому у бейджа своя. Пусто — подсказки нет.\n */\n public readonly badgeTitle: InputSignal<string> = input<string>('');\n\n /**\n * Подпись бейджа для чтения с экрана: точка или число сами по себе не говорят, что значат.\n * Пусто — атрибут не ставится, и озвучивается значение бейджа как есть.\n */\n public readonly badgeAriaLabel: InputSignal<string> = input<string>('');\n\n /** Заблокированная вкладка: не выбирается и не получает фокус. */\n public readonly disabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Скрытая вкладка: не рендерится ни в шапке, ни в контенте. */\n public readonly hidden: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Вкладка с ошибками: подсвечивается danger-цветом. */\n public readonly invalid: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Подсказка для невалидной вкладки. Пусто — берётся переведённое умолчание. */\n public readonly invalidMessage: InputSignal<string> = input<string>('');\n\n /**\n * Подсказка при наведении на вкладку — в том числе на отключённую, чтобы объяснить, почему она\n * недоступна. У вкладки без подписи она же становится её именем для чтения с экрана.\n */\n public readonly tooltip: InputSignal<string> = input<string>('');\n\n /** Вкладку можно закрыть: крестик в шапке и клавиша Delete поднимают `tabClose` у `rt-tabs`. */\n public readonly closable: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Подсказка крестика закрываемой вкладки. Пусто — подсказки нет. */\n public readonly closeTooltip: InputSignal<string> = input<string>('');\n\n /** Сторона подсказки крестика. Не задана — сторона подсказки по умолчанию. */\n public readonly closeTooltipPlacement: InputSignal<IRtTooltip.Placement | null> = input<IRtTooltip.Placement | null>(null);\n\n /**\n * Указатель стоит на крестике. Выставляет `rt-tabs`: пока он там, подсказка самой вкладки\n * молчит, и видна только подсказка крестика.\n */\n public readonly closeHovered: WritableSignal<boolean> = signal<boolean>(false);\n\n /** Готовый текст подсказки: своя формулировка важнее умолчания. */\n public readonly invalidTitle: Signal<string> = computed((): string => this.invalidMessage() || this.#t_uiTabInvalid());\n\n /**\n * Подсказка кнопки вкладки: у неверной — объяснение ошибки, иначе своя подсказка. Пока\n * указатель на крестике, пусто: две подсказки разом читались бы как одна. Крестик, убранный\n * из-под указателя, ухода не сообщает, поэтому признак читается вместе с `showClose`.\n */\n public readonly buttonTooltip: Signal<string> = computed((): string => {\n if (this.closeHovered() && this.showClose()) {\n return '';\n }\n\n return this.invalid() ? this.invalidTitle() : this.tooltip();\n });\n\n /**\n * Имя вкладки для чтения с экрана, когда видимой подписи нет: вкладка из одного значка\n * называется своей подсказкой. С подписью или своим заголовком атрибут не ставится.\n */\n public readonly ariaLabel: Signal<string | null> = computed((): string | null =>\n this.label() || this.titleTemplate() ? null : this.tooltip() || null\n );\n\n /**\n * Имя крестика для чтения с экрана: текст его подсказки, без подсказки — переведённое «Закрыть».\n * Крестик — отдельная кнопка, и без имени диктор назвал бы её просто «кнопка».\n */\n public readonly closeLabel: Signal<string> = computed((): string => this.closeTooltip() || this.#t_uiClose());\n\n /** Крестик рисуется только у доступной вкладки: отключённую закрыть нельзя. */\n public readonly showClose: Signal<boolean> = computed((): boolean => this.closable() && !this.disabled());\n}\n","import {\n afterRenderEffect,\n computed,\n DestroyRef,\n ElementRef,\n inject,\n linkedSignal,\n Signal,\n signal,\n untracked,\n WritableSignal,\n} from '@angular/core';\n\nimport { RtTabDirective } from './rt-tab.directive';\nimport { IRtTabs } from './rt-tabs.model';\n\n/** Признак, по которому пользователь просит обходиться без движения. */\nexport const RT_TABS_REDUCED_MOTION: string = '(prefers-reduced-motion: reduce)';\n\n/** Куда сдвигается содержимое: к вкладке правее (`forward`) или левее (`backward`). */\nexport type TRtTabsPanelShift = 'forward' | 'backward';\n\n/** Панель прежней вкладки, пока её уход не кончился, и место, с которого она уходит (px от хоста). */\nexport interface IRtTabsLeavingPanel {\n readonly id: IRtTabs.Id;\n readonly shift: TRtTabsPanelShift;\n readonly top: number;\n readonly left: number;\n}\n\n/** Смена выбора: с какой вкладки, на какую и длительность из входа (`null` — из токена). */\nexport interface IRtTabsMove {\n readonly previous: IRtTabs.Id | null;\n readonly next: IRtTabs.Id | null;\n readonly duration: string | null;\n}\n\n/**\n * Панель в области содержимого: активная, уходящая (`leaving`) или сохранённая скрытой (`idle`) —\n * тело посещённой вкладки при `preserveContent`.\n */\nexport interface IRtTabsPanel {\n readonly tab: RtTabDirective;\n readonly leaving: IRtTabsLeavingPanel | null;\n readonly idle: boolean;\n}\n\n/** Что показывает область содержимого: активная вкладка, длительность и сохранение посещённых. */\nexport interface IRtTabsShown {\n readonly active: Signal<RtTabDirective | null>;\n readonly duration: () => IRtTabs.AnimationDuration;\n readonly preserve: () => boolean;\n}\n\n/** Вкладки компонента: все объявленные, видимые и выбранная. */\nexport interface IRtTabsSet {\n readonly all: Signal<readonly RtTabDirective[]>;\n readonly visible: Signal<readonly RtTabDirective[]>;\n readonly selectedId: Signal<IRtTabs.Id | null>;\n}\n\n/** Место полосы выбранной вкладки внутри полосы вкладок: левый край, низ вкладки и ширина (px). */\ninterface IInkBox {\n readonly x: number;\n readonly bottom: number;\n readonly width: number;\n}\n\n/** Длительность из входа в значение CSS: число и строка из одних цифр — миллисекунды. */\nexport function rtTabsCssDuration(value: IRtTabs.AnimationDuration): string | null {\n const text: string = value === null ? '' : String(value).trim();\n\n if (!text) {\n return null;\n }\n\n return /^\\d+(\\.\\d+)?$/.test(text) ? `${text}ms` : text;\n}\n\n/** Длительность CSS в миллисекундах; то, что не читается как время, — ноль. */\nexport function rtTabsDurationMs(value: string): number {\n const text: string = value.trim();\n const amount: number = parseFloat(text);\n\n if (Number.isNaN(amount)) {\n return 0;\n }\n\n if (text.endsWith('ms')) {\n return amount;\n }\n\n return text.endsWith('s') ? amount * 1000 : amount;\n}\n\n/** Набор посещённых вкладок с вкладкой `id`: тот же набор, если она в нём уже есть. */\nfunction withVisited(visited: ReadonlySet<IRtTabs.Id>, id: IRtTabs.Id | null): ReadonlySet<IRtTabs.Id> {\n return id === null || visited.has(id) ? visited : new Set([...visited, id]);\n}\n\nfunction sameInkBox(a: IInkBox | null, b: IInkBox | null): boolean {\n if (a === null || b === null) {\n return a === b;\n }\n\n return a.x === b.x && a.bottom === b.bottom && a.width === b.width;\n}\n\n/**\n * Уходящая панель при смене выбора. Место берётся у панели прежней вкладки, пока она ещё в потоке:\n * уходя, она встаёт поверх области содержимого в ту же точку. Без движения — нулевая длительность\n * или `prefers-reduced-motion` — уходящей панели нет.\n */\nexport function rtTabsLeavingPanel(\n host: HTMLElement,\n win: Window | null,\n ids: readonly IRtTabs.Id[],\n move: IRtTabsMove\n): IRtTabsLeavingPanel | null {\n const { previous, next } = move;\n\n if (previous === null || next === null || previous === next || !win) {\n return null;\n }\n\n if (win.matchMedia?.(RT_TABS_REDUCED_MOTION).matches) {\n return null;\n }\n\n const duration: string = move.duration ?? win.getComputedStyle(host).getPropertyValue('--rt-tabs-panel-duration');\n const panel: HTMLElement | undefined = Array.from(host.querySelectorAll<HTMLElement>(':scope > .rt-tabs__content')).find(\n (node: HTMLElement): boolean => node.id === `rt-tabpanel-${previous}`\n );\n\n if (!panel || rtTabsDurationMs(duration) <= 0) {\n return null;\n }\n\n const hostBox: DOMRect = host.getBoundingClientRect();\n const panelBox: DOMRect = panel.getBoundingClientRect();\n\n return {\n id: previous,\n shift: ids.indexOf(next) > ids.indexOf(previous) ? 'forward' : 'backward',\n top: panelBox.top - hostBox.top - host.clientTop,\n left: panelBox.left - hostBox.left - host.clientLeft,\n };\n}\n\n/**\n * Панели при сохранении посещённых: тело вкладки появляется при первом открытии и дальше живёт\n * скрытым. Порядок — порядок вкладок, чтобы вид панели не переставлялся в разметке при смене.\n */\nexport function rtTabsPreservedPanels(\n all: readonly RtTabDirective[],\n visited: ReadonlySet<IRtTabs.Id>,\n active: RtTabDirective,\n leaving: IRtTabsLeavingPanel | null\n): IRtTabsPanel[] {\n return all\n .filter((tab: RtTabDirective): boolean => tab === active || visited.has(tab.id()))\n .map((tab: RtTabDirective): IRtTabsPanel => {\n if (tab === active) {\n return { leaving: null, idle: false, tab };\n }\n\n const isLeaving: boolean = leaving !== null && leaving.id === tab.id();\n\n return { leaving: isLeaving ? leaving : null, idle: !isLeaving, tab };\n });\n}\n\n/**\n * Смена панелей: уходящая панель прежней вкладки и въезжающая новая. Уходящая считается от смены\n * выбора и гасится концом её движения. Создаётся в контексте внедрения компонента.\n */\nexport class RtTabsPanels {\n /** Панель прежней вкладки, пока она уходит; без движения её нет вовсе. */\n public readonly leaving: WritableSignal<IRtTabsLeavingPanel | null>;\n\n /**\n * Панели области содержимого: активная и, пока она уходит, прежняя. Прежняя стоит первой, и\n * `track` по id сохраняет её вид — уходит та же панель, а не её новая копия. При сохранении\n * посещённых панели стоят в порядке вкладок, и неактивные остаются скрытыми.\n */\n public readonly list: Signal<readonly IRtTabsPanel[]>;\n\n /** Вкладки, которые открывались хоть раз: их тела живут при `preserveContent`. */\n readonly #visited: Signal<ReadonlySet<IRtTabs.Id>>;\n\n /** Направление идущей смены панели; `null` — панель стоит на месте. */\n public readonly shift: Signal<TRtTabsPanelShift | null>;\n\n /** Длительность из входа `animationDuration` в виде CSS; `null` — длительности из токенов. */\n public readonly duration: Signal<string | null>;\n\n /** Длительности полосы и панели на хосте из входа; без входа их держат токены. Прокрутку полосы\n * вход не трогает, как у `mat-tab-group`: её длительность — только токен. */\n public readonly durations: Signal<Readonly<Record<string, string>> | null>;\n\n constructor(host: HTMLElement, win: Window | null, tabs: IRtTabsSet, shown: IRtTabsShown) {\n this.duration = computed((): string | null => rtTabsCssDuration(shown.duration()));\n this.durations = computed((): Readonly<Record<string, string>> | null => {\n const duration: string | null = this.duration();\n\n return duration === null\n ? null\n : {\n '--rt-tabs-indicator-duration': duration,\n '--rt-tabs-panel-duration': duration,\n };\n });\n const ids: () => IRtTabs.Id[] = (): IRtTabs.Id[] => tabs.visible().map((tab: RtTabDirective): IRtTabs.Id => tab.id());\n\n this.leaving = linkedSignal<IRtTabs.Id | null, IRtTabsLeavingPanel | null>({\n source: tabs.selectedId,\n computation: (id: IRtTabs.Id | null, previous: { source: IRtTabs.Id | null } | undefined): IRtTabsLeavingPanel | null =>\n untracked((): IRtTabsLeavingPanel | null =>\n rtTabsLeavingPanel(host, win, ids(), { previous: previous?.source ?? null, next: id, duration: this.duration() })\n ),\n });\n\n this.#visited = linkedSignal<IRtTabs.Id | null, ReadonlySet<IRtTabs.Id>>({\n source: tabs.selectedId,\n computation: (id: IRtTabs.Id | null, previous: { value: ReadonlySet<IRtTabs.Id> } | undefined): ReadonlySet<IRtTabs.Id> =>\n withVisited(previous?.value ?? new Set(), id),\n });\n\n this.list = computed((): readonly IRtTabsPanel[] => {\n const active: RtTabDirective | null = shown.active();\n const leaving: IRtTabsLeavingPanel | null = this.leaving();\n\n if (!active) {\n return [];\n }\n\n if (shown.preserve()) {\n return rtTabsPreservedPanels(tabs.all(), this.#visited(), active, leaving);\n }\n\n const current: IRtTabsPanel = { tab: active, leaving: null, idle: false };\n const leavingTab: RtTabDirective | undefined =\n leaving === null || leaving.id === active.id()\n ? undefined\n : tabs.visible().find((tab: RtTabDirective): boolean => tab.id() === leaving.id);\n\n return leaving && leavingTab ? [{ leaving, idle: false, tab: leavingTab }, current] : [current];\n });\n\n this.shift = computed((): TRtTabsPanelShift | null =>\n this.list().some((panel: IRtTabsPanel): boolean => panel.leaving !== null) ? (this.leaving()?.shift ?? null) : null\n );\n }\n\n /** Конец движения панели убирает уходящую. Движение вложенных узлов сюда не считается. */\n public animationEnd(event: AnimationEvent): void {\n if (event.target === event.currentTarget) {\n this.leaving.set(null);\n }\n }\n}\n\n/**\n * Полоса выбранной вкладки — один элемент на всю полосу: замер ставит её под выбранную вкладку, и\n * при смене выбора она переезжает. Слежение за размером полосы и вкладок ловит сдвиг без смены\n * выбора — подпись поменялась или шрифт догрузился.\n */\nexport class RtTabsInk {\n readonly #win: Window | null;\n\n readonly #list: Signal<ElementRef<HTMLElement> | undefined>;\n\n readonly #active: Signal<RtTabDirective | null>;\n\n #watch: ResizeObserver | null = null;\n\n /** Где стоит полоса; `null` — не измерена, и полосу рисует сама вкладка. */\n public readonly box: WritableSignal<IInkBox | null> = signal<IInkBox | null>(null, { equal: sameInkBox });\n\n /** Полоса уже стоит на месте и дальше переезжает: первое измерение ставит её без движения. */\n public readonly animated: WritableSignal<boolean> = signal(false);\n\n /** Сдвиг полосы к левому краю вкладки и к её низу. */\n public readonly translate: Signal<string | null> = computed((): string | null => {\n const box: IInkBox | null = this.box();\n\n return box ? `${box.x}px ${box.bottom}px` : null;\n });\n\n /** Полоса красится как ошибка, когда выбранная вкладка неверна. */\n public readonly invalid: Signal<boolean> = computed((): boolean => this.#active()?.invalid() ?? false);\n\n constructor(\n win: Window | null,\n list: Signal<ElementRef<HTMLElement> | undefined>,\n tabs: { readonly visible: Signal<readonly RtTabDirective[]>; readonly active: Signal<RtTabDirective | null> }\n ) {\n this.#win = win;\n this.#list = list;\n this.#active = tabs.active;\n\n // Новая вкладка в полосе — новый узел под слежение, новый выбор — новое место полосы.\n afterRenderEffect((): void => {\n tabs.visible();\n this.#active();\n this.#watchSizes();\n this.#place();\n });\n\n inject(DestroyRef).onDestroy((): void => this.#watch?.disconnect());\n }\n\n /** Перевешивает слежение за размером на вкладки, что сейчас стоят в полосе. */\n #watchSizes(): void {\n const list: HTMLElement | undefined = this.#list()?.nativeElement;\n\n if (!list || typeof ResizeObserver === 'undefined') {\n return;\n }\n\n if (!this.#watch) {\n this.#watch = new ResizeObserver((): void => this.#place());\n }\n\n const watch: ResizeObserver = this.#watch;\n watch.disconnect();\n watch.observe(list);\n list.querySelectorAll<HTMLElement>('[data-tabitem]').forEach((node: HTMLElement): void => watch.observe(node));\n }\n\n /** Ставит полосу под выбранную вкладку. Дробные размеры сохраняются: полоса ложится ровно по вкладке. */\n #place(): void {\n const list: HTMLElement | undefined = this.#list()?.nativeElement;\n const id: IRtTabs.Id | undefined = this.#active()?.id();\n const tab: HTMLElement | null | undefined = id === undefined ? null : list?.querySelector<HTMLElement>(`[data-tabitem=\"${id}\"]`);\n\n if (!list || !tab) {\n this.box.set(null);\n return;\n }\n\n const listBox: DOMRect = list.getBoundingClientRect();\n const tabBox: DOMRect = tab.getBoundingClientRect();\n\n this.box.set({\n x: tabBox.left - listBox.left - list.clientLeft + list.scrollLeft,\n bottom: tabBox.bottom - listBox.top - list.clientTop + list.scrollTop,\n width: tabBox.width,\n });\n\n if (!untracked(this.animated)) {\n this.#win?.requestAnimationFrame((): void => this.animated.set(true));\n }\n }\n}\n","import { ElementRef } from '@angular/core';\n\nimport { IRtTabs } from './rt-tabs.model';\nimport { RT_TABS_REDUCED_MOTION, rtTabsDurationMs } from './rt-tabs.motion';\n\n/** Кривая, которой читается непонятное значение. */\nconst EASE_OUT: readonly [number, number, number, number] = [0, 0, 0.58, 1];\n\n/** Именованные кривые CSS в виде опорных точек `cubic-bezier`. */\nconst NAMED_EASINGS: ReadonlyMap<string, readonly [number, number, number, number]> = new Map<\n string,\n readonly [number, number, number, number]\n>([\n ['linear', [0, 0, 1, 1]],\n ['ease', [0.25, 0.1, 0.25, 1]],\n ['ease-in', [0.42, 0, 1, 1]],\n ['ease-out', EASE_OUT],\n ['ease-in-out', [0.42, 0, 0.58, 1]],\n]);\n\n/** Шаг прокрутки полосы за один тик удержания стрелки (px). */\nconst HOLD_STEP: number = 12;\n\n/** Сдвиг одного нажатия на стрелку при шаге `fixed` (px): столько давал короткий клик до шага на страницу. */\nconst FIXED_STEP: number = 80;\n\n/** Доля видимой ширины полосы, на которую сдвигает одно нажатие на стрелку при шагах `page` и `third`. */\nconst STEP_SHARE: Readonly<Record<Exclude<IRtTabs.ScrollStep, 'fixed'>, number>> = { page: 1, third: 1 / 3 };\n\n/** Точка кубической кривой Безье с концами 0 и 1 по одной оси. */\nfunction bezierAt(t: number, p1: number, p2: number): number {\n const u: number = 1 - t;\n\n return 3 * u * u * t * p1 + 3 * u * t * t * p2 + t * t * t;\n}\n\n/**\n * Кривая CSS как функция доли времени в долю пути: `linear`, `ease`, `ease-in`, `ease-out`,\n * `ease-in-out` и `cubic-bezier(…)`. Непонятное значение читается как `ease-out`.\n */\nexport function rtTabsEasing(value: string): (progress: number) => number {\n const text: string = value.trim();\n const match: RegExpMatchArray | null = /^cubic-bezier\\(([^)]*)\\)$/.exec(text);\n const parsed: number[] = match ? match[1].split(',').map((part: string): number => parseFloat(part)) : [];\n const valid: boolean = parsed.length === 4 && parsed.every((point: number): boolean => Number.isFinite(point));\n const points: readonly number[] = valid ? parsed : (NAMED_EASINGS.get(text) ?? EASE_OUT);\n const [x1, y1, x2, y2]: readonly number[] = points;\n\n return (progress: number): number => {\n if (progress <= 0 || progress >= 1) {\n return Math.min(1, Math.max(0, progress));\n }\n\n // Доля времени — координата x на кривой: её параметр ищется делением отрезка пополам.\n let low: number = 0;\n let high: number = 1;\n for (let step: number = 0; step < 30; step++) {\n const mid: number = (low + high) / 2;\n if (bezierAt(mid, x1, x2) < progress) {\n low = mid;\n } else {\n high = mid;\n }\n }\n\n return bezierAt((low + high) / 2, y1, y2);\n };\n}\n\n/** Куда прокрутить полосу нажатием на стрелку: на шаг `step` от `from`, не дальше края. */\nexport function rtTabsPageTarget(list: HTMLElement, from: number, back: boolean, step: IRtTabs.ScrollStep): number {\n const max: number = Math.max(0, list.scrollWidth - list.clientWidth);\n const shift: number = step === 'fixed' ? FIXED_STEP : list.clientWidth * STEP_SHARE[step];\n\n return Math.min(max, Math.max(0, from + (back ? -shift : shift)));\n}\n\n/**\n * Куда прокрутить полосу, чтобы вкладка встала целиком; `null` — она уже видна целиком. `inset` —\n * ширина стрелки поверх края полосы: вкладка не у конца полосы отступает от края на неё, иначе\n * встала бы под стрелку.\n */\nexport function rtTabsIntoViewTarget(list: HTMLElement, tab: HTMLElement, inset: number = 0): number | null {\n const left: number = tab.offsetLeft;\n const right: number = left + tab.offsetWidth;\n const before: number = left > 0 ? inset : 0;\n // 1px — погрешность субпиксельного scrollWidth\n const after: number = list.scrollWidth - right > 1 ? inset : 0;\n\n if (left - before < list.scrollLeft) {\n return Math.max(left - before, 0);\n }\n\n if (right + after > list.scrollLeft + list.clientWidth) {\n return right + after - list.clientWidth;\n }\n\n return null;\n}\n\n/**\n * Плавная прокрутка полосы вкладок. Двигается сама прокрутка, а не сдвиг содержимого: колесо,\n * касание и полоса прокрутки остаются у браузера. Длительность и кривая — свойства хоста\n * `--rt-tabs-scroll-duration` и `--rt-tabs-scroll-easing`; ноль или `prefers-reduced-motion` —\n * прокрутка сразу.\n */\nexport class RtTabsScroller {\n readonly #win: Window | null;\n\n readonly #host: HTMLElement;\n\n readonly #list: () => ElementRef<HTMLElement> | undefined;\n\n #frame: number | null = null;\n\n /** Куда едет идущая прокрутка: следующий шаг считается от неё, а не от середины пути. */\n #target: number | null = null;\n\n constructor(win: Window | null, host: HTMLElement, list: () => ElementRef<HTMLElement> | undefined) {\n this.#win = win;\n this.#host = host;\n this.#list = list;\n }\n\n /** Положение, от которого считать следующий шаг: цель идущей прокрутки или текущее. */\n public from(): number {\n return this.#target ?? this.#list()?.nativeElement.scrollLeft ?? 0;\n }\n\n /** Прокручивает полосу к `left`; новая прокрутка заменяет идущую. */\n public to(left: number): void {\n const list: HTMLElement | undefined = this.#list()?.nativeElement;\n const win: Window | null = this.#win;\n this.stop();\n\n if (!list || !win) {\n return;\n }\n\n const style: CSSStyleDeclaration = win.getComputedStyle(this.#host);\n const duration: number = win.matchMedia?.(RT_TABS_REDUCED_MOTION).matches\n ? 0\n : rtTabsDurationMs(style.getPropertyValue('--rt-tabs-scroll-duration'));\n const start: number = list.scrollLeft;\n\n if (duration <= 0 || start === left) {\n list.scrollLeft = left;\n return;\n }\n\n const ease: (progress: number) => number = rtTabsEasing(style.getPropertyValue('--rt-tabs-scroll-easing'));\n const startedAt: number = win.performance.now();\n this.#target = left;\n\n const tick: (now: number) => void = (now: number): void => {\n const progress: number = Math.min(1, (now - startedAt) / duration);\n list.scrollLeft = start + (left - start) * ease(progress);\n this.#frame = progress < 1 ? win.requestAnimationFrame(tick) : null;\n if (this.#frame === null) {\n this.#target = null;\n }\n };\n this.#frame = win.requestAnimationFrame(tick);\n }\n\n /**\n * Тик прокрутки удержанием стрелки: сдвиг на несколько точек без плавности, остановив идущую.\n * Отвечает, осталось ли куда ехать.\n */\n public nudge(back: boolean): boolean {\n this.stop();\n const list: HTMLElement | undefined = this.#list()?.nativeElement;\n\n if (!list) {\n return false;\n }\n\n const remaining: number = back ? list.scrollLeft : list.scrollWidth - list.scrollLeft - list.clientWidth;\n\n if (remaining > 0) {\n list.scrollLeft += (back ? -1 : 1) * Math.min(HOLD_STEP, remaining);\n }\n\n return remaining - HOLD_STEP > 0;\n }\n\n /** Останавливает идущую прокрутку там, где она есть. */\n public stop(): void {\n if (this.#frame !== null) {\n this.#win?.cancelAnimationFrame(this.#frame);\n }\n this.#frame = null;\n this.#target = null;\n }\n}\n","import { IRtTabs } from './rt-tabs.model';\nimport { rtTabsPageTarget, RtTabsScroller } from './rt-tabs.scroll';\n\n/** Интервал тика прокрутки при зажатой стрелке (мс). */\nconst SCROLL_TICK_MS: number = 15;\n\n/** Сколько держать стрелку, чтобы нажатие стало прокруткой по удержанию, а не шагом (мс). */\nconst HOLD_DELAY_MS: number = 300;\n\nexport type TRtTabsScrollDirection = 'before' | 'after';\n\n/**\n * Нажатие на стрелку прокрутки полосы. Отпущенная до `HOLD_DELAY_MS` стрелка сдвигает полосу на\n * шаг `scrollStep`, удержанная дольше — прокручивает её непрерывно, пока не отпустят.\n */\nexport class RtTabsArrowPress {\n readonly #win: Window | null;\n\n readonly #scroller: RtTabsScroller;\n\n readonly #list: () => HTMLElement | undefined;\n\n readonly #step: () => IRtTabs.ScrollStep;\n\n /** Полоса сдвинулась: видимость стрелок пересчитывается. */\n readonly #moved: () => void;\n\n /** Хэндл интервала прокрутки по удержанию стрелки. */\n #scrollIntervalId: number | null = null;\n\n /** Хэндл ожидания, после которого нажатие на стрелку становится удержанием. */\n #holdTimeoutId: number | null = null;\n\n /** Стрелка, нажатая и ещё не отпущенная. */\n #pressed: TRtTabsScrollDirection | null = null;\n\n constructor(\n win: Window | null,\n scroller: RtTabsScroller,\n list: () => HTMLElement | undefined,\n step: () => IRtTabs.ScrollStep,\n moved: () => void\n ) {\n this.#win = win;\n this.#scroller = scroller;\n this.#list = list;\n this.#step = step;\n this.#moved = moved;\n }\n\n /** Стрелку нажали: через `HOLD_DELAY_MS` нажатие становится удержанием. */\n public down(direction: TRtTabsScrollDirection): void {\n if (this.#pressed !== null || !this.#win) {\n return;\n }\n\n this.#pressed = direction;\n this.#holdTimeoutId = this.#win.setTimeout((): void => {\n this.#holdTimeoutId = null;\n this.#scrollIntervalId =\n this.#win?.setInterval((): void => {\n if (!this.#scroller.nudge(direction === 'before')) {\n this.stop();\n }\n this.#moved();\n }, SCROLL_TICK_MS) ?? null;\n }, HOLD_DELAY_MS);\n }\n\n /** Стрелку отпустили: короткое нажатие — шаг `scrollStep`, после удержания — только стоп. */\n public up(): void {\n const direction: TRtTabsScrollDirection | null = this.#pressed;\n const shortPress: boolean = this.#holdTimeoutId !== null;\n const list: HTMLElement | undefined = this.#list();\n\n this.stop();\n\n if (direction !== null && shortPress && list) {\n this.#scroller.to(rtTabsPageTarget(list, this.#scroller.from(), direction === 'before', this.#step()));\n // Сразу — для прокрутки без движения; плавную ведут события прокрутки самой полосы.\n this.#moved();\n }\n }\n\n /** Снимает ожидание и интервал: указатель ушёл со стрелки или компонент разрушен с зажатой. */\n public stop(): void {\n this.#pressed = null;\n if (this.#win && this.#holdTimeoutId !== null) {\n this.#win.clearTimeout(this.#holdTimeoutId);\n this.#holdTimeoutId = null;\n }\n if (this.#win && this.#scrollIntervalId !== null) {\n this.#win.clearInterval(this.#scrollIntervalId);\n this.#scrollIntervalId = null;\n }\n }\n}\n","/**\n * Следит за размерами вкладок полосы. Вкладки стали шире или уже — например, у них появились\n * счётчики после загрузки данных — и полоса снова встаёт к выбранной вкладке. Человек сам прокрутил\n * полосу колесом, касанием или стрелкой — полоса больше не следит, пока не выберут вкладку.\n */\nexport class RtTabsFollow {\n /** Размеры вкладок изменились, а человек полосу не трогал. */\n readonly #resized: () => void;\n\n #observer: ResizeObserver | null = null;\n\n #list: HTMLElement | null = null;\n\n /** Полосу прокрутили рукой: смена размеров её больше не двигает. */\n #manual: boolean = false;\n\n readonly #onManual: () => void = (): void => this.manual();\n\n constructor(resized: () => void) {\n this.#resized = resized;\n }\n\n /** Наблюдает полосу и все её `count` вкладок заново: зовётся, когда сменился набор вкладок. */\n public watch(list: HTMLElement | undefined, count: number): void {\n // Окно без наблюдателя — серверная отрисовка и старые движки: полоса просто не следит.\n if (typeof ResizeObserver === 'undefined' || !list || !count) {\n return;\n }\n\n if (this.#list !== list) {\n this.#unlisten();\n list.addEventListener('wheel', this.#onManual, { passive: true });\n list.addEventListener('touchstart', this.#onManual, { passive: true });\n this.#list = list;\n }\n\n this.#observer ??= new ResizeObserver((): void => {\n if (!this.#manual) {\n this.#resized();\n }\n });\n const observer: ResizeObserver = this.#observer;\n observer.disconnect();\n observer.observe(list);\n list.querySelectorAll<HTMLElement>('[data-tabitem]').forEach((item: HTMLElement): void => observer.observe(item));\n }\n\n public manual(): void {\n this.#manual = true;\n }\n\n /** Выбрали вкладку: полоса снова следит за ней. */\n public follow(): void {\n this.#manual = false;\n }\n\n public stop(): void {\n this.#observer?.disconnect();\n this.#unlisten();\n }\n\n #unlisten(): void {\n this.#list?.removeEventListener('wheel', this.#onManual);\n this.#list?.removeEventListener('touchstart', this.#onManual);\n this.#list = null;\n }\n}\n","import { Directive, inject, input, InputSignalWithTransform, TemplateRef } from '@angular/core';\n\nimport { IRtTabs } from './rt-tabs.model';\n\n/**\n * Декларирует header-контрол `<rt-tabs>` — произвольный шаблон (кнопка, фильтр),\n * который рендерится слева или справа от полосы вкладок. Ставится на\n * `<ng-template>`; `rt-tabs` собирает контролы через `contentChildren` и\n * раскладывает по сторонам согласно `side`.\n */\n@Directive({\n selector: '[rtTabsControl]',\n})\nexport class RtTabsControlDirective {\n /** Шаблон контрола, выводимый в header-слоте. */\n public readonly templateRef: TemplateRef<unknown> = inject<TemplateRef<unknown>>(TemplateRef);\n\n /**\n * Сторона размещения относительно полосы вкладок.\n *\n * Пустое значение приводится к правой стороне: `<ng-template rtTabsControl>` без значения\n * задаёт входу пустую строку, а не умолчание, и такой контрол не попадал ни в левый слот,\n * ни в правый — он пропадал из шапки вовсе.\n */\n public readonly side: InputSignalWithTransform<IRtTabs.ControlSide, IRtTabs.ControlSide | ''> = input<\n IRtTabs.ControlSide,\n IRtTabs.ControlSide | ''\n >('right', {\n alias: 'rtTabsControl',\n transform: (value: IRtTabs.ControlSide | ''): IRtTabs.ControlSide => (value === '' ? 'right' : value),\n });\n}\n","import { BooleanInput } from '@angular/cdk/coercion';\nimport { DOCUMENT, NgTemplateOutlet } from '@angular/common';\nimport {\n afterNextRender,\n afterRenderEffect,\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChildren,\n DestroyRef,\n ElementRef,\n inject,\n Injector,\n input,\n InputSignal,\n InputSignalWithTransform,\n output,\n OutputEmitterRef,\n Signal,\n signal,\n viewChild,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nimport { debounceTime, fromEvent } from 'rxjs';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\nimport { RtTabDirective } from './rt-tab.directive';\nimport { RtTabsArrowPress, TRtTabsScrollDirection } from './rt-tabs.arrow-press';\nimport { RtTabsFollow } from './rt-tabs.follow';\nimport { RtTabsControlDirective } from './rt-tabs-control.directive';\nimport { IRtTabs } from './rt-tabs.model';\nimport { RtTabsInk, RtTabsPanels } from './rt-tabs.motion';\nimport { rtTabsIntoViewTarget, RtTabsScroller } from './rt-tabs.scroll';\n\n/** Дебаунс пересчёта видимости стрелок прокрутки на resize/scroll (мс). */\nconst REST_DEBOUNCE_MS: number = 50;\n\nconst BEM_BLOCK: string = 'rt-tabs';\n\n/**\n * Полоса вкладок с проекцией контента. Вкладки декларируются через\n * `<ng-template rtTab=\"id\" label=\"…\">…</ng-template>` (см. {@link RtTabDirective}),\n * собираются `contentChildren` и рендерятся как header-кнопки + активная панель.\n * Опциональные header-контролы — через `[rtTabsControl]`.\n *\n * Компонент \"controlled-ish\": активная вкладка берётся из `activeId` (если\n * задан), иначе — из внутреннего выбора, иначе — первая доступная. Клик/клавиша\n * эмиттят `activeIdChange`; синхронизацию `activeId` оставляем потребителю.\n *\n * Горизонтальная полоса при переполнении прячет вкладки под скролл и показывает\n * стрелки-«хвосты» (`__rest`): нажатие сдвигает полосу на шаг `scrollStep`, удержание\n * прокручивает непрерывно. Стрелки стоят поверх вкладок или, при `scrollArrows=\"inline\"`, в своих\n * местах по краям. Вертикальная ориентация раскладывает вкладки в колонку без стрелок.\n *\n * Смена вкладки движется: полоса выбранной вкладки — один элемент полосы, он переезжает на новую\n * вкладку; панель прежней вкладки уходит в сторону, обратную переходу, новая въезжает следом.\n * Длительности — токены `--rt-tabs-indicator-duration` и `--rt-tabs-panel-duration` или вход\n * `animationDuration`; `prefers-reduced-motion` снимает движение целиком.\n *\n * Доступность: `role=\"tablist\"`/`role=\"tab\"`/`role=\"tabpanel\"`, `aria-selected`,\n * roving `tabindex`, навигация стрелками + Home/End; при `activation=\"manual\"` они только\n * переводят фокус, а вкладку открывают Enter и Space.\n */\n@Component({\n selector: 'rt-tabs',\n templateUrl: './rt-tabs.component.html',\n styleUrl: './rt-tabs.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // angular\n NgTemplateOutlet,\n\n // standalone components / directives\n RtIconComponent,\n RtTooltipDirective,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n host: {\n class: BEM_BLOCK,\n '[class.rt-tabs--direction--horizontal]': \"direction() === 'horizontal'\",\n '[class.rt-tabs--direction--vertical]': \"direction() === 'vertical'\",\n '[class.rt-tabs--animating]': 'panels.shift() !== null',\n '[style]': 'panels.durations()',\n },\n})\nexport class RtTabsComponent {\n /** `Window` через `DOCUMENT` (SSR-safe: `defaultView` может быть `null`). */\n readonly #win: Window | null = inject(DOCUMENT).defaultView;\n\n readonly #host: HTMLElement = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n /** Все задекларированные вкладки (включая скрытые). */\n protected readonly tabs: Signal<readonly RtTabDirective[]> = contentChildren(RtTabDirective);\n\n /** Все header-контролы. */\n protected readonly controls: Signal<readonly RtTabsControlDirective[]> = contentChildren(RtTabsControlDirective);\n\n /** Видимые вкладки (без `hidden`). */\n protected readonly visibleTabs: Signal<readonly RtTabDirective[]> = computed((): readonly RtTabDirective[] =>\n this.tabs().filter((tab: RtTabDirective): boolean => !tab.hidden())\n );\n\n protected readonly leftControls: Signal<readonly RtTabsControlDirective[]> = computed((): readonly RtTabsControlDirective[] =>\n this.controls().filter((c: RtTabsControlDirective): boolean => c.side() === 'left')\n );\n\n protected readonly rightControls: Signal<readonly RtTabsControlDirective[]> = computed((): readonly RtTabsControlDirective[] =>\n this.controls().filter((c: RtTabsControlDirective): boolean => c.side() === 'right')\n );\n\n /**\n * Эффективный id активной вкладки. Приоритет: контролируемый `activeId` →\n * внутренний выбор → первая доступная. Кандидат валидируется по множеству\n * видимых незаблокированных вкладок, поэтому корректно реагирует на\n * асинхронную загрузку/смену набора вкладок.\n */\n protected readonly selectedId: Signal<IRtTabs.Id | null> = computed((): IRtTabs.Id | null => {\n const enabled: readonly RtTabDirective[] = this.visibleTabs().filter((tab: RtTabDirective): boolean => !tab.disabled());\n const candidate: IRtTabs.Id | null = this.activeId() ?? this.#internalId();\n const candidateValid: boolean = candidate !== null && enabled.some((tab: RtTabDirective): boolean => tab.id() === candidate);\n\n let result: IRtTabs.Id | null;\n if (candidateValid) {\n result = candidate;\n } else if (enabled.length) {\n result = enabled[0].id();\n } else {\n result = null;\n }\n\n return result;\n });\n\n /** Активная вкладка целиком (для рендера панели). */\n protected readonly activeTab: Signal<RtTabDirective | null> = computed(\n (): RtTabDirective | null => this.visibleTabs().find((tab: RtTabDirective): boolean => tab.id() === this.selectedId()) ?? null\n );\n\n /**\n * Вкладка в таб-порядке: та, на которую стрелками перевели фокус в ручном режиме, иначе\n * активная. Фокус на вкладке, которой больше нет или которая отключилась, не держится.\n */\n protected readonly focusId: Signal<IRtTabs.Id | null> = computed((): IRtTabs.Id | null => {\n const focused: IRtTabs.Id | null = this.#focusedId();\n const valid: boolean =\n focused !== null && this.visibleTabs().some((tab: RtTabDirective): boolean => tab.id() === focused && !tab.disabled());\n\n return valid ? focused : this.selectedId();\n });\n\n /** Видны ли стрелки прокрутки слева/справа (только горизонтальная полоса). */\n protected readonly restBeforeVisible: WritableSignal<boolean> = signal(false);\n protected readonly restAfterVisible: WritableSignal<boolean> = signal(false);\n\n /** Полоса шире своего места: в раскладке `inline` по этому признаку встают обе стрелки. */\n protected readonly overflowing: Signal<boolean> = computed((): boolean => this.restBeforeVisible() || this.restAfterVisible());\n\n protected readonly tabListRef: Signal<ElementRef<HTMLElement> | undefined> = viewChild<ElementRef<HTMLElement>>('tabList');\n\n /** Смена панелей: прежняя уходит в сторону, обратную переходу, новая въезжает следом. */\n protected readonly panels: RtTabsPanels = new RtTabsPanels(\n this.#host,\n this.#win,\n { all: this.tabs, visible: this.visibleTabs, selectedId: this.selectedId },\n {\n active: computed((): RtTabDirective | null => (this.headerOnly() ? null : this.activeTab())),\n // Входы объявлены ниже: на этой строке их ещё нет, и они читаются при каждом обращении.\n duration: (): IRtTabs.AnimationDuration => this.animationDuration(),\n preserve: (): boolean => this.preserveContent(),\n }\n );\n\n /** Полоса выбранной вкладки: одна на всю полосу, переезжает при смене выбора. */\n protected readonly ink: RtTabsInk = new RtTabsInk(this.#win, this.tabListRef, { visible: this.visibleTabs, active: this.activeTab });\n\n /** Контролируемый активный id. `null` — компонент сам выбирает первую вкладку. */\n public readonly activeId: InputSignal<IRtTabs.Id | null> = input<IRtTabs.Id | null>(null);\n\n /** Ориентация полосы. */\n public readonly direction: InputSignal<IRtTabs.Direction> = input<IRtTabs.Direction>('horizontal');\n\n /** Растягивать вкладки на всю ширину полосы. */\n public readonly stretch: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Скроллить область контента при переполнении. */\n public readonly contentScrollable: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(true, {\n transform: booleanAttribute,\n });\n\n /**\n * Только полоса, без панели: вкладки служат навигацией, а содержимое живёт в другом месте —\n * например, полоса стоит в середине `rt-toolbar`. Панель `role=\"tabpanel\"` не рисуется, и\n * вкладки не ссылаются на неё.\n */\n public readonly headerOnly: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Тело вкладки создаётся при первом открытии и дальше живёт скрытым, как у `mat-tab-group` с\n * `preserveContent`: введённое на вкладке переживает уход с неё. Неоткрытая вкладка не создаётся.\n */\n public readonly preserveContent: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Стрелки и Home/End открывают вкладку сразу (`auto`) или только переводят фокус (`manual`). */\n public readonly activation: InputSignal<IRtTabs.Activation> = input<IRtTabs.Activation>('auto');\n\n /** Стрелки прокрутки поверх вкладок (`overlay`) или в своих местах по краям полосы (`inline`). */\n public readonly scrollArrows: InputSignal<IRtTabs.ScrollArrows> = input<IRtTabs.ScrollArrows>('overlay');\n\n /** Шаг нажатия на стрелку: 80 px (`fixed`), видимая ширина полосы (`page`) или её треть (`third`), как у Material. */\n public readonly scrollStep: InputSignal<IRtTabs.ScrollStep> = input<IRtTabs.ScrollStep>('fixed');\n\n /**\n * Длительность движения при смене вкладки — и полосы, и панели, как у `mat-tab-group`: `500`,\n * `'500ms'`, `'0.5s'`; `0` выключает движение. Без входа длительности берутся из токенов.\n */\n public readonly animationDuration: InputSignal<IRtTabs.AnimationDuration> = input<IRtTabs.AnimationDuration>(null);\n\n /** Таб-стоп открытой панели, как `contentTabIndex` у `mat-tab-group`: `null` — Tab идёт с полосы прямо в поля панели. */\n public readonly contentTabIndex: InputSignal<number | null> = input<number | null>(0);\n\n /** Эмиттит id вкладки при её выборе (клик/клавиатура). */\n public readonly activeIdChange: OutputEmitterRef<IRtTabs.Id> = output<IRtTabs.Id>();\n\n /**\n * Просьба закрыть вкладку с `closable`: крестик или Delete на вкладке в фокусе. Набор вкладок\n * держит потребитель — он и убирает вкладку; закрытая активная откатывается на первую доступную.\n */\n public readonly tabClose: OutputEmitterRef<IRtTabs.Id> = output<IRtTabs.Id>();\n\n readonly #injector: Injector = inject(Injector);\n\n /** Плавная прокрутка полосы: стрелки и вкладка, встающая в видимую область. */\n readonly #scroller: RtTabsScroller = new RtTabsScroller(this.#win, this.#host, (): ElementRef<HTMLElement> | undefined =>\n this.tabListRef()\n );\n\n /** Внутренний выбор (uncontrolled-ветка). */\n readonly #internalId: WritableSignal<IRtTabs.Id | null> = signal<IRtTabs.Id | null>(null);\n\n /** Вкладка, на которую перевели фокус стрелками в ручном режиме; сбрасывается выбором. */\n readonly #focusedId: WritableSignal<IRtTabs.Id | null> = signal<IRtTabs.Id | null>(null);\n\n /** Нажатие и удержание стрелок прокрутки. */\n readonly #press: RtTabsArrowPress = new RtTabsArrowPress(\n this.#win,\n this.#scroller,\n (): HTMLElement | undefined => this.tabListRef()?.nativeElement,\n (): IRtTabs.ScrollStep => this.scrollStep(),\n (): void => this.#updateRestVisibility()\n );\n\n /** Вкладки стали шире или уже — полоса снова встаёт к выбранной, пока её не прокрутили рукой. */\n readonly #follow: RtTabsFollow = new RtTabsFollow((): void => this.#scrollToSelected(true));\n\n /** Вкладка, к которой полоса прокручена последней: второй прокрутки к ней не нужно. */\n #scrolledId: IRtTabs.Id | null = null;\n\n constructor() {\n if (this.#win) {\n fromEvent(this.#win, 'resize')\n .pipe(debounceTime(REST_DEBOUNCE_MS), takeUntilDestroyed())\n .subscribe((): void => this.#updateRestVisibility());\n }\n\n afterNextRender((): void => {\n this.#scrollToSelected();\n this.#updateRestVisibility();\n });\n\n // Смена вкладки извне — входом `activeId` или новым набором вкладок. После клика\n // полоса уже прокручена из `selectTab`, и `#scrolledId` пропускает вторую прокрутку.\n afterRenderEffect((): void => this.#scrollToSelected());\n\n // Новый набор вкладок — наблюдение за их размерами ставится заново.\n afterRenderEffect((): void => this.#follow.watch(this.tabListRef()?.nativeElement, this.visibleTabs().length));\n\n // Снимаем hold-scroll интервал при уничтожении: если компонент разрушить\n // с зажатой стрелкой (pointerdown без pointerup), интервал остался бы жив.\n inject(DestroyRef).onDestroy((): void => {\n this.#press.stop();\n this.#follow.stop();\n this.#scroller.stop();\n });\n }\n\n protected selectTab(id: IRtTabs.Id): void {\n const target: RtTabDirective | undefined = this.visibleTabs().find((tab: RtTabDirective): boolean => tab.id() === id);\n\n if (!target || target.disabled()) {\n return;\n }\n\n this.#internalId.set(id);\n this.#focusedId.set(null);\n this.activeIdChange.emit(id);\n this.#follow.follow();\n this.#scrollTabIntoView(id);\n }\n\n /** Крестик: нажатие не выбирает вкладку; фокус с крестика после закрытия уходит на вкладку, не на страницу. */\n protected onCloseClick(event: MouseEvent, tab: RtTabDirective): void {\n event.stopPropagation();\n this.#close(tab, event.currentTarget instanceof HTMLElement && event.currentTarget.matches(':focus'));\n }\n\n /**\n * Навигация по вкладкам с клавиатуры. Шаг считается от вкладки в фокусе: в ручном режиме она\n * не совпадает с активной. Enter и Space ловит сама кнопка — они дают click и выбор.\n */\n protected onTabKeydown(event: KeyboardEvent, tab: RtTabDirective): void {\n if (event.key === 'Delete') {\n this.#closeByKey(event, tab);\n return;\n }\n\n const enabled: readonly RtTabDirective[] = this.visibleTabs().filter((item: RtTabDirective): boolean => !item.disabled());\n\n if (!enabled.length) {\n return;\n }\n\n const isVertical: boolean = this.direction() === 'vertical';\n const nextKey: string = isVertical ? 'ArrowDown' : 'ArrowRight';\n const prevKey: string = isVertical ? 'ArrowUp' : 'ArrowLeft';\n const currentIndex: number = enabled.findIndex((item: RtTabDirective): boolean => item.id() === tab.id());\n\n // Карта клавиша → целевой индекс (без if/else-if цепочки).\n const moveByKey: ReadonlyMap<string, number> = new Map<string, number>([\n [nextKey, (currentIndex + 1) % enabled.length],\n [prevKey, (currentIndex - 1 + enabled.length) % enabled.length],\n ['Home', 0],\n ['End', enabled.length - 1],\n ]);\n\n const targetIndex: number | undefined = moveByKey.get(event.key);\n\n if (targetIndex === undefined) {\n return;\n }\n\n event.preventDefault();\n const targetId: IRtTabs.Id = enabled[targetIndex].id();\n\n if (this.activation() === 'manual') {\n this.#focusedId.set(targetId);\n this.#scrollTabIntoView(targetId);\n } else {\n this.selectTab(targetId);\n }\n this.#focusTab(targetId);\n }\n\n /** Нажатие ЛКМ на стрелку: шаг или прокрутка по удержанию — {@link RtTabsArrowPress}. */\n protected onRestPointerDown(direction: TRtTabsScrollDirection, event: MouseEvent): void {\n if (event.button === 0) {\n this.#follow.manual();\n this.#press.down(direction);\n }\n }\n\n protected onRestPointerUp(): void {\n this.#press.up();\n }\n\n /** Указатель ушёл со стрелки: прокрутка останавливается, шага нет. */\n protected onRestPointerLeave(): void {\n this.#press.stop();\n }\n\n protected onTabListScroll(): void {\n this.#updateRestVisibility();\n }\n\n /**\n * Delete на закрываемой вкладке. Фокус после перерисовки встаёт на активную вкладку: закрытая\n * пропадёт из шапки, и фокус иначе упал бы на страницу.\n */\n #closeByKey(event: KeyboardEvent, tab: RtTabDirective): void {\n if (!tab.showClose()) {\n return;\n }\n\n event.preventDefault();\n this.#close(tab, true);\n }\n\n /**\n * Просьба закрыть вкладку. Владелец убирает её из набора; если она была активной, выбор после\n * перерисовки переходит на первую доступную, и об этом сообщает `activeIdChange` — иначе владелец,\n * держащий `activeId`, хранил бы id закрытой вкладки и показывал её содержимое снаружи.\n */\n #close(tab: RtTabDirective, focus: boolean): void {\n const closedId: IRtTabs.Id = tab.id();\n const wasActive: boolean = this.selectedId() === closedId;\n this.tabClose.emit(closedId);\n\n afterNextRender(\n (): void => {\n const id: IRtTabs.Id | null = this.selectedId();\n if (id === null) {\n return;\n }\n if (wasActive && id !== closedId) {\n this.#internalId.set(id);\n this.activeIdChange.emit(id);\n }\n if (focus) {\n this.#focusTab(id);\n }\n },\n { injector: this.#injector }\n );\n }\n\n #updateRestVisibility(): void {\n const list: HTMLElement | undefined = this.tabListRef()?.nativeElement;\n\n if (!list || this.direction() !== 'horizontal') {\n this.restBeforeVisible.set(false);\n this.restAfterVisible.set(false);\n return;\n }\n\n const scrolledRight: number = list.scrollWidth - list.scrollLeft - list.clientWidth;\n\n this.restBeforeVisible.set(list.scrollLeft > 0);\n // 1px — погрешность субпиксельного scrollWidth\n this.restAfterVisible.set(scrolledRight > 1);\n }\n\n /** `again` — вкладки сменили размер: та же вкладка встаёт на место ещё раз. */\n #scrollToSelected(again: boolean = false): void {\n const id: IRtTabs.Id | null = this.selectedId();\n\n if (id !== null && (again || id !== this.#scrolledId)) {\n this.#follow.follow();\n this.#scrollTabIntoView(id);\n }\n }\n\n /**\n * Ставит вкладку в полосу целиком. Стрелки поверх полосы закрывают её края, поэтому вкладка\n * отступает от края на ширину стрелки. Первая прокрутка — сразу: открытая страница не едет.\n */\n #scrollTabIntoView(id: IRtTabs.Id): void {\n const list: HTMLElement | undefined = this.tabListRef()?.nativeElement;\n const tab: HTMLElement | null | undefined = list?.querySelector<HTMLElement>(`[data-tabitem=\"${id}\"]`);\n\n if (!list || !tab) {\n return;\n }\n\n const first: boolean = this.#scrolledId === null;\n const rest: HTMLElement | null | undefined = list.parentElement?.querySelector<HTMLElement>('.rt-tabs__rest');\n const inset: number = this.scrollArrows() === 'overlay' ? (rest?.offsetWidth ?? 0) : 0;\n const target: number | null = rtTabsIntoViewTarget(list, tab, inset);\n this.#scrolledId = id;\n\n if (target !== null && first) {\n this.#scroller.stop();\n list.scrollLeft = target;\n } else if (target !== null) {\n this.#scroller.to(target);\n } else {\n // вкладка целиком в зоне видимости — прокрутка не нужна\n }\n\n // Сразу — для прокрутки без движения; плавную ведут события прокрутки самой полосы.\n this.#updateRestVisibility();\n }\n\n #focusTab(id: IRtTabs.Id): void {\n const list: HTMLElement | undefined = this.tabListRef()?.nativeElement;\n // Без прокрутки фокусом: вкладку в видимую область ведёт плавная прокрутка полосы.\n list?.querySelector<HTMLElement>(`[data-tabid=\"${id}\"]`)?.focus({ preventScroll: true });\n }\n}\n","<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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-tabs.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tab.directive.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.motion.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.scroll.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.arrow-press.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.follow.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs-control.directive.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.component.ts","../../../projects/ui-kit-v2/src/lib/components/tabs/rt-tabs.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n computed,\n Directive,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n Signal,\n signal,\n TemplateRef,\n WritableSignal,\n} from '@angular/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { IRtTooltip } from '@rt-tools/ui-kit-v2/tooltip';\nimport { IRtTabs } from './rt-tabs.model';\n\n/**\n * Декларирует одну вкладку `<rt-tabs>`. Ставится на `<ng-template>`: контент\n * шаблона становится телом панели и рендерится только когда вкладка активна.\n *\n * Метаданные (label, icon, disabled, badge, invalid) — signal-inputs, поэтому\n * шапка вкладки реагирует на их изменение без ручной перерегистрации. Сам\n * список вкладок `rt-tabs` собирает через `contentChildren`.\n */\n@Directive({\n selector: '[rtTab]',\n})\nexport class RtTabDirective {\n readonly #t_uiTabInvalid: Signal<string> = rtKitLabel('uiTabInvalid');\n readonly #t_uiClose: Signal<string> = rtKitLabel('uiClose');\n\n /** Шаблон тела панели — рендерится в области контента при активной вкладке. */\n public readonly templateRef: TemplateRef<unknown> = inject<TemplateRef<unknown>>(TemplateRef);\n\n /** Стабильный идентификатор вкладки (значение атрибута `rtTab`). */\n public readonly id: InputSignal<IRtTabs.Id> = input<IRtTabs.Id>('', { alias: 'rtTab' });\n\n /** Текстовый заголовок. Игнорируется, если задан `titleTemplate`. */\n public readonly label: InputSignal<string> = input<string>('');\n\n /** Кастомный шаблон заголовка — замещает `label`. */\n public readonly titleTemplate: InputSignal<TemplateRef<unknown> | null> = input<TemplateRef<unknown> | null>(null);\n\n /** Иконка слева от заголовка. */\n public readonly icon: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /**\n * Имя значка Material вместо `icon` — рисуется так же, как вход `glyph` у `rt-icon`.\n * Задан вместе с `icon` — решает `rt-icon`.\n */\n public readonly glyph: InputSignal<string | null> = input<string | null>(null);\n\n /** Семантический цвет иконки заголовка. */\n public readonly iconColor: InputSignal<IRtTabs.TitleColor> = input<IRtTabs.TitleColor>('current');\n\n /** Значение бейджа справа от заголовка (число/строка). `null` — без бейджа. */\n public readonly badge: InputSignal<string | number | null> = input<string | number | null>(null);\n\n /**\n * Подсказка при наведении на бейдж. Подсказка самой кнопки занята неверной вкладкой,\n * поэтому у бейджа своя. Пусто — подсказки нет.\n */\n public readonly badgeTitle: InputSignal<string> = input<string>('');\n\n /**\n * Подпись бейджа для чтения с экрана: точка или число сами по себе не говорят, что значат.\n * Пусто — атрибут не ставится, и озвучивается значение бейджа как есть.\n */\n public readonly badgeAriaLabel: InputSignal<string> = input<string>('');\n\n /** Заблокированная вкладка: не выбирается и не получает фокус. */\n public readonly disabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Скрытая вкладка: не рендерится ни в шапке, ни в контенте. */\n public readonly hidden: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Вкладка с ошибками: подсвечивается danger-цветом. */\n public readonly invalid: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Подсказка для невалидной вкладки. Пусто — берётся переведённое умолчание. */\n public readonly invalidMessage: InputSignal<string> = input<string>('');\n\n /**\n * Подсказка при наведении на вкладку — в том числе на отключённую, чтобы объяснить, почему она\n * недоступна. У вкладки без подписи она же становится её именем для чтения с экрана.\n */\n public readonly tooltip: InputSignal<string> = input<string>('');\n\n /** Вкладку можно закрыть: крестик в шапке и клавиша Delete поднимают `tabClose` у `rt-tabs`. */\n public readonly closable: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Подсказка крестика закрываемой вкладки. Пусто — подсказки нет. */\n public readonly closeTooltip: InputSignal<string> = input<string>('');\n\n /** Сторона подсказки крестика. Не задана — сторона подсказки по умолчанию. */\n public readonly closeTooltipPlacement: InputSignal<IRtTooltip.Placement | null> = input<IRtTooltip.Placement | null>(null);\n\n /**\n * Указатель стоит на крестике. Выставляет `rt-tabs`: пока он там, подсказка самой вкладки\n * молчит, и видна только подсказка крестика.\n */\n public readonly closeHovered: WritableSignal<boolean> = signal<boolean>(false);\n\n /** Готовый текст подсказки: своя формулировка важнее умолчания. */\n public readonly invalidTitle: Signal<string> = computed((): string => this.invalidMessage() || this.#t_uiTabInvalid());\n\n /**\n * Подсказка кнопки вкладки: у неверной — объяснение ошибки, иначе своя подсказка. Пока\n * указатель на крестике, пусто: две подсказки разом читались бы как одна. Крестик, убранный\n * из-под указателя, ухода не сообщает, поэтому признак читается вместе с `showClose`.\n */\n public readonly buttonTooltip: Signal<string> = computed((): string => {\n if (this.closeHovered() && this.showClose()) {\n return '';\n }\n\n return this.invalid() ? this.invalidTitle() : this.tooltip();\n });\n\n /**\n * Имя вкладки для чтения с экрана, когда видимой подписи нет: вкладка из одного значка\n * называется своей подсказкой. С подписью или своим заголовком атрибут не ставится.\n */\n public readonly ariaLabel: Signal<string | null> = computed((): string | null =>\n this.label() || this.titleTemplate() ? null : this.tooltip() || null\n );\n\n /**\n * Имя крестика для чтения с экрана: текст его подсказки, без подсказки — переведённое «Закрыть».\n * Крестик — отдельная кнопка, и без имени диктор назвал бы её просто «кнопка».\n */\n public readonly closeLabel: Signal<string> = computed((): string => this.closeTooltip() || this.#t_uiClose());\n\n /** Крестик рисуется только у доступной вкладки: отключённую закрыть нельзя. */\n public readonly showClose: Signal<boolean> = computed((): boolean => this.closable() && !this.disabled());\n}\n","import {\n afterRenderEffect,\n computed,\n DestroyRef,\n ElementRef,\n inject,\n linkedSignal,\n Signal,\n signal,\n untracked,\n WritableSignal,\n} from '@angular/core';\n\nimport { RtTabDirective } from './rt-tab.directive';\nimport { IRtTabs } from './rt-tabs.model';\n\n/** Признак, по которому пользователь просит обходиться без движения. */\nexport const RT_TABS_REDUCED_MOTION: string = '(prefers-reduced-motion: reduce)';\n\n/** Куда сдвигается содержимое: к вкладке правее (`forward`) или левее (`backward`). */\nexport type TRtTabsPanelShift = 'forward' | 'backward';\n\n/** Панель прежней вкладки, пока её уход не кончился, и место, с которого она уходит (px от хоста). */\nexport interface IRtTabsLeavingPanel {\n readonly id: IRtTabs.Id;\n readonly shift: TRtTabsPanelShift;\n readonly top: number;\n readonly left: number;\n}\n\n/** Смена выбора: с какой вкладки, на какую и длительность из входа (`null` — из токена). */\nexport interface IRtTabsMove {\n readonly previous: IRtTabs.Id | null;\n readonly next: IRtTabs.Id | null;\n readonly duration: string | null;\n}\n\n/**\n * Панель в области содержимого: активная, уходящая (`leaving`) или сохранённая скрытой (`idle`) —\n * тело посещённой вкладки при `preserveContent`.\n */\nexport interface IRtTabsPanel {\n readonly tab: RtTabDirective;\n readonly leaving: IRtTabsLeavingPanel | null;\n readonly idle: boolean;\n}\n\n/** Что показывает область содержимого: активная вкладка, длительность и сохранение посещённых. */\nexport interface IRtTabsShown {\n readonly active: Signal<RtTabDirective | null>;\n readonly duration: () => IRtTabs.AnimationDuration;\n readonly preserve: () => boolean;\n}\n\n/** Вкладки компонента: все объявленные, видимые и выбранная. */\nexport interface IRtTabsSet {\n readonly all: Signal<readonly RtTabDirective[]>;\n readonly visible: Signal<readonly RtTabDirective[]>;\n readonly selectedId: Signal<IRtTabs.Id | null>;\n}\n\n/** Место полосы выбранной вкладки внутри полосы вкладок: левый край, низ вкладки и ширина (px). */\ninterface IInkBox {\n readonly x: number;\n readonly bottom: number;\n readonly width: number;\n}\n\n/** Длительность из входа в значение CSS: число и строка из одних цифр — миллисекунды. */\nexport function rtTabsCssDuration(value: IRtTabs.AnimationDuration): string | null {\n const text: string = value === null ? '' : String(value).trim();\n\n if (!text) {\n return null;\n }\n\n return /^\\d+(\\.\\d+)?$/.test(text) ? `${text}ms` : text;\n}\n\n/** Длительность CSS в миллисекундах; то, что не читается как время, — ноль. */\nexport function rtTabsDurationMs(value: string): number {\n const text: string = value.trim();\n const amount: number = parseFloat(text);\n\n if (Number.isNaN(amount)) {\n return 0;\n }\n\n if (text.endsWith('ms')) {\n return amount;\n }\n\n return text.endsWith('s') ? amount * 1000 : amount;\n}\n\n/** Набор посещённых вкладок с вкладкой `id`: тот же набор, если она в нём уже есть. */\nfunction withVisited(visited: ReadonlySet<IRtTabs.Id>, id: IRtTabs.Id | null): ReadonlySet<IRtTabs.Id> {\n return id === null || visited.has(id) ? visited : new Set([...visited, id]);\n}\n\nfunction sameInkBox(a: IInkBox | null, b: IInkBox | null): boolean {\n if (a === null || b === null) {\n return a === b;\n }\n\n return a.x === b.x && a.bottom === b.bottom && a.width === b.width;\n}\n\n/**\n * Уходящая панель при смене выбора. Место берётся у панели прежней вкладки, пока она ещё в потоке:\n * уходя, она встаёт поверх области содержимого в ту же точку. Без движения — нулевая длительность\n * или `prefers-reduced-motion` — уходящей панели нет.\n */\nexport function rtTabsLeavingPanel(\n host: HTMLElement,\n win: Window | null,\n ids: readonly IRtTabs.Id[],\n move: IRtTabsMove\n): IRtTabsLeavingPanel | null {\n const { previous, next } = move;\n\n if (previous === null || next === null || previous === next || !win) {\n return null;\n }\n\n if (win.matchMedia?.(RT_TABS_REDUCED_MOTION).matches) {\n return null;\n }\n\n const duration: string = move.duration ?? win.getComputedStyle(host).getPropertyValue('--rt-tabs-panel-duration');\n const panel: HTMLElement | undefined = Array.from(host.querySelectorAll<HTMLElement>(':scope > .rt-tabs__content')).find(\n (node: HTMLElement): boolean => node.id === `rt-tabpanel-${previous}`\n );\n\n if (!panel || rtTabsDurationMs(duration) <= 0) {\n return null;\n }\n\n const hostBox: DOMRect = host.getBoundingClientRect();\n const panelBox: DOMRect = panel.getBoundingClientRect();\n\n return {\n id: previous,\n shift: ids.indexOf(next) > ids.indexOf(previous) ? 'forward' : 'backward',\n top: panelBox.top - hostBox.top - host.clientTop,\n left: panelBox.left - hostBox.left - host.clientLeft,\n };\n}\n\n/**\n * Панели при сохранении посещённых: тело вкладки появляется при первом открытии и дальше живёт\n * скрытым. Порядок — порядок вкладок, чтобы вид панели не переставлялся в разметке при смене.\n */\nexport function rtTabsPreservedPanels(\n all: readonly RtTabDirective[],\n visited: ReadonlySet<IRtTabs.Id>,\n active: RtTabDirective,\n leaving: IRtTabsLeavingPanel | null\n): IRtTabsPanel[] {\n return all\n .filter((tab: RtTabDirective): boolean => tab === active || visited.has(tab.id()))\n .map((tab: RtTabDirective): IRtTabsPanel => {\n if (tab === active) {\n return { leaving: null, idle: false, tab };\n }\n\n const isLeaving: boolean = leaving !== null && leaving.id === tab.id();\n\n return { leaving: isLeaving ? leaving : null, idle: !isLeaving, tab };\n });\n}\n\n/**\n * Смена панелей: уходящая панель прежней вкладки и въезжающая новая. Уходящая считается от смены\n * выбора и гасится концом её движения. Создаётся в контексте внедрения компонента.\n */\nexport class RtTabsPanels {\n /** Панель прежней вкладки, пока она уходит; без движения её нет вовсе. */\n public readonly leaving: WritableSignal<IRtTabsLeavingPanel | null>;\n\n /**\n * Панели области содержимого: активная и, пока она уходит, прежняя. Прежняя стоит первой, и\n * `track` по id сохраняет её вид — уходит та же панель, а не её новая копия. При сохранении\n * посещённых панели стоят в порядке вкладок, и неактивные остаются скрытыми.\n */\n public readonly list: Signal<readonly IRtTabsPanel[]>;\n\n /** Вкладки, которые открывались хоть раз: их тела живут при `preserveContent`. */\n readonly #visited: Signal<ReadonlySet<IRtTabs.Id>>;\n\n /** Направление идущей смены панели; `null` — панель стоит на месте. */\n public readonly shift: Signal<TRtTabsPanelShift | null>;\n\n /** Длительность из входа `animationDuration` в виде CSS; `null` — длительности из токенов. */\n public readonly duration: Signal<string | null>;\n\n /** Длительности полосы и панели на хосте из входа; без входа их держат токены. Прокрутку полосы\n * вход не трогает, как у `mat-tab-group`: её длительность — только токен. */\n public readonly durations: Signal<Readonly<Record<string, string>> | null>;\n\n constructor(host: HTMLElement, win: Window | null, tabs: IRtTabsSet, shown: IRtTabsShown) {\n this.duration = computed((): string | null => rtTabsCssDuration(shown.duration()));\n this.durations = computed((): Readonly<Record<string, string>> | null => {\n const duration: string | null = this.duration();\n\n return duration === null\n ? null\n : {\n '--rt-tabs-indicator-duration': duration,\n '--rt-tabs-panel-duration': duration,\n };\n });\n const ids: () => IRtTabs.Id[] = (): IRtTabs.Id[] => tabs.visible().map((tab: RtTabDirective): IRtTabs.Id => tab.id());\n\n this.leaving = linkedSignal<IRtTabs.Id | null, IRtTabsLeavingPanel | null>({\n source: tabs.selectedId,\n computation: (id: IRtTabs.Id | null, previous: { source: IRtTabs.Id | null } | undefined): IRtTabsLeavingPanel | null =>\n untracked((): IRtTabsLeavingPanel | null =>\n rtTabsLeavingPanel(host, win, ids(), { previous: previous?.source ?? null, next: id, duration: this.duration() })\n ),\n });\n\n this.#visited = linkedSignal<IRtTabs.Id | null, ReadonlySet<IRtTabs.Id>>({\n source: tabs.selectedId,\n computation: (id: IRtTabs.Id | null, previous: { value: ReadonlySet<IRtTabs.Id> } | undefined): ReadonlySet<IRtTabs.Id> =>\n withVisited(previous?.value ?? new Set(), id),\n });\n\n this.list = computed((): readonly IRtTabsPanel[] => {\n const active: RtTabDirective | null = shown.active();\n const leaving: IRtTabsLeavingPanel | null = this.leaving();\n\n if (!active) {\n return [];\n }\n\n if (shown.preserve()) {\n return rtTabsPreservedPanels(tabs.all(), this.#visited(), active, leaving);\n }\n\n const current: IRtTabsPanel = { tab: active, leaving: null, idle: false };\n const leavingTab: RtTabDirective | undefined =\n leaving === null || leaving.id === active.id()\n ? undefined\n : tabs.visible().find((tab: RtTabDirective): boolean => tab.id() === leaving.id);\n\n return leaving && leavingTab ? [{ leaving, idle: false, tab: leavingTab }, current] : [current];\n });\n\n this.shift = computed((): TRtTabsPanelShift | null =>\n this.list().some((panel: IRtTabsPanel): boolean => panel.leaving !== null) ? (this.leaving()?.shift ?? null) : null\n );\n }\n\n /** Конец движения панели убирает уходящую. Движение вложенных узлов сюда не считается. */\n public animationEnd(event: AnimationEvent): void {\n if (event.target === event.currentTarget) {\n this.leaving.set(null);\n }\n }\n}\n\n/**\n * Полоса выбранной вкладки — один элемент на всю полосу: замер ставит её под выбранную вкладку, и\n * при смене выбора она переезжает. Слежение за размером полосы и вкладок ловит сдвиг без смены\n * выбора — подпись поменялась или шрифт догрузился.\n */\nexport class RtTabsInk {\n readonly #win: Window | null;\n\n readonly #list: Signal<ElementRef<HTMLElement> | undefined>;\n\n readonly #active: Signal<RtTabDirective | null>;\n\n #watch: ResizeObserver | null = null;\n\n /** Где стоит полоса; `null` — не измерена, и полосу рисует сама вкладка. */\n public readonly box: WritableSignal<IInkBox | null> = signal<IInkBox | null>(null, { equal: sameInkBox });\n\n /** Полоса уже стоит на месте и дальше переезжает: первое измерение ставит её без движения. */\n public readonly animated: WritableSignal<boolean> = signal(false);\n\n /** Сдвиг полосы к левому краю вкладки и к её низу. */\n public readonly translate: Signal<string | null> = computed((): string | null => {\n const box: IInkBox | null = this.box();\n\n return box ? `${box.x}px ${box.bottom}px` : null;\n });\n\n /** Полоса красится как ошибка, когда выбранная вкладка неверна. */\n public readonly invalid: Signal<boolean> = computed((): boolean => this.#active()?.invalid() ?? false);\n\n constructor(\n win: Window | null,\n list: Signal<ElementRef<HTMLElement> | undefined>,\n tabs: { readonly visible: Signal<readonly RtTabDirective[]>; readonly active: Signal<RtTabDirective | null> }\n ) {\n this.#win = win;\n this.#list = list;\n this.#active = tabs.active;\n\n // Новая вкладка в полосе — новый узел под слежение, новый выбор — новое место полосы.\n afterRenderEffect((): void => {\n tabs.visible();\n this.#active();\n this.#watchSizes();\n this.#place();\n });\n\n inject(DestroyRef).onDestroy((): void => this.#watch?.disconnect());\n }\n\n /** Перевешивает слежение за размером на вкладки, что сейчас стоят в полосе. */\n #watchSizes(): void {\n const list: HTMLElement | undefined = this.#list()?.nativeElement;\n\n if (!list || typeof ResizeObserver === 'undefined') {\n return;\n }\n\n if (!this.#watch) {\n this.#watch = new ResizeObserver((): void => this.#place());\n }\n\n const watch: ResizeObserver = this.#watch;\n watch.disconnect();\n watch.observe(list);\n list.querySelectorAll<HTMLElement>('[data-tabitem]').forEach((node: HTMLElement): void => watch.observe(node));\n }\n\n /** Ставит полосу под выбранную вкладку. Дробные размеры сохраняются: полоса ложится ровно по вкладке. */\n #place(): void {\n const list: HTMLElement | undefined = this.#list()?.nativeElement;\n const id: IRtTabs.Id | undefined = this.#active()?.id();\n const tab: HTMLElement | null | undefined = id === undefined ? null : list?.querySelector<HTMLElement>(`[data-tabitem=\"${id}\"]`);\n\n if (!list || !tab) {\n this.box.set(null);\n return;\n }\n\n const listBox: DOMRect = list.getBoundingClientRect();\n const tabBox: DOMRect = tab.getBoundingClientRect();\n\n this.box.set({\n x: tabBox.left - listBox.left - list.clientLeft + list.scrollLeft,\n bottom: tabBox.bottom - listBox.top - list.clientTop + list.scrollTop,\n width: tabBox.width,\n });\n\n if (!untracked(this.animated)) {\n this.#win?.requestAnimationFrame((): void => this.animated.set(true));\n }\n }\n}\n","import { ElementRef } from '@angular/core';\n\nimport { IRtTabs } from './rt-tabs.model';\nimport { RT_TABS_REDUCED_MOTION, rtTabsDurationMs } from './rt-tabs.motion';\n\n/** Кривая, которой читается непонятное значение. */\nconst EASE_OUT: readonly [number, number, number, number] = [0, 0, 0.58, 1];\n\n/** Именованные кривые CSS в виде опорных точек `cubic-bezier`. */\nconst NAMED_EASINGS: ReadonlyMap<string, readonly [number, number, number, number]> = new Map<\n string,\n readonly [number, number, number, number]\n>([\n ['linear', [0, 0, 1, 1]],\n ['ease', [0.25, 0.1, 0.25, 1]],\n ['ease-in', [0.42, 0, 1, 1]],\n ['ease-out', EASE_OUT],\n ['ease-in-out', [0.42, 0, 0.58, 1]],\n]);\n\n/** Шаг прокрутки полосы за один тик удержания стрелки (px). */\nconst HOLD_STEP: number = 12;\n\n/** Сдвиг одного нажатия на стрелку при шаге `fixed` (px): столько давал короткий клик до шага на страницу. */\nconst FIXED_STEP: number = 80;\n\n/** Доля видимой ширины полосы, на которую сдвигает одно нажатие на стрелку при шагах `page` и `third`. */\nconst STEP_SHARE: Readonly<Record<Exclude<IRtTabs.ScrollStep, 'fixed'>, number>> = { page: 1, third: 1 / 3 };\n\n/** Точка кубической кривой Безье с концами 0 и 1 по одной оси. */\nfunction bezierAt(t: number, p1: number, p2: number): number {\n const u: number = 1 - t;\n\n return 3 * u * u * t * p1 + 3 * u * t * t * p2 + t * t * t;\n}\n\n/**\n * Кривая CSS как функция доли времени в долю пути: `linear`, `ease`, `ease-in`, `ease-out`,\n * `ease-in-out` и `cubic-bezier(…)`. Непонятное значение читается как `ease-out`.\n */\nexport function rtTabsEasing(value: string): (progress: number) => number {\n const text: string = value.trim();\n const match: RegExpMatchArray | null = /^cubic-bezier\\(([^)]*)\\)$/.exec(text);\n const parsed: number[] = match ? match[1].split(',').map((part: string): number => parseFloat(part)) : [];\n const valid: boolean = parsed.length === 4 && parsed.every((point: number): boolean => Number.isFinite(point));\n const points: readonly number[] = valid ? parsed : (NAMED_EASINGS.get(text) ?? EASE_OUT);\n const [x1, y1, x2, y2]: readonly number[] = points;\n\n return (progress: number): number => {\n if (progress <= 0 || progress >= 1) {\n return Math.min(1, Math.max(0, progress));\n }\n\n // Доля времени — координата x на кривой: её параметр ищется делением отрезка пополам.\n let low: number = 0;\n let high: number = 1;\n for (let step: number = 0; step < 30; step++) {\n const mid: number = (low + high) / 2;\n if (bezierAt(mid, x1, x2) < progress) {\n low = mid;\n } else {\n high = mid;\n }\n }\n\n return bezierAt((low + high) / 2, y1, y2);\n };\n}\n\n/** Куда прокрутить полосу нажатием на стрелку: на шаг `step` от `from`, не дальше края. */\nexport function rtTabsPageTarget(list: HTMLElement, from: number, back: boolean, step: IRtTabs.ScrollStep): number {\n const max: number = Math.max(0, list.scrollWidth - list.clientWidth);\n const shift: number = step === 'fixed' ? FIXED_STEP : list.clientWidth * STEP_SHARE[step];\n\n return Math.min(max, Math.max(0, from + (back ? -shift : shift)));\n}\n\n/**\n * Куда прокрутить полосу, чтобы вкладка встала целиком; `null` — она уже видна целиком. `inset` —\n * ширина стрелки поверх края полосы: вкладка не у конца полосы отступает от края на неё, иначе\n * встала бы под стрелку.\n */\nexport function rtTabsIntoViewTarget(list: HTMLElement, tab: HTMLElement, inset: number = 0): number | null {\n const left: number = tab.offsetLeft;\n const right: number = left + tab.offsetWidth;\n const before: number = left > 0 ? inset : 0;\n // 1px — погрешность субпиксельного scrollWidth\n const after: number = list.scrollWidth - right > 1 ? inset : 0;\n\n if (left - before < list.scrollLeft) {\n return Math.max(left - before, 0);\n }\n\n if (right + after > list.scrollLeft + list.clientWidth) {\n return right + after - list.clientWidth;\n }\n\n return null;\n}\n\n/**\n * Плавная прокрутка полосы вкладок. Двигается сама прокрутка, а не сдвиг содержимого: колесо,\n * касание и полоса прокрутки остаются у браузера. Длительность и кривая — свойства хоста\n * `--rt-tabs-scroll-duration` и `--rt-tabs-scroll-easing`; ноль или `prefers-reduced-motion` —\n * прокрутка сразу.\n */\nexport class RtTabsScroller {\n readonly #win: Window | null;\n\n readonly #host: HTMLElement;\n\n readonly #list: () => ElementRef<HTMLElement> | undefined;\n\n #frame: number | null = null;\n\n /** Куда едет идущая прокрутка: следующий шаг считается от неё, а не от середины пути. */\n #target: number | null = null;\n\n constructor(win: Window | null, host: HTMLElement, list: () => ElementRef<HTMLElement> | undefined) {\n this.#win = win;\n this.#host = host;\n this.#list = list;\n }\n\n /** Положение, от которого считать следующий шаг: цель идущей прокрутки или текущее. */\n public from(): number {\n return this.#target ?? this.#list()?.nativeElement.scrollLeft ?? 0;\n }\n\n /** Прокручивает полосу к `left`; новая прокрутка заменяет идущую. */\n public to(left: number): void {\n const list: HTMLElement | undefined = this.#list()?.nativeElement;\n const win: Window | null = this.#win;\n this.stop();\n\n if (!list || !win) {\n return;\n }\n\n const style: CSSStyleDeclaration = win.getComputedStyle(this.#host);\n const duration: number = win.matchMedia?.(RT_TABS_REDUCED_MOTION).matches\n ? 0\n : rtTabsDurationMs(style.getPropertyValue('--rt-tabs-scroll-duration'));\n const start: number = list.scrollLeft;\n\n if (duration <= 0 || start === left) {\n list.scrollLeft = left;\n return;\n }\n\n const ease: (progress: number) => number = rtTabsEasing(style.getPropertyValue('--rt-tabs-scroll-easing'));\n const startedAt: number = win.performance.now();\n this.#target = left;\n\n const tick: (now: number) => void = (now: number): void => {\n const progress: number = Math.min(1, (now - startedAt) / duration);\n list.scrollLeft = start + (left - start) * ease(progress);\n this.#frame = progress < 1 ? win.requestAnimationFrame(tick) : null;\n if (this.#frame === null) {\n this.#target = null;\n }\n };\n this.#frame = win.requestAnimationFrame(tick);\n }\n\n /**\n * Тик прокрутки удержанием стрелки: сдвиг на несколько точек без плавности, остановив идущую.\n * Отвечает, осталось ли куда ехать.\n */\n public nudge(back: boolean): boolean {\n this.stop();\n const list: HTMLElement | undefined = this.#list()?.nativeElement;\n\n if (!list) {\n return false;\n }\n\n const remaining: number = back ? list.scrollLeft : list.scrollWidth - list.scrollLeft - list.clientWidth;\n\n if (remaining > 0) {\n list.scrollLeft += (back ? -1 : 1) * Math.min(HOLD_STEP, remaining);\n }\n\n return remaining - HOLD_STEP > 0;\n }\n\n /** Останавливает идущую прокрутку там, где она есть. */\n public stop(): void {\n if (this.#frame !== null) {\n this.#win?.cancelAnimationFrame(this.#frame);\n }\n this.#frame = null;\n this.#target = null;\n }\n}\n","import { IRtTabs } from './rt-tabs.model';\nimport { rtTabsPageTarget, RtTabsScroller } from './rt-tabs.scroll';\n\n/** Интервал тика прокрутки при зажатой стрелке (мс). */\nconst SCROLL_TICK_MS: number = 15;\n\n/** Сколько держать стрелку, чтобы нажатие стало прокруткой по удержанию, а не шагом (мс). */\nconst HOLD_DELAY_MS: number = 300;\n\nexport type TRtTabsScrollDirection = 'before' | 'after';\n\n/**\n * Нажатие на стрелку прокрутки полосы. Отпущенная до `HOLD_DELAY_MS` стрелка сдвигает полосу на\n * шаг `scrollStep`, удержанная дольше — прокручивает её непрерывно, пока не отпустят.\n */\nexport class RtTabsArrowPress {\n readonly #win: Window | null;\n\n readonly #scroller: RtTabsScroller;\n\n readonly #list: () => HTMLElement | undefined;\n\n readonly #step: () => IRtTabs.ScrollStep;\n\n /** Полоса сдвинулась: видимость стрелок пересчитывается. */\n readonly #moved: () => void;\n\n /** Хэндл интервала прокрутки по удержанию стрелки. */\n #scrollIntervalId: number | null = null;\n\n /** Хэндл ожидания, после которого нажатие на стрелку становится удержанием. */\n #holdTimeoutId: number | null = null;\n\n /** Стрелка, нажатая и ещё не отпущенная. */\n #pressed: TRtTabsScrollDirection | null = null;\n\n constructor(\n win: Window | null,\n scroller: RtTabsScroller,\n list: () => HTMLElement | undefined,\n step: () => IRtTabs.ScrollStep,\n moved: () => void\n ) {\n this.#win = win;\n this.#scroller = scroller;\n this.#list = list;\n this.#step = step;\n this.#moved = moved;\n }\n\n /** Стрелку нажали: через `HOLD_DELAY_MS` нажатие становится удержанием. */\n public down(direction: TRtTabsScrollDirection): void {\n if (this.#pressed !== null || !this.#win) {\n return;\n }\n\n this.#pressed = direction;\n this.#holdTimeoutId = this.#win.setTimeout((): void => {\n this.#holdTimeoutId = null;\n this.#scrollIntervalId =\n this.#win?.setInterval((): void => {\n if (!this.#scroller.nudge(direction === 'before')) {\n this.stop();\n }\n this.#moved();\n }, SCROLL_TICK_MS) ?? null;\n }, HOLD_DELAY_MS);\n }\n\n /** Стрелку отпустили: короткое нажатие — шаг `scrollStep`, после удержания — только стоп. */\n public up(): void {\n const direction: TRtTabsScrollDirection | null = this.#pressed;\n const shortPress: boolean = this.#holdTimeoutId !== null;\n const list: HTMLElement | undefined = this.#list();\n\n this.stop();\n\n if (direction !== null && shortPress && list) {\n this.#scroller.to(rtTabsPageTarget(list, this.#scroller.from(), direction === 'before', this.#step()));\n // Сразу — для прокрутки без движения; плавную ведут события прокрутки самой полосы.\n this.#moved();\n }\n }\n\n /** Снимает ожидание и интервал: указатель ушёл со стрелки или компонент разрушен с зажатой. */\n public stop(): void {\n this.#pressed = null;\n if (this.#win && this.#holdTimeoutId !== null) {\n this.#win.clearTimeout(this.#holdTimeoutId);\n this.#holdTimeoutId = null;\n }\n if (this.#win && this.#scrollIntervalId !== null) {\n this.#win.clearInterval(this.#scrollIntervalId);\n this.#scrollIntervalId = null;\n }\n }\n}\n","/**\n * Следит за размерами вкладок полосы. Вкладки стали шире или уже — например, у них появились\n * счётчики после загрузки данных — и полоса снова встаёт к выбранной вкладке. Человек сам прокрутил\n * полосу колесом, касанием или стрелкой — полоса больше не следит, пока не выберут вкладку.\n */\nexport class RtTabsFollow {\n /** Размеры вкладок изменились, а человек полосу не трогал. */\n readonly #resized: () => void;\n\n #observer: ResizeObserver | null = null;\n\n #list: HTMLElement | null = null;\n\n /** Полосу прокрутили рукой: смена размеров её больше не двигает. */\n #manual: boolean = false;\n\n readonly #onManual: () => void = (): void => this.manual();\n\n constructor(resized: () => void) {\n this.#resized = resized;\n }\n\n /** Наблюдает полосу и все её `count` вкладок заново: зовётся, когда сменился набор вкладок. */\n public watch(list: HTMLElement | undefined, count: number): void {\n // Окно без наблюдателя — серверная отрисовка и старые движки: полоса просто не следит.\n if (typeof ResizeObserver === 'undefined' || !list || !count) {\n return;\n }\n\n if (this.#list !== list) {\n this.#unlisten();\n list.addEventListener('wheel', this.#onManual, { passive: true });\n list.addEventListener('touchstart', this.#onManual, { passive: true });\n this.#list = list;\n }\n\n this.#observer ??= new ResizeObserver((): void => {\n if (!this.#manual) {\n this.#resized();\n }\n });\n const observer: ResizeObserver = this.#observer;\n observer.disconnect();\n observer.observe(list);\n list.querySelectorAll<HTMLElement>('[data-tabitem]').forEach((item: HTMLElement): void => observer.observe(item));\n }\n\n public manual(): void {\n this.#manual = true;\n }\n\n /** Выбрали вкладку: полоса снова следит за ней. */\n public follow(): void {\n this.#manual = false;\n }\n\n public stop(): void {\n this.#observer?.disconnect();\n this.#unlisten();\n }\n\n #unlisten(): void {\n this.#list?.removeEventListener('wheel', this.#onManual);\n this.#list?.removeEventListener('touchstart', this.#onManual);\n this.#list = null;\n }\n}\n","import { Directive, inject, input, InputSignalWithTransform, TemplateRef } from '@angular/core';\n\nimport { IRtTabs } from './rt-tabs.model';\n\n/**\n * Декларирует header-контрол `<rt-tabs>` — произвольный шаблон (кнопка, фильтр),\n * который рендерится слева или справа от полосы вкладок. Ставится на\n * `<ng-template>`; `rt-tabs` собирает контролы через `contentChildren` и\n * раскладывает по сторонам согласно `side`.\n */\n@Directive({\n selector: '[rtTabsControl]',\n})\nexport class RtTabsControlDirective {\n /** Шаблон контрола, выводимый в header-слоте. */\n public readonly templateRef: TemplateRef<unknown> = inject<TemplateRef<unknown>>(TemplateRef);\n\n /**\n * Сторона размещения относительно полосы вкладок.\n *\n * Пустое значение приводится к правой стороне: `<ng-template rtTabsControl>` без значения\n * задаёт входу пустую строку, а не умолчание, и такой контрол не попадал ни в левый слот,\n * ни в правый — он пропадал из шапки вовсе.\n */\n public readonly side: InputSignalWithTransform<IRtTabs.ControlSide, IRtTabs.ControlSide | ''> = input<\n IRtTabs.ControlSide,\n IRtTabs.ControlSide | ''\n >('right', {\n alias: 'rtTabsControl',\n transform: (value: IRtTabs.ControlSide | ''): IRtTabs.ControlSide => (value === '' ? 'right' : value),\n });\n}\n","import { BooleanInput } from '@angular/cdk/coercion';\nimport { DOCUMENT, NgTemplateOutlet } from '@angular/common';\nimport {\n afterNextRender,\n afterRenderEffect,\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChildren,\n DestroyRef,\n ElementRef,\n inject,\n Injector,\n input,\n InputSignal,\n InputSignalWithTransform,\n output,\n OutputEmitterRef,\n Signal,\n signal,\n viewChild,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nimport { debounceTime, fromEvent } from 'rxjs';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\nimport { RtTabDirective } from './rt-tab.directive';\nimport { RtTabsArrowPress, TRtTabsScrollDirection } from './rt-tabs.arrow-press';\nimport { RtTabsFollow } from './rt-tabs.follow';\nimport { RtTabsControlDirective } from './rt-tabs-control.directive';\nimport { IRtTabs } from './rt-tabs.model';\nimport { RtTabsInk, RtTabsPanels } from './rt-tabs.motion';\nimport { rtTabsIntoViewTarget, RtTabsScroller } from './rt-tabs.scroll';\n\n/** Дебаунс пересчёта видимости стрелок прокрутки на resize/scroll (мс). */\nconst REST_DEBOUNCE_MS: number = 50;\n\nconst BEM_BLOCK: string = 'rt-tabs';\n\n/**\n * Полоса вкладок с проекцией контента. Вкладки декларируются через\n * `<ng-template rtTab=\"id\" label=\"…\">…</ng-template>` (см. {@link RtTabDirective}),\n * собираются `contentChildren` и рендерятся как header-кнопки + активная панель.\n * Опциональные header-контролы — через `[rtTabsControl]`.\n *\n * Компонент \"controlled-ish\": активная вкладка берётся из `activeId` (если\n * задан), иначе — из внутреннего выбора, иначе — первая доступная. Клик/клавиша\n * эмиттят `activeIdChange`; синхронизацию `activeId` оставляем потребителю.\n *\n * Горизонтальная полоса при переполнении прячет вкладки под скролл и показывает\n * стрелки-«хвосты» (`__rest`): нажатие сдвигает полосу на шаг `scrollStep`, удержание\n * прокручивает непрерывно. Стрелки стоят поверх вкладок или, при `scrollArrows=\"inline\"`, в своих\n * местах по краям. Вертикальная ориентация раскладывает вкладки в колонку без стрелок.\n *\n * Смена вкладки движется: полоса выбранной вкладки — один элемент полосы, он переезжает на новую\n * вкладку; панель прежней вкладки уходит в сторону, обратную переходу, новая въезжает следом.\n * Длительности — токены `--rt-tabs-indicator-duration` и `--rt-tabs-panel-duration` или вход\n * `animationDuration`; `prefers-reduced-motion` снимает движение целиком.\n *\n * Доступность: `role=\"tablist\"`/`role=\"tab\"`/`role=\"tabpanel\"`, `aria-selected`,\n * roving `tabindex`, навигация стрелками + Home/End; при `activation=\"manual\"` они только\n * переводят фокус, а вкладку открывают Enter и Space.\n */\n@Component({\n selector: 'rt-tabs',\n templateUrl: './rt-tabs.component.html',\n styleUrl: './rt-tabs.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // angular\n NgTemplateOutlet,\n\n // standalone components / directives\n RtIconComponent,\n RtTooltipDirective,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n host: {\n class: BEM_BLOCK,\n '[class.rt-tabs--direction--horizontal]': \"direction() === 'horizontal'\",\n '[class.rt-tabs--direction--vertical]': \"direction() === 'vertical'\",\n '[class.rt-tabs--animating]': 'panels.shift() !== null',\n '[style]': 'panels.durations()',\n },\n})\nexport class RtTabsComponent {\n /** `Window` через `DOCUMENT` (SSR-safe: `defaultView` может быть `null`). */\n readonly #win: Window | null = inject(DOCUMENT).defaultView;\n\n readonly #host: HTMLElement = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n /** Все задекларированные вкладки (включая скрытые). */\n protected readonly tabs: Signal<readonly RtTabDirective[]> = contentChildren(RtTabDirective);\n\n /** Все header-контролы. */\n protected readonly controls: Signal<readonly RtTabsControlDirective[]> = contentChildren(RtTabsControlDirective);\n\n /** Видимые вкладки (без `hidden`). */\n protected readonly visibleTabs: Signal<readonly RtTabDirective[]> = computed((): readonly RtTabDirective[] =>\n this.tabs().filter((tab: RtTabDirective): boolean => !tab.hidden())\n );\n\n protected readonly leftControls: Signal<readonly RtTabsControlDirective[]> = computed((): readonly RtTabsControlDirective[] =>\n this.controls().filter((c: RtTabsControlDirective): boolean => c.side() === 'left')\n );\n\n protected readonly rightControls: Signal<readonly RtTabsControlDirective[]> = computed((): readonly RtTabsControlDirective[] =>\n this.controls().filter((c: RtTabsControlDirective): boolean => c.side() === 'right')\n );\n\n /**\n * Эффективный id активной вкладки. Приоритет: контролируемый `activeId` →\n * внутренний выбор → первая доступная. Кандидат валидируется по множеству\n * видимых незаблокированных вкладок, поэтому корректно реагирует на\n * асинхронную загрузку/смену набора вкладок.\n */\n protected readonly selectedId: Signal<IRtTabs.Id | null> = computed((): IRtTabs.Id | null => {\n const enabled: readonly RtTabDirective[] = this.visibleTabs().filter((tab: RtTabDirective): boolean => !tab.disabled());\n const candidate: IRtTabs.Id | null = this.activeId() ?? this.#internalId();\n const candidateValid: boolean = candidate !== null && enabled.some((tab: RtTabDirective): boolean => tab.id() === candidate);\n\n let result: IRtTabs.Id | null;\n if (candidateValid) {\n result = candidate;\n } else if (enabled.length) {\n result = enabled[0].id();\n } else {\n result = null;\n }\n\n return result;\n });\n\n /** Активная вкладка целиком (для рендера панели). */\n protected readonly activeTab: Signal<RtTabDirective | null> = computed(\n (): RtTabDirective | null => this.visibleTabs().find((tab: RtTabDirective): boolean => tab.id() === this.selectedId()) ?? null\n );\n\n /**\n * Вкладка в таб-порядке: та, на которую стрелками перевели фокус в ручном режиме, иначе\n * активная. Фокус на вкладке, которой больше нет или которая отключилась, не держится.\n */\n protected readonly focusId: Signal<IRtTabs.Id | null> = computed((): IRtTabs.Id | null => {\n const focused: IRtTabs.Id | null = this.#focusedId();\n const valid: boolean =\n focused !== null && this.visibleTabs().some((tab: RtTabDirective): boolean => tab.id() === focused && !tab.disabled());\n\n return valid ? focused : this.selectedId();\n });\n\n /** Видны ли стрелки прокрутки слева/справа (только горизонтальная полоса). */\n protected readonly restBeforeVisible: WritableSignal<boolean> = signal(false);\n protected readonly restAfterVisible: WritableSignal<boolean> = signal(false);\n\n /** Полоса шире своего места: в раскладке `inline` по этому признаку встают обе стрелки. */\n protected readonly overflowing: Signal<boolean> = computed((): boolean => this.restBeforeVisible() || this.restAfterVisible());\n\n protected readonly tabListRef: Signal<ElementRef<HTMLElement> | undefined> = viewChild<ElementRef<HTMLElement>>('tabList');\n\n /** Смена панелей: прежняя уходит в сторону, обратную переходу, новая въезжает следом. */\n protected readonly panels: RtTabsPanels = new RtTabsPanels(\n this.#host,\n this.#win,\n { all: this.tabs, visible: this.visibleTabs, selectedId: this.selectedId },\n {\n active: computed((): RtTabDirective | null => (this.headerOnly() ? null : this.activeTab())),\n // Входы объявлены ниже: на этой строке их ещё нет, и они читаются при каждом обращении.\n duration: (): IRtTabs.AnimationDuration => this.animationDuration(),\n preserve: (): boolean => this.preserveContent(),\n }\n );\n\n /** Полоса выбранной вкладки: одна на всю полосу, переезжает при смене выбора. */\n protected readonly ink: RtTabsInk = new RtTabsInk(this.#win, this.tabListRef, { visible: this.visibleTabs, active: this.activeTab });\n\n /** Контролируемый активный id. `null` — компонент сам выбирает первую вкладку. */\n public readonly activeId: InputSignal<IRtTabs.Id | null> = input<IRtTabs.Id | null>(null);\n\n /** Ориентация полосы. */\n public readonly direction: InputSignal<IRtTabs.Direction> = input<IRtTabs.Direction>('horizontal');\n\n /** Растягивать вкладки на всю ширину полосы. */\n public readonly stretch: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Скроллить область контента при переполнении. */\n public readonly contentScrollable: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(true, {\n transform: booleanAttribute,\n });\n\n /**\n * Только полоса, без панели: вкладки служат навигацией, а содержимое живёт в другом месте —\n * например, полоса стоит в середине `rt-toolbar`. Панель `role=\"tabpanel\"` не рисуется, и\n * вкладки не ссылаются на неё.\n */\n public readonly headerOnly: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Тело вкладки создаётся при первом открытии и дальше живёт скрытым, как у `mat-tab-group` с\n * `preserveContent`: введённое на вкладке переживает уход с неё. Неоткрытая вкладка не создаётся.\n */\n public readonly preserveContent: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Стрелки и Home/End открывают вкладку сразу (`auto`) или только переводят фокус (`manual`). */\n public readonly activation: InputSignal<IRtTabs.Activation> = input<IRtTabs.Activation>('auto');\n\n /** Стрелки прокрутки поверх вкладок (`overlay`) или в своих местах по краям полосы (`inline`). */\n public readonly scrollArrows: InputSignal<IRtTabs.ScrollArrows> = input<IRtTabs.ScrollArrows>('overlay');\n\n /** Шаг нажатия на стрелку: 80 px (`fixed`), видимая ширина полосы (`page`) или её треть (`third`), как у Material. */\n public readonly scrollStep: InputSignal<IRtTabs.ScrollStep> = input<IRtTabs.ScrollStep>('fixed');\n\n /**\n * Длительность движения при смене вкладки — и полосы, и панели, как у `mat-tab-group`: `500`,\n * `'500ms'`, `'0.5s'`; `0` выключает движение. Без входа длительности берутся из токенов.\n */\n public readonly animationDuration: InputSignal<IRtTabs.AnimationDuration> = input<IRtTabs.AnimationDuration>(null);\n\n /** Таб-стоп открытой панели, как `contentTabIndex` у `mat-tab-group`: `null` — Tab идёт с полосы прямо в поля панели. */\n public readonly contentTabIndex: InputSignal<number | null> = input<number | null>(0);\n\n /** Эмиттит id вкладки при её выборе (клик/клавиатура). */\n public readonly activeIdChange: OutputEmitterRef<IRtTabs.Id> = output<IRtTabs.Id>();\n\n /**\n * Просьба закрыть вкладку с `closable`: крестик или Delete на вкладке в фокусе. Набор вкладок\n * держит потребитель — он и убирает вкладку; закрытая активная откатывается на первую доступную.\n */\n public readonly tabClose: OutputEmitterRef<IRtTabs.Id> = output<IRtTabs.Id>();\n\n readonly #injector: Injector = inject(Injector);\n\n /** Плавная прокрутка полосы: стрелки и вкладка, встающая в видимую область. */\n readonly #scroller: RtTabsScroller = new RtTabsScroller(this.#win, this.#host, (): ElementRef<HTMLElement> | undefined =>\n this.tabListRef()\n );\n\n /** Внутренний выбор (uncontrolled-ветка). */\n readonly #internalId: WritableSignal<IRtTabs.Id | null> = signal<IRtTabs.Id | null>(null);\n\n /** Вкладка, на которую перевели фокус стрелками в ручном режиме; сбрасывается выбором. */\n readonly #focusedId: WritableSignal<IRtTabs.Id | null> = signal<IRtTabs.Id | null>(null);\n\n /** Нажатие и удержание стрелок прокрутки. */\n readonly #press: RtTabsArrowPress = new RtTabsArrowPress(\n this.#win,\n this.#scroller,\n (): HTMLElement | undefined => this.tabListRef()?.nativeElement,\n (): IRtTabs.ScrollStep => this.scrollStep(),\n (): void => this.#updateRestVisibility()\n );\n\n /** Вкладки стали шире или уже — полоса снова встаёт к выбранной, пока её не прокрутили рукой. */\n readonly #follow: RtTabsFollow = new RtTabsFollow((): void => this.#scrollToSelected(true));\n\n /** Вкладка, к которой полоса прокручена последней: второй прокрутки к ней не нужно. */\n #scrolledId: IRtTabs.Id | null = null;\n\n constructor() {\n if (this.#win) {\n fromEvent(this.#win, 'resize')\n .pipe(debounceTime(REST_DEBOUNCE_MS), takeUntilDestroyed())\n .subscribe((): void => this.#updateRestVisibility());\n }\n\n afterNextRender((): void => {\n this.#scrollToSelected();\n this.#updateRestVisibility();\n });\n\n // Смена вкладки извне — входом `activeId` или новым набором вкладок. После клика\n // полоса уже прокручена из `selectTab`, и `#scrolledId` пропускает вторую прокрутку.\n afterRenderEffect((): void => this.#scrollToSelected());\n\n // Новый набор вкладок — наблюдение за их размерами ставится заново.\n afterRenderEffect((): void => this.#follow.watch(this.tabListRef()?.nativeElement, this.visibleTabs().length));\n\n // Снимаем hold-scroll интервал при уничтожении: если компонент разрушить\n // с зажатой стрелкой (pointerdown без pointerup), интервал остался бы жив.\n inject(DestroyRef).onDestroy((): void => {\n this.#press.stop();\n this.#follow.stop();\n this.#scroller.stop();\n });\n }\n\n protected selectTab(id: IRtTabs.Id): void {\n const target: RtTabDirective | undefined = this.visibleTabs().find((tab: RtTabDirective): boolean => tab.id() === id);\n\n if (!target || target.disabled()) {\n return;\n }\n\n this.#internalId.set(id);\n this.#focusedId.set(null);\n this.activeIdChange.emit(id);\n this.#follow.follow();\n this.#scrollTabIntoView(id);\n }\n\n /** Крестик: нажатие не выбирает вкладку; фокус с крестика после закрытия уходит на вкладку, не на страницу. */\n protected onCloseClick(event: MouseEvent, tab: RtTabDirective): void {\n event.stopPropagation();\n this.#close(tab, event.currentTarget instanceof HTMLElement && event.currentTarget.matches(':focus'));\n }\n\n /**\n * Навигация по вкладкам с клавиатуры. Шаг считается от вкладки в фокусе: в ручном режиме она\n * не совпадает с активной. Enter и Space ловит сама кнопка — они дают click и выбор.\n */\n protected onTabKeydown(event: KeyboardEvent, tab: RtTabDirective): void {\n if (event.key === 'Delete') {\n this.#closeByKey(event, tab);\n return;\n }\n\n const enabled: readonly RtTabDirective[] = this.visibleTabs().filter((item: RtTabDirective): boolean => !item.disabled());\n\n if (!enabled.length) {\n return;\n }\n\n const isVertical: boolean = this.direction() === 'vertical';\n const nextKey: string = isVertical ? 'ArrowDown' : 'ArrowRight';\n const prevKey: string = isVertical ? 'ArrowUp' : 'ArrowLeft';\n const currentIndex: number = enabled.findIndex((item: RtTabDirective): boolean => item.id() === tab.id());\n\n // Карта клавиша → целевой индекс (без if/else-if цепочки).\n const moveByKey: ReadonlyMap<string, number> = new Map<string, number>([\n [nextKey, (currentIndex + 1) % enabled.length],\n [prevKey, (currentIndex - 1 + enabled.length) % enabled.length],\n ['Home', 0],\n ['End', enabled.length - 1],\n ]);\n\n const targetIndex: number | undefined = moveByKey.get(event.key);\n\n if (targetIndex === undefined) {\n return;\n }\n\n event.preventDefault();\n const targetId: IRtTabs.Id = enabled[targetIndex].id();\n\n if (this.activation() === 'manual') {\n this.#focusedId.set(targetId);\n this.#scrollTabIntoView(targetId);\n } else {\n this.selectTab(targetId);\n }\n this.#focusTab(targetId);\n }\n\n /** Нажатие ЛКМ на стрелку: шаг или прокрутка по удержанию — {@link RtTabsArrowPress}. */\n protected onRestPointerDown(direction: TRtTabsScrollDirection, event: MouseEvent): void {\n if (event.button === 0) {\n this.#follow.manual();\n this.#press.down(direction);\n }\n }\n\n protected onRestPointerUp(): void {\n this.#press.up();\n }\n\n /** Указатель ушёл со стрелки: прокрутка останавливается, шага нет. */\n protected onRestPointerLeave(): void {\n this.#press.stop();\n }\n\n protected onTabListScroll(): void {\n this.#updateRestVisibility();\n }\n\n /**\n * Delete на закрываемой вкладке. Фокус после перерисовки встаёт на активную вкладку: закрытая\n * пропадёт из шапки, и фокус иначе упал бы на страницу.\n */\n #closeByKey(event: KeyboardEvent, tab: RtTabDirective): void {\n if (!tab.showClose()) {\n return;\n }\n\n event.preventDefault();\n this.#close(tab, true);\n }\n\n /**\n * Просьба закрыть вкладку. Владелец убирает её из набора; если она была активной, выбор после\n * перерисовки переходит на первую доступную, и об этом сообщает `activeIdChange` — иначе владелец,\n * держащий `activeId`, хранил бы id закрытой вкладки и показывал её содержимое снаружи.\n */\n #close(tab: RtTabDirective, focus: boolean): void {\n const closedId: IRtTabs.Id = tab.id();\n const wasActive: boolean = this.selectedId() === closedId;\n this.tabClose.emit(closedId);\n\n afterNextRender(\n (): void => {\n const id: IRtTabs.Id | null = this.selectedId();\n if (id === null) {\n return;\n }\n if (wasActive && id !== closedId) {\n this.#internalId.set(id);\n this.activeIdChange.emit(id);\n }\n if (focus) {\n this.#focusTab(id);\n }\n },\n { injector: this.#injector }\n );\n }\n\n #updateRestVisibility(): void {\n const list: HTMLElement | undefined = this.tabListRef()?.nativeElement;\n\n if (!list || this.direction() !== 'horizontal') {\n this.restBeforeVisible.set(false);\n this.restAfterVisible.set(false);\n return;\n }\n\n const scrolledRight: number = list.scrollWidth - list.scrollLeft - list.clientWidth;\n\n this.restBeforeVisible.set(list.scrollLeft > 0);\n // 1px — погрешность субпиксельного scrollWidth\n this.restAfterVisible.set(scrolledRight > 1);\n }\n\n /** `again` — вкладки сменили размер: та же вкладка встаёт на место ещё раз. */\n #scrollToSelected(again: boolean = false): void {\n const id: IRtTabs.Id | null = this.selectedId();\n\n if (id !== null && (again || id !== this.#scrolledId)) {\n this.#follow.follow();\n this.#scrollTabIntoView(id);\n }\n }\n\n /**\n * Ставит вкладку в полосу целиком. Стрелки поверх полосы закрывают её края, поэтому вкладка\n * отступает от края на ширину стрелки. Первая прокрутка — сразу: открытая страница не едет.\n */\n #scrollTabIntoView(id: IRtTabs.Id): void {\n const list: HTMLElement | undefined = this.tabListRef()?.nativeElement;\n const tab: HTMLElement | null | undefined = list?.querySelector<HTMLElement>(`[data-tabitem=\"${id}\"]`);\n\n if (!list || !tab) {\n return;\n }\n\n const first: boolean = this.#scrolledId === null;\n const rest: HTMLElement | null | undefined = list.parentElement?.querySelector<HTMLElement>('.rt-tabs__rest');\n const inset: number = this.scrollArrows() === 'overlay' ? (rest?.offsetWidth ?? 0) : 0;\n const target: number | null = rtTabsIntoViewTarget(list, tab, inset);\n this.#scrolledId = id;\n\n if (target !== null && first) {\n this.#scroller.stop();\n list.scrollLeft = target;\n } else if (target !== null) {\n this.#scroller.to(target);\n } else {\n // вкладка целиком в зоне видимости — прокрутка не нужна\n }\n\n // Сразу — для прокрутки без движения; плавную ведут события прокрутки самой полосы.\n this.#updateRestVisibility();\n }\n\n #focusTab(id: IRtTabs.Id): void {\n const list: HTMLElement | undefined = this.tabListRef()?.nativeElement;\n // Без прокрутки фокусом: вкладку в видимую область ведёт плавная прокрутка полосы.\n list?.querySelector<HTMLElement>(`[data-tabid=\"${id}\"]`)?.focus({ preventScroll: true });\n }\n}\n","<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"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-tag.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/tag/rt-tag.component.ts","../../../projects/ui-kit-v2/src/lib/components/tag/rt-tag.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n afterRenderEffect,\n booleanAttribute,\n inject,\n input,\n output,\n signal,\n viewChild,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n InputSignal,\n InputSignalWithTransform,\n OnDestroy,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { IRtMatchPart, rtMatchParts } from '@rt-tools/ui-kit-v2/core';\nimport { IRtTag } from './rt-tag.model';\n\nconst BEM_BLOCK: string = 'rt-tag';\n\n/** Ступень значка по ступени пилюли. `md` оставляет значок таким, каким он был до ступеней. */\nconst ICON_BY_SIZE: Readonly<Record<IRtTag.Size, IRtIcon.Size>> = { sm: 'xs', md: 'sm', lg: 'md' };\n\n/**\n * Status/label pill для отображения статусов и счётчиков.\n * Поддерживает 6 severity-вариантов (`info` / `success` / `warning` / `danger` /\n * `secondary` / `neutral`), любой шаг скругления входом `radius` и опциональный close-control\n * (рендерит `rt-icon-button` с иконкой `ico-close` и emits `closed` MouseEvent).\n *\n * Все цвета — через семантические `--rt-color-state-*` токены; layout через\n * primitive `--rt-space-*` / `--rt-radius-*` / `--rt-text-*`. BEM-разметка через\n * директивы `rtBlock` / `rtElem` / `rtMod` из `@rt-tools/core`.\n */\n@Component({\n selector: 'rt-tag',\n templateUrl: './rt-tag.component.html',\n styleUrl: './rt-tag.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtIconComponent,\n RtIconButtonComponent,\n RtTooltipDirective,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtTagComponent implements OnDestroy {\n /** Текст pill — обязательный input. */\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n #resizeObserver: ResizeObserver | null = null;\n\n protected readonly textRef: Signal<ElementRef<HTMLElement> | undefined> = viewChild<ElementRef<HTMLElement>>('text');\n\n /** Подписи не хватило места: она урезана многоточием, и целое значение показывает подсказка. */\n protected readonly overflowing: WritableSignal<boolean> = signal<boolean>(false);\n\n /** Размер значка ведёт ступень пилюли: свой вход у него был бы вторым числом об одном. */\n protected readonly iconSize: Signal<IRtIcon.Size> = computed((): IRtIcon.Size => ICON_BY_SIZE[this.size()]);\n\n /** Подпись, разрезанная по словам `highlight`: без них — один кусок целиком. */\n protected readonly parts: Signal<ReadonlyArray<IRtMatchPart>> = computed((): ReadonlyArray<IRtMatchPart> =>\n rtMatchParts(this.value(), this.highlight())\n );\n\n public readonly value: InputSignal<string> = input.required<string>();\n\n /**\n * Слова поиска, найденные куски которых метка отмечает: приложение, что ищет и по меткам,\n * показывает, где слово нашлось. Пустая строка ничего не отмечает.\n */\n public readonly highlight: InputSignal<string> = input<string>('');\n\n /** Семантическая палитра. По умолчанию `neutral` (нейтральный серый). */\n public readonly severity: InputSignal<IRtTag.Severity> = input<IRtTag.Severity>('neutral');\n\n /**\n * Ступень размера. Умолчание `md` — тот размер, каким метка рисовалась до появления ступеней.\n * Отступы, кегль и значок двигаются вместе: кегль, названный отдельно, оставил бы отступы от\n * другой ступени, и ряд пилюль перестал бы выстраиваться.\n */\n public readonly size: InputSignal<IRtTag.Size> = input<IRtTag.Size>('md');\n\n /** Вид заливки. По умолчанию `solid`; `outlined` — прозрачный фон + рамка. */\n public readonly appearance: InputSignal<IRtTag.Appearance> = input<IRtTag.Appearance>('solid');\n\n /** Префикс-иконка слева от текста. `null` (дефолт) — без иконки. */\n public readonly icon: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /** Суффикс-иконка справа от текста (напр. `external-link` у тега-ссылки). */\n public readonly iconEnd: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /** Рендерит крестик `rt-icon-button` справа от текста. */\n public readonly closable: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Эмиттит MouseEvent при клике на close-button (только если `closable=true`). */\n public readonly closed: OutputEmitterRef<MouseEvent> = output<MouseEvent>();\n\n constructor() {\n afterRenderEffect((): void => {\n this.value();\n this.size();\n this.#observeText();\n this.#measure();\n });\n }\n\n public ngOnDestroy(): void {\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n }\n\n protected onClose(event: MouseEvent): void {\n event.stopPropagation();\n this.closed.emit(event);\n }\n\n /**\n * Переполнение считается наблюдателем за размером, а не отсчётом после отрисовки: отсчёт\n * отвечает о машине, а не о раскладке — на свободной его всегда хватает, на занятой нет, а\n * подпись, переполнившаяся позже, подсказки не получила бы вовсе.\n */\n #observeText(): void {\n const node: HTMLElement | undefined = this.textRef()?.nativeElement;\n\n if (node === undefined || this.#resizeObserver !== null || typeof ResizeObserver === 'undefined') {\n return;\n }\n\n this.#resizeObserver = new ResizeObserver((): void => this.#measure());\n this.#resizeObserver.observe(node);\n }\n\n #measure(): void {\n const node: HTMLElement | undefined = this.textRef()?.nativeElement;\n\n if (node !== undefined) {\n this.overflowing.set(node.scrollWidth > node.clientWidth);\n }\n }\n}\n","<span\n rtBlock=\"rt-tag\"\n qa-dataid=\"tag\"\n [attr.data-severity]=\"severity()\"\n [rtMod]=\"{\n severity: severity(),\n size: size(),\n appearance: appearance(),\n closable: closable(),\n }\">\n @if (icon(); as iconName) {\n <rt-icon rtElem=\"icon\" [size]=\"iconSize()\" [name]=\"iconName\" />\n }\n <!--\n Целое значение показывает подсказка, и только когда подписи не хватило места:\n урезанный текст без подсказки читается как целый — узнать, где он на деле кончается,\n человеку неоткуда. Пустой текст директиву выключает.\n -->\n <span rtElem=\"text\" qa-dataid=\"tag-text\" #text [rtTooltip]=\"overflowing() ? value() : ''\">\n @for (part of parts(); track $index) {\n <span rtElem=\"part\" [rtMod]=\"{ match: part.matched }\">{{ part.text }}</span>\n }\n </span>\n @if (iconEnd(); as iconEndName) {\n <rt-icon rtElem=\"icon-end\" [size]=\"iconSize()\" [name]=\"iconEndName\" />\n }\n @if (closable()) {\n <rt-icon-button\n rtElem=\"close\"\n qa-dataid=\"tag-close\"\n icon=\"ico-close\"\n variant=\"ghost\"\n size=\"sm\"\n radius=\"full\"\n [ariaLabel]=\"t().uiRemove\"\n (clicked)=\"onClose($event)\" />\n }\n</span>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-tag.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/tag/rt-tag.component.ts","../../../projects/ui-kit-v2/src/lib/components/tag/rt-tag.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n afterRenderEffect,\n booleanAttribute,\n inject,\n input,\n output,\n signal,\n viewChild,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n InputSignal,\n InputSignalWithTransform,\n OnDestroy,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { IRtMatchPart, rtMatchParts } from '@rt-tools/ui-kit-v2/core';\nimport { IRtTag } from './rt-tag.model';\n\nconst BEM_BLOCK: string = 'rt-tag';\n\n/** Ступень значка по ступени пилюли. `md` оставляет значок таким, каким он был до ступеней. */\nconst ICON_BY_SIZE: Readonly<Record<IRtTag.Size, IRtIcon.Size>> = { sm: 'xs', md: 'sm', lg: 'md' };\n\n/**\n * Status/label pill для отображения статусов и счётчиков.\n * Поддерживает 6 severity-вариантов (`info` / `success` / `warning` / `danger` /\n * `secondary` / `neutral`), любой шаг скругления входом `radius` и опциональный close-control\n * (рендерит `rt-icon-button` с иконкой `ico-close` и emits `closed` MouseEvent).\n *\n * Все цвета — через семантические `--rt-color-state-*` токены; layout через\n * primitive `--rt-space-*` / `--rt-radius-*` / `--rt-text-*`. BEM-разметка через\n * директивы `rtBlock` / `rtElem` / `rtMod` из `@rt-tools/core`.\n */\n@Component({\n selector: 'rt-tag',\n templateUrl: './rt-tag.component.html',\n styleUrl: './rt-tag.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtIconComponent,\n RtIconButtonComponent,\n RtTooltipDirective,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtTagComponent implements OnDestroy {\n /** Текст pill — обязательный input. */\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n #resizeObserver: ResizeObserver | null = null;\n\n protected readonly textRef: Signal<ElementRef<HTMLElement> | undefined> = viewChild<ElementRef<HTMLElement>>('text');\n\n /** Подписи не хватило места: она урезана многоточием, и целое значение показывает подсказка. */\n protected readonly overflowing: WritableSignal<boolean> = signal<boolean>(false);\n\n /** Размер значка ведёт ступень пилюли: свой вход у него был бы вторым числом об одном. */\n protected readonly iconSize: Signal<IRtIcon.Size> = computed((): IRtIcon.Size => ICON_BY_SIZE[this.size()]);\n\n /** Подпись, разрезанная по словам `highlight`: без них — один кусок целиком. */\n protected readonly parts: Signal<ReadonlyArray<IRtMatchPart>> = computed((): ReadonlyArray<IRtMatchPart> =>\n rtMatchParts(this.value(), this.highlight())\n );\n\n public readonly value: InputSignal<string> = input.required<string>();\n\n /**\n * Слова поиска, найденные куски которых метка отмечает: приложение, что ищет и по меткам,\n * показывает, где слово нашлось. Пустая строка ничего не отмечает.\n */\n public readonly highlight: InputSignal<string> = input<string>('');\n\n /** Семантическая палитра. По умолчанию `neutral` (нейтральный серый). */\n public readonly severity: InputSignal<IRtTag.Severity> = input<IRtTag.Severity>('neutral');\n\n /**\n * Ступень размера. Умолчание `md` — тот размер, каким метка рисовалась до появления ступеней.\n * Отступы, кегль и значок двигаются вместе: кегль, названный отдельно, оставил бы отступы от\n * другой ступени, и ряд пилюль перестал бы выстраиваться.\n */\n public readonly size: InputSignal<IRtTag.Size> = input<IRtTag.Size>('md');\n\n /** Вид заливки. По умолчанию `solid`; `outlined` — прозрачный фон + рамка. */\n public readonly appearance: InputSignal<IRtTag.Appearance> = input<IRtTag.Appearance>('solid');\n\n /** Префикс-иконка слева от текста. `null` (дефолт) — без иконки. */\n public readonly icon: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /** Суффикс-иконка справа от текста (напр. `external-link` у тега-ссылки). */\n public readonly iconEnd: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /** Рендерит крестик `rt-icon-button` справа от текста. */\n public readonly closable: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Эмиттит MouseEvent при клике на close-button (только если `closable=true`). */\n public readonly closed: OutputEmitterRef<MouseEvent> = output<MouseEvent>();\n\n constructor() {\n afterRenderEffect((): void => {\n this.value();\n this.size();\n this.#observeText();\n this.#measure();\n });\n }\n\n public ngOnDestroy(): void {\n this.#resizeObserver?.disconnect();\n this.#resizeObserver = null;\n }\n\n protected onClose(event: MouseEvent): void {\n event.stopPropagation();\n this.closed.emit(event);\n }\n\n /**\n * Переполнение считается наблюдателем за размером, а не отсчётом после отрисовки: отсчёт\n * отвечает о машине, а не о раскладке — на свободной его всегда хватает, на занятой нет, а\n * подпись, переполнившаяся позже, подсказки не получила бы вовсе.\n */\n #observeText(): void {\n const node: HTMLElement | undefined = this.textRef()?.nativeElement;\n\n if (node === undefined || this.#resizeObserver !== null || typeof ResizeObserver === 'undefined') {\n return;\n }\n\n this.#resizeObserver = new ResizeObserver((): void => this.#measure());\n this.#resizeObserver.observe(node);\n }\n\n #measure(): void {\n const node: HTMLElement | undefined = this.textRef()?.nativeElement;\n\n if (node !== undefined) {\n this.overflowing.set(node.scrollWidth > node.clientWidth);\n }\n }\n}\n","<span\n rtBlock=\"rt-tag\"\n qa-dataid=\"tag\"\n [attr.data-severity]=\"severity()\"\n [rtMod]=\"{\n severity: severity(),\n size: size(),\n appearance: appearance(),\n closable: closable(),\n }\">\n @if (icon(); as iconName) {\n <rt-icon rtElem=\"icon\" [size]=\"iconSize()\" [name]=\"iconName\" />\n }\n <!--\n Целое значение показывает подсказка, и только когда подписи не хватило места:\n урезанный текст без подсказки читается как целый — узнать, где он на деле кончается,\n человеку неоткуда. Пустой текст директиву выключает.\n -->\n <span rtElem=\"text\" qa-dataid=\"tag-text\" #text [rtTooltip]=\"overflowing() ? value() : ''\">\n @for (part of parts(); track $index) {\n <span rtElem=\"part\" [rtMod]=\"{ match: part.matched }\">{{ part.text }}</span>\n }\n </span>\n @if (iconEnd(); as iconEndName) {\n <rt-icon rtElem=\"icon-end\" [size]=\"iconSize()\" [name]=\"iconEndName\" />\n }\n @if (closable()) {\n <rt-icon-button\n rtElem=\"close\"\n qa-dataid=\"tag-close\"\n icon=\"ico-close\"\n variant=\"ghost\"\n size=\"sm\"\n radius=\"full\"\n [ariaLabel]=\"t().uiRemove\"\n (clicked)=\"onClose($event)\" />\n }\n</span>\n"],"mappings":"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"}
|