@rt-tools/ui-kit-v2 0.35.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/fesm2022/rt-tools-ui-kit-v2-action-bar.mjs +1 -0
  2. package/fesm2022/rt-tools-ui-kit-v2-action-bar.mjs.map +1 -1
  3. package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs +2 -1
  4. package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs.map +1 -1
  5. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs +1 -0
  6. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs.map +1 -1
  7. package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs +2 -1
  8. package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs.map +1 -1
  9. package/fesm2022/rt-tools-ui-kit-v2-color-palette.mjs +1 -0
  10. package/fesm2022/rt-tools-ui-kit-v2-color-palette.mjs.map +1 -1
  11. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs +4 -2
  12. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs.map +1 -1
  13. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs +1 -0
  14. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs.map +1 -1
  15. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs +1 -0
  16. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs.map +1 -1
  17. package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs +2 -1
  18. package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs.map +1 -1
  19. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +5 -2
  20. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -1
  21. package/fesm2022/rt-tools-ui-kit-v2-field.mjs +1 -0
  22. package/fesm2022/rt-tools-ui-kit-v2-field.mjs.map +1 -1
  23. package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs +2 -1
  24. package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs.map +1 -1
  25. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs +2 -1
  26. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs.map +1 -1
  27. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs +2 -1
  28. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs.map +1 -1
  29. package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs +2 -1
  30. package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs.map +1 -1
  31. package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs +2 -1
  32. package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs.map +1 -1
  33. package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs +2 -1
  34. package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs.map +1 -1
  35. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs +1 -0
  36. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs.map +1 -1
  37. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +10 -6
  38. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -1
  39. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs +22 -2
  40. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs.map +1 -1
  41. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +36 -5
  42. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  43. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs +2 -1
  44. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs.map +1 -1
  45. package/fesm2022/rt-tools-ui-kit-v2-select.mjs +1 -0
  46. package/fesm2022/rt-tools-ui-kit-v2-select.mjs.map +1 -1
  47. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +4 -2
  48. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -1
  49. package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs +3 -1
  50. package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs.map +1 -1
  51. package/fesm2022/rt-tools-ui-kit-v2-split-button.mjs +1 -0
  52. package/fesm2022/rt-tools-ui-kit-v2-split-button.mjs.map +1 -1
  53. package/fesm2022/rt-tools-ui-kit-v2-table.mjs +3 -1
  54. package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
  55. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +2 -1
  56. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -1
  57. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +2 -1
  58. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -1
  59. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +53 -5
  60. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -1
  61. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs +2 -1
  62. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs.map +1 -1
  63. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs +37 -0
  64. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs.map +1 -1
  65. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs +2 -1
  66. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs.map +1 -1
  67. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs +2 -1
  68. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs.map +1 -1
  69. package/fesm2022/rt-tools-ui-kit-v2-usage-ring.mjs +4 -3
  70. package/fesm2022/rt-tools-ui-kit-v2-usage-ring.mjs.map +1 -1
  71. package/package.json +1 -1
  72. package/src/lib/components/page-header/rt-page-header-mobile.scss +6 -0
  73. package/src/lib/components/popover/CONTEXT.md +4 -0
  74. package/src/lib/components/thread-list/rt-thread-list.component.scss +7 -0
  75. package/src/lib/components/tooltip/CONTEXT.md +4 -0
  76. package/src/rich-editor/lib/components/chat/rt-chat.component.scss +31 -1
  77. package/types/rt-tools-ui-kit-v2-popover.d.ts +11 -0
  78. package/types/rt-tools-ui-kit-v2-rich-editor.d.ts +7 -0
  79. package/types/rt-tools-ui-kit-v2-thread-list.d.ts +7 -1
  80. package/types/rt-tools-ui-kit-v2-tooltip.d.ts +12 -0
@@ -175,6 +175,7 @@ var RtActionBarComponent = class RtActionBarComponent {
175
175
  "rtPopoverFitViewport",
176
176
  "rtPopoverContext",
177
177
  "rtPopoverPanelClass",
178
+ "rtPopoverBackdropClass",
178
179
  "rtPopoverDisabled",
179
180
  "rtPopoverOffsetY",
180
181
  "rtPopoverOffsetX",
@@ -1 +1 @@
1
- {"version":3,"file":"rt-tools-ui-kit-v2-action-bar.mjs","names":["BEM_BLOCK"],"sources":["../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar.component.ts","../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar.component.html","../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar.model.ts","../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar.service.ts","../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar-holder.component.ts","../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar-holder.component.html"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n computed,\n input,\n output,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { IRtIcon, TRtKitLabelParams } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtMenuItemComponent } from '@rt-tools/ui-kit-v2/menu';\nimport { RtPopoverDirective } from '@rt-tools/ui-kit-v2/popover';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { IRtActionBar } from './rt-action-bar.model';\n\nconst BEM_BLOCK: string = 'rt-action-bar';\n\n/** Действие вместе с готовой записью модификаторов: шаблон методов не зовёт. */\ninterface IActionView {\n readonly action: IRtActionBar.Action;\n readonly modifiers: Readonly<Record<string, boolean>>;\n /**\n * Имя кнопки для вспомогательных средств — у действия со значком. На грубом указателе подпись\n * снята правилом стиля, а значок немой: без имени кнопка осталась бы безымянной.\n */\n readonly ariaLabel: string | null;\n}\n\n/**\n * Полоса массовых действий: счёт слева, действия рядом, крестик справа.\n *\n * Своего состояния не держит вовсе — ни выбранного, ни открытости. Ей дают\n * настройку входом, а наружу она сообщает две вещи: что нажали действие и что\n * нажали крестик. Держатель `rt-action-bar-holder` решает, стоит ли она в\n * разметке и где над страницей приколота.\n *\n * Действие с вложенным списком само не срабатывает: оно заголовок группы, и\n * список раскрывается всплывающим слоем кита. Нажатие пункта списка закрывает\n * полосу так же, как нажатие обычного действия: где человек нажал — в полосе\n * или на шаг глубже — о трате выбранного не говорит ничего.\n */\n@Component({\n selector: 'rt-action-bar',\n templateUrl: './rt-action-bar.component.html',\n styleUrl: './rt-action-bar.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n NgTemplateOutlet,\n RtIconComponent,\n RtIconButtonComponent,\n RtMenuItemComponent,\n RtPopoverDirective,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n role: 'toolbar',\n },\n})\nexport class RtActionBarComponent {\n /** Подстановки счётчика: подпись собирает словарь, а не склейка слов в шаблоне. */\n readonly #countParams: Signal<TRtKitLabelParams> = computed((): TRtKitLabelParams => ({\n count: this.config().selected,\n total: this.config().total,\n }));\n\n protected readonly countText: Signal<string> = rtKitLabel('uiSelectedOf', this.#countParams);\n\n protected readonly closeLabel: Signal<string> = rtKitLabel('uiClose');\n\n /**\n * Действия с готовыми модификаторами. Признак значка стоит модификатором, а не\n * условием в шаблоне: подпись у действия со значком снимает правило стиля по\n * грубому указателю, и решать это условием значило бы увезти оформление в код.\n */\n protected readonly actions: Signal<readonly IActionView[]> = computed((): readonly IActionView[] =>\n this.config().actions.map((action: IRtActionBar.Action): IActionView => ({\n action,\n modifiers: { danger: action.look === 'danger', withIcon: !!(action.icon || action.glyph) },\n ariaLabel: action.icon || action.glyph ? action.label : null,\n }))\n );\n\n public readonly config: InputSignal<IRtActionBar.Config> = input.required<IRtActionBar.Config>();\n /** Значок кнопки, закрывающей полосу. */\n public readonly closeIcon: InputSignal<IRtIcon.Name> = input<IRtIcon.Name>('close');\n\n public readonly actionRun: OutputEmitterRef<IRtActionBar.Action> = output<IRtActionBar.Action>();\n\n public readonly closed: OutputEmitterRef<void> = output<void>();\n\n protected onAction(action: IRtActionBar.Action): void {\n action.run?.();\n this.actionRun.emit(action);\n this.closed.emit();\n }\n\n protected onClose(): void {\n this.closed.emit();\n }\n}\n","<ng-container rtBlock=\"rt-action-bar\">\n <span rtElem=\"counter\" qa-dataid=\"action-bar-counter\">{{ countText() }}</span>\n\n @if (actions().length) {\n <div rtElem=\"actions\" qa-dataid=\"action-bar-actions\">\n @for (view of actions(); track view.action.label) {\n @if (view.action.menu) {\n <!--\n Действие с вложенным списком само не срабатывает: оно заголовок группы, и\n нажатие раскрывает слой. Список приходит слою контекстом — одного шаблона\n хватает на все такие действия.\n -->\n <button\n type=\"button\"\n rtElem=\"action\"\n qa-dataid=\"action-bar-action\"\n [rtMod]=\"view.modifiers\"\n [attr.aria-label]=\"view.ariaLabel\"\n [rtPopover]=\"menuTpl\"\n [rtPopoverContext]=\"view.action.menu\">\n <ng-container *ngTemplateOutlet=\"actionFace; context: { $implicit: view.action }\" />\n </button>\n } @else {\n <button\n type=\"button\"\n rtElem=\"action\"\n qa-dataid=\"action-bar-action\"\n [rtMod]=\"view.modifiers\"\n [attr.aria-label]=\"view.ariaLabel\"\n (click)=\"onAction(view.action)\">\n <ng-container *ngTemplateOutlet=\"actionFace; context: { $implicit: view.action }\" />\n </button>\n }\n }\n </div>\n }\n\n <rt-icon-button\n rtElem=\"close\"\n qa-dataid=\"action-bar-close\"\n variant=\"ghost\"\n size=\"sm\"\n [icon]=\"closeIcon()\"\n [ariaLabel]=\"closeLabel()\"\n (clicked)=\"onClose()\" />\n\n <!--\n Оба шаблона объявлены внутри блока намеренно: `rtElem` берёт имя блока инъекцией у\n ближайшего предка с `rtBlock`, а у шаблона, объявленного снаружи, такого предка нет\n вовсе — компонент не поднимается совсем, с отказом об отсутствующем поставщике.\n\n Лицо действия: значок и подпись. Подпись стоит в разметке всегда — снимает её правило\n стиля по грубому указателю, и только у действия, у которого значок есть.\n -->\n <ng-template #actionFace let-action>\n @if (action.icon || action.glyph) {\n <rt-icon rtElem=\"action-icon\" size=\"sm\" [name]=\"action.icon ?? null\" [glyph]=\"action.glyph ?? null\" />\n }\n\n <span rtElem=\"action-label\">{{ action.label }}</span>\n </ng-template>\n\n <ng-template #menuTpl let-menu>\n <div rtElem=\"menu\" qa-dataid=\"action-bar-menu\" role=\"menu\">\n @for (item of menu; track item.label) {\n <rt-menu-item\n qa-dataid=\"action-bar-menu-item\"\n [icon]=\"item.icon ?? null\"\n [glyph]=\"item.glyph ?? null\"\n [label]=\"item.label\"\n [danger]=\"item.look === 'danger'\"\n (selected)=\"onAction(item)\" />\n }\n </div>\n </ng-template>\n</ng-container>\n","import { IRtIcon } from '@rt-tools/ui-kit-v2/core';\n\n/**\n * Контракты полосы массовых действий. Один корневой неймспейс с префиксом `I`.\n *\n * Отличие от договора первого кита одно и оно намеренное: произвольного объекта\n * стилей на действии здесь нет. Вид кнопки называется именем из набора кита —\n * значение цвета в разметку не приходит вовсе.\n */\nexport namespace IRtActionBar {\n /** Вид действия: тем же именем, каким его зовёт кнопка кита. */\n export type Look = 'plain' | 'danger';\n\n /**\n * Одно нажатие в полосе. Либо `run` — то, что действие делает, — либо `menu`:\n * вложенный список. Действие с вложенным списком само не срабатывает: оно\n * заголовок группы, и запуск его наравне с раскрытием запустил бы то, чего\n * человек не выбирал.\n */\n export interface Action {\n readonly label: string;\n readonly icon?: IRtIcon.Name;\n /**\n * Имя Material вместо значка кита: рисуется так же, как вход `glyph` у `rt-icon` — парой из\n * перечня кита или лигатурой шрифта. Значок кита, заданный рядом, сильнее.\n */\n readonly glyph?: string;\n readonly look?: IRtActionBar.Look;\n readonly run?: () => void;\n readonly menu?: readonly IRtActionBar.Action[];\n }\n\n /**\n * Настройка полосы целиком. Счёт приходит парой: сколько выбрано и сколько\n * всего. Полоса ничего из этого не считает — ей дают числа.\n */\n export interface Config {\n readonly selected: number;\n readonly total: number;\n readonly actions: readonly IRtActionBar.Action[];\n }\n}\n\n/**\n * Сколько полоса держится в разметке после закрытия — ровно длительность ухода\n * из стилей.\n *\n * Число живёт здесь, а не только в правиле стиля: разметку снимает держатель, и,\n * разойдясь с правилом, он обрывает уход на полпути. Держателю и стилям нужно\n * одно и то же число, поэтому оно объявлено рядом с договором, а не в одном из них.\n */\nexport const RT_ACTION_BAR_LEAVE_MS: number = 300;\n","import { Injectable, Signal, WritableSignal, signal } from '@angular/core';\n\nimport { IRtActionBar } from './rt-action-bar.model';\n\nconst EMPTY_CONFIG: IRtActionBar.Config = { selected: 0, total: 0, actions: [] };\n\n/**\n * Настройка полосы массовых действий: держатель её читает, список — пишет.\n *\n * Служба без корня намеренно. Тот, кто отмечает строки, и тот, кто рисует полосу,\n * стоят на разной глубине одного экрана, и передавать настройку вниз через всё,\n * что между ними, значит рассказать о полосе каждому из них. Потребитель\n * объявляет службу на своём уровне — там, где у него живёт список.\n */\n@Injectable()\nexport class RtActionBarService {\n readonly #config: WritableSignal<IRtActionBar.Config> = signal<IRtActionBar.Config>(EMPTY_CONFIG);\n\n public readonly config: Signal<IRtActionBar.Config> = this.#config.asReadonly();\n\n /** Список действий. Счёт не трогается: он приходит своим вызовом. */\n public setActions(actions: readonly IRtActionBar.Action[]): void {\n this.#config.update((config: IRtActionBar.Config): IRtActionBar.Config => ({ ...config, actions }));\n }\n\n /** Счёт выбранного. Полоса открывается именно им. */\n public setCounts(selected: number, total: number): void {\n this.#config.update((config: IRtActionBar.Config): IRtActionBar.Config => ({ ...config, selected, total }));\n }\n\n /** Отпустить выбранное: счёт обнуляется, список действий остаётся. */\n public clearSelection(): void {\n this.#config.update((config: IRtActionBar.Config): IRtActionBar.Config => ({ ...config, selected: 0, total: 0 }));\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n InputSignal,\n Signal,\n ViewEncapsulation,\n WritableSignal,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\n\nimport { RtActionBarComponent } from './rt-action-bar.component';\nimport { IRtActionBar, RT_ACTION_BAR_LEAVE_MS } from './rt-action-bar.model';\nimport { RtActionBarService } from './rt-action-bar.service';\n\nconst BEM_BLOCK: string = 'rt-action-bar-holder';\n\n/**\n * Держатель полосы массовых действий: решает, стоит ли она в разметке, и прикалывает\n * её над страницей. Настройку читает у службы, которую потребитель объявил на своём\n * уровне — там, где у него живёт список.\n *\n * Полоса открывается счётом выбранного, а не своим признаком: два источника одного\n * признака расходятся молча, и признак, оставшийся поднятым над опустевшим выбором,\n * держал бы полосу над страницей, где ничего не выбрано.\n *\n * После закрытия полоса остаётся в разметке ровно на длительность ухода — число одно\n * и лежит в договоре рядом. Разойдясь с правилом стиля, держатель обрывал бы уход на\n * полпути.\n */\n@Component({\n selector: 'rt-action-bar-holder',\n templateUrl: './rt-action-bar-holder.component.html',\n styleUrl: './rt-action-bar-holder.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [RtActionBarComponent, BlockDirective, ElemDirective, ModDirective],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtActionBarHolderComponent {\n readonly #service: RtActionBarService = inject(RtActionBarService);\n readonly #destroyRef: DestroyRef = inject(DestroyRef);\n\n /** Уходит ли полоса прямо сейчас: разметка держит её, пока правило стиля не доиграет. */\n readonly #leaving: WritableSignal<boolean> = signal<boolean>(false);\n\n #leaveTimer: ReturnType<typeof setTimeout> | null = null;\n\n /**\n * Была ли полоса открыта до этой перемены. Без этого признака уходу не с чего начаться:\n * к минуте, когда выбранное обнулилось, и «открыта», и «стоит в разметке» уже ложь, так\n * что условие по ним не срабатывает никогда. В первом ките оно написано именно так, и\n * уход там не заводится вовсе — образец прочитан, а не перенесён.\n */\n #wasOpened: boolean = false;\n\n protected readonly config: Signal<IRtActionBar.Config> = this.#service.config;\n\n /** Выбрано ли что-нибудь: этим полоса и открывается. */\n protected readonly opened: Signal<boolean> = computed((): boolean => this.config().selected > 0);\n\n /** Стоит ли полоса в разметке: она остаётся в ней и на время ухода. */\n protected readonly shown: Signal<boolean> = computed((): boolean => this.opened() || this.#leaving());\n\n protected readonly leaving: Signal<boolean> = this.#leaving.asReadonly();\n\n /** Значок кнопки, закрывающей полосу, — уходит в саму полосу. */\n public readonly closeIcon: InputSignal<IRtIcon.Name> = input<IRtIcon.Name>('close');\n\n constructor() {\n effect((): void => {\n const opened: boolean = this.opened();\n\n untracked((): void => {\n this.#clearLeaveTimer();\n\n if (opened) {\n this.#wasOpened = true;\n this.#leaving.set(false);\n\n return;\n }\n\n if (this.#wasOpened) {\n this.#wasOpened = false;\n this.#startLeaving();\n }\n });\n });\n\n this.#destroyRef.onDestroy((): void => this.#clearLeaveTimer());\n }\n\n /** Крестик сообщает наружу; выбранное отпускает служба, которой список и владеет. */\n protected onClosed(): void {\n this.#service.clearSelection();\n }\n\n /** Полоса остаётся в разметке на время ухода и снимается по его концу. */\n #startLeaving(): void {\n this.#leaving.set(true);\n this.#leaveTimer = setTimeout((): void => {\n this.#leaving.set(false);\n this.#leaveTimer = null;\n }, RT_ACTION_BAR_LEAVE_MS);\n }\n\n #clearLeaveTimer(): void {\n if (this.#leaveTimer !== null) {\n clearTimeout(this.#leaveTimer);\n this.#leaveTimer = null;\n }\n }\n}\n","<ng-container rtBlock=\"rt-action-bar-holder\">\n @if (shown()) {\n <rt-action-bar\n rtElem=\"bar\"\n qa-dataid=\"action-bar-holder-bar\"\n [rtMod]=\"{ leaving: leaving() }\"\n [config]=\"config()\"\n [closeIcon]=\"closeIcon()\"\n (closed)=\"onClosed()\" />\n }\n</ng-container>\n"],"mappings":"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"}
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-action-bar.mjs","names":["BEM_BLOCK"],"sources":["../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar.component.ts","../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar.component.html","../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar.model.ts","../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar.service.ts","../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar-holder.component.ts","../../../projects/ui-kit-v2/src/lib/components/action-bar/rt-action-bar-holder.component.html"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n computed,\n input,\n output,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { IRtIcon, TRtKitLabelParams } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtMenuItemComponent } from '@rt-tools/ui-kit-v2/menu';\nimport { RtPopoverDirective } from '@rt-tools/ui-kit-v2/popover';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { IRtActionBar } from './rt-action-bar.model';\n\nconst BEM_BLOCK: string = 'rt-action-bar';\n\n/** Действие вместе с готовой записью модификаторов: шаблон методов не зовёт. */\ninterface IActionView {\n readonly action: IRtActionBar.Action;\n readonly modifiers: Readonly<Record<string, boolean>>;\n /**\n * Имя кнопки для вспомогательных средств — у действия со значком. На грубом указателе подпись\n * снята правилом стиля, а значок немой: без имени кнопка осталась бы безымянной.\n */\n readonly ariaLabel: string | null;\n}\n\n/**\n * Полоса массовых действий: счёт слева, действия рядом, крестик справа.\n *\n * Своего состояния не держит вовсе — ни выбранного, ни открытости. Ей дают\n * настройку входом, а наружу она сообщает две вещи: что нажали действие и что\n * нажали крестик. Держатель `rt-action-bar-holder` решает, стоит ли она в\n * разметке и где над страницей приколота.\n *\n * Действие с вложенным списком само не срабатывает: оно заголовок группы, и\n * список раскрывается всплывающим слоем кита. Нажатие пункта списка закрывает\n * полосу так же, как нажатие обычного действия: где человек нажал — в полосе\n * или на шаг глубже — о трате выбранного не говорит ничего.\n */\n@Component({\n selector: 'rt-action-bar',\n templateUrl: './rt-action-bar.component.html',\n styleUrl: './rt-action-bar.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n NgTemplateOutlet,\n RtIconComponent,\n RtIconButtonComponent,\n RtMenuItemComponent,\n RtPopoverDirective,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n role: 'toolbar',\n },\n})\nexport class RtActionBarComponent {\n /** Подстановки счётчика: подпись собирает словарь, а не склейка слов в шаблоне. */\n readonly #countParams: Signal<TRtKitLabelParams> = computed((): TRtKitLabelParams => ({\n count: this.config().selected,\n total: this.config().total,\n }));\n\n protected readonly countText: Signal<string> = rtKitLabel('uiSelectedOf', this.#countParams);\n\n protected readonly closeLabel: Signal<string> = rtKitLabel('uiClose');\n\n /**\n * Действия с готовыми модификаторами. Признак значка стоит модификатором, а не\n * условием в шаблоне: подпись у действия со значком снимает правило стиля по\n * грубому указателю, и решать это условием значило бы увезти оформление в код.\n */\n protected readonly actions: Signal<readonly IActionView[]> = computed((): readonly IActionView[] =>\n this.config().actions.map((action: IRtActionBar.Action): IActionView => ({\n action,\n modifiers: { danger: action.look === 'danger', withIcon: !!(action.icon || action.glyph) },\n ariaLabel: action.icon || action.glyph ? action.label : null,\n }))\n );\n\n public readonly config: InputSignal<IRtActionBar.Config> = input.required<IRtActionBar.Config>();\n /** Значок кнопки, закрывающей полосу. */\n public readonly closeIcon: InputSignal<IRtIcon.Name> = input<IRtIcon.Name>('close');\n\n public readonly actionRun: OutputEmitterRef<IRtActionBar.Action> = output<IRtActionBar.Action>();\n\n public readonly closed: OutputEmitterRef<void> = output<void>();\n\n protected onAction(action: IRtActionBar.Action): void {\n action.run?.();\n this.actionRun.emit(action);\n this.closed.emit();\n }\n\n protected onClose(): void {\n this.closed.emit();\n }\n}\n","<ng-container rtBlock=\"rt-action-bar\">\n <span rtElem=\"counter\" qa-dataid=\"action-bar-counter\">{{ countText() }}</span>\n\n @if (actions().length) {\n <div rtElem=\"actions\" qa-dataid=\"action-bar-actions\">\n @for (view of actions(); track view.action.label) {\n @if (view.action.menu) {\n <!--\n Действие с вложенным списком само не срабатывает: оно заголовок группы, и\n нажатие раскрывает слой. Список приходит слою контекстом — одного шаблона\n хватает на все такие действия.\n -->\n <button\n type=\"button\"\n rtElem=\"action\"\n qa-dataid=\"action-bar-action\"\n [rtMod]=\"view.modifiers\"\n [attr.aria-label]=\"view.ariaLabel\"\n [rtPopover]=\"menuTpl\"\n [rtPopoverContext]=\"view.action.menu\">\n <ng-container *ngTemplateOutlet=\"actionFace; context: { $implicit: view.action }\" />\n </button>\n } @else {\n <button\n type=\"button\"\n rtElem=\"action\"\n qa-dataid=\"action-bar-action\"\n [rtMod]=\"view.modifiers\"\n [attr.aria-label]=\"view.ariaLabel\"\n (click)=\"onAction(view.action)\">\n <ng-container *ngTemplateOutlet=\"actionFace; context: { $implicit: view.action }\" />\n </button>\n }\n }\n </div>\n }\n\n <rt-icon-button\n rtElem=\"close\"\n qa-dataid=\"action-bar-close\"\n variant=\"ghost\"\n size=\"sm\"\n [icon]=\"closeIcon()\"\n [ariaLabel]=\"closeLabel()\"\n (clicked)=\"onClose()\" />\n\n <!--\n Оба шаблона объявлены внутри блока намеренно: `rtElem` берёт имя блока инъекцией у\n ближайшего предка с `rtBlock`, а у шаблона, объявленного снаружи, такого предка нет\n вовсе — компонент не поднимается совсем, с отказом об отсутствующем поставщике.\n\n Лицо действия: значок и подпись. Подпись стоит в разметке всегда — снимает её правило\n стиля по грубому указателю, и только у действия, у которого значок есть.\n -->\n <ng-template #actionFace let-action>\n @if (action.icon || action.glyph) {\n <rt-icon rtElem=\"action-icon\" size=\"sm\" [name]=\"action.icon ?? null\" [glyph]=\"action.glyph ?? null\" />\n }\n\n <span rtElem=\"action-label\">{{ action.label }}</span>\n </ng-template>\n\n <ng-template #menuTpl let-menu>\n <div rtElem=\"menu\" qa-dataid=\"action-bar-menu\" role=\"menu\">\n @for (item of menu; track item.label) {\n <rt-menu-item\n qa-dataid=\"action-bar-menu-item\"\n [icon]=\"item.icon ?? null\"\n [glyph]=\"item.glyph ?? null\"\n [label]=\"item.label\"\n [danger]=\"item.look === 'danger'\"\n (selected)=\"onAction(item)\" />\n }\n </div>\n </ng-template>\n</ng-container>\n","import { IRtIcon } from '@rt-tools/ui-kit-v2/core';\n\n/**\n * Контракты полосы массовых действий. Один корневой неймспейс с префиксом `I`.\n *\n * Отличие от договора первого кита одно и оно намеренное: произвольного объекта\n * стилей на действии здесь нет. Вид кнопки называется именем из набора кита —\n * значение цвета в разметку не приходит вовсе.\n */\nexport namespace IRtActionBar {\n /** Вид действия: тем же именем, каким его зовёт кнопка кита. */\n export type Look = 'plain' | 'danger';\n\n /**\n * Одно нажатие в полосе. Либо `run` — то, что действие делает, — либо `menu`:\n * вложенный список. Действие с вложенным списком само не срабатывает: оно\n * заголовок группы, и запуск его наравне с раскрытием запустил бы то, чего\n * человек не выбирал.\n */\n export interface Action {\n readonly label: string;\n readonly icon?: IRtIcon.Name;\n /**\n * Имя Material вместо значка кита: рисуется так же, как вход `glyph` у `rt-icon` — парой из\n * перечня кита или лигатурой шрифта. Значок кита, заданный рядом, сильнее.\n */\n readonly glyph?: string;\n readonly look?: IRtActionBar.Look;\n readonly run?: () => void;\n readonly menu?: readonly IRtActionBar.Action[];\n }\n\n /**\n * Настройка полосы целиком. Счёт приходит парой: сколько выбрано и сколько\n * всего. Полоса ничего из этого не считает — ей дают числа.\n */\n export interface Config {\n readonly selected: number;\n readonly total: number;\n readonly actions: readonly IRtActionBar.Action[];\n }\n}\n\n/**\n * Сколько полоса держится в разметке после закрытия — ровно длительность ухода\n * из стилей.\n *\n * Число живёт здесь, а не только в правиле стиля: разметку снимает держатель, и,\n * разойдясь с правилом, он обрывает уход на полпути. Держателю и стилям нужно\n * одно и то же число, поэтому оно объявлено рядом с договором, а не в одном из них.\n */\nexport const RT_ACTION_BAR_LEAVE_MS: number = 300;\n","import { Injectable, Signal, WritableSignal, signal } from '@angular/core';\n\nimport { IRtActionBar } from './rt-action-bar.model';\n\nconst EMPTY_CONFIG: IRtActionBar.Config = { selected: 0, total: 0, actions: [] };\n\n/**\n * Настройка полосы массовых действий: держатель её читает, список — пишет.\n *\n * Служба без корня намеренно. Тот, кто отмечает строки, и тот, кто рисует полосу,\n * стоят на разной глубине одного экрана, и передавать настройку вниз через всё,\n * что между ними, значит рассказать о полосе каждому из них. Потребитель\n * объявляет службу на своём уровне — там, где у него живёт список.\n */\n@Injectable()\nexport class RtActionBarService {\n readonly #config: WritableSignal<IRtActionBar.Config> = signal<IRtActionBar.Config>(EMPTY_CONFIG);\n\n public readonly config: Signal<IRtActionBar.Config> = this.#config.asReadonly();\n\n /** Список действий. Счёт не трогается: он приходит своим вызовом. */\n public setActions(actions: readonly IRtActionBar.Action[]): void {\n this.#config.update((config: IRtActionBar.Config): IRtActionBar.Config => ({ ...config, actions }));\n }\n\n /** Счёт выбранного. Полоса открывается именно им. */\n public setCounts(selected: number, total: number): void {\n this.#config.update((config: IRtActionBar.Config): IRtActionBar.Config => ({ ...config, selected, total }));\n }\n\n /** Отпустить выбранное: счёт обнуляется, список действий остаётся. */\n public clearSelection(): void {\n this.#config.update((config: IRtActionBar.Config): IRtActionBar.Config => ({ ...config, selected: 0, total: 0 }));\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n InputSignal,\n Signal,\n ViewEncapsulation,\n WritableSignal,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\n\nimport { RtActionBarComponent } from './rt-action-bar.component';\nimport { IRtActionBar, RT_ACTION_BAR_LEAVE_MS } from './rt-action-bar.model';\nimport { RtActionBarService } from './rt-action-bar.service';\n\nconst BEM_BLOCK: string = 'rt-action-bar-holder';\n\n/**\n * Держатель полосы массовых действий: решает, стоит ли она в разметке, и прикалывает\n * её над страницей. Настройку читает у службы, которую потребитель объявил на своём\n * уровне — там, где у него живёт список.\n *\n * Полоса открывается счётом выбранного, а не своим признаком: два источника одного\n * признака расходятся молча, и признак, оставшийся поднятым над опустевшим выбором,\n * держал бы полосу над страницей, где ничего не выбрано.\n *\n * После закрытия полоса остаётся в разметке ровно на длительность ухода — число одно\n * и лежит в договоре рядом. Разойдясь с правилом стиля, держатель обрывал бы уход на\n * полпути.\n */\n@Component({\n selector: 'rt-action-bar-holder',\n templateUrl: './rt-action-bar-holder.component.html',\n styleUrl: './rt-action-bar-holder.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [RtActionBarComponent, BlockDirective, ElemDirective, ModDirective],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtActionBarHolderComponent {\n readonly #service: RtActionBarService = inject(RtActionBarService);\n readonly #destroyRef: DestroyRef = inject(DestroyRef);\n\n /** Уходит ли полоса прямо сейчас: разметка держит её, пока правило стиля не доиграет. */\n readonly #leaving: WritableSignal<boolean> = signal<boolean>(false);\n\n #leaveTimer: ReturnType<typeof setTimeout> | null = null;\n\n /**\n * Была ли полоса открыта до этой перемены. Без этого признака уходу не с чего начаться:\n * к минуте, когда выбранное обнулилось, и «открыта», и «стоит в разметке» уже ложь, так\n * что условие по ним не срабатывает никогда. В первом ките оно написано именно так, и\n * уход там не заводится вовсе — образец прочитан, а не перенесён.\n */\n #wasOpened: boolean = false;\n\n protected readonly config: Signal<IRtActionBar.Config> = this.#service.config;\n\n /** Выбрано ли что-нибудь: этим полоса и открывается. */\n protected readonly opened: Signal<boolean> = computed((): boolean => this.config().selected > 0);\n\n /** Стоит ли полоса в разметке: она остаётся в ней и на время ухода. */\n protected readonly shown: Signal<boolean> = computed((): boolean => this.opened() || this.#leaving());\n\n protected readonly leaving: Signal<boolean> = this.#leaving.asReadonly();\n\n /** Значок кнопки, закрывающей полосу, — уходит в саму полосу. */\n public readonly closeIcon: InputSignal<IRtIcon.Name> = input<IRtIcon.Name>('close');\n\n constructor() {\n effect((): void => {\n const opened: boolean = this.opened();\n\n untracked((): void => {\n this.#clearLeaveTimer();\n\n if (opened) {\n this.#wasOpened = true;\n this.#leaving.set(false);\n\n return;\n }\n\n if (this.#wasOpened) {\n this.#wasOpened = false;\n this.#startLeaving();\n }\n });\n });\n\n this.#destroyRef.onDestroy((): void => this.#clearLeaveTimer());\n }\n\n /** Крестик сообщает наружу; выбранное отпускает служба, которой список и владеет. */\n protected onClosed(): void {\n this.#service.clearSelection();\n }\n\n /** Полоса остаётся в разметке на время ухода и снимается по его концу. */\n #startLeaving(): void {\n this.#leaving.set(true);\n this.#leaveTimer = setTimeout((): void => {\n this.#leaving.set(false);\n this.#leaveTimer = null;\n }, RT_ACTION_BAR_LEAVE_MS);\n }\n\n #clearLeaveTimer(): void {\n if (this.#leaveTimer !== null) {\n clearTimeout(this.#leaveTimer);\n this.#leaveTimer = null;\n }\n }\n}\n","<ng-container rtBlock=\"rt-action-bar-holder\">\n @if (shown()) {\n <rt-action-bar\n rtElem=\"bar\"\n qa-dataid=\"action-bar-holder-bar\"\n [rtMod]=\"{ leaving: leaving() }\"\n [config]=\"config()\"\n [closeIcon]=\"closeIcon()\"\n (closed)=\"onClosed()\" />\n }\n</ng-container>\n"],"mappings":"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"}
@@ -180,7 +180,8 @@ var RtAiRunStatusComponent = class RtAiRunStatusComponent {
180
180
  "rtTooltipPlacement",
181
181
  "rtTooltipShowDelay",
182
182
  "rtTooltipWhenTruncated",
183
- "rtTooltipHideOnClick"
183
+ "rtTooltipHideOnClick",
184
+ "rtTooltipShowOnTap"
184
185
  ],
185
186
  exportAs: ["rtTooltip"]
186
187
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rt-tools-ui-kit-v2-ai-run-status.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/ai-run-status/rt-ai-run-status.component.ts","../../../projects/ui-kit-v2/src/lib/components/ai-run-status/rt-ai-run-status.component.html"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n input,\n InputSignal,\n model,\n ModelSignal,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { IRtIcon, rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtSpinnerComponent } from '@rt-tools/ui-kit-v2/spinner';\nimport { IRtTimeline, RtTimelineComponent } from '@rt-tools/ui-kit-v2/timeline';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\n\nimport { IRtAiRunStatus } from './rt-ai-run-status.model';\n\nconst BEM_BLOCK: string = 'rt-ai-run-status';\n\n/** Значок и его цвет по состоянию; у `running` значка нет — на его месте крутилка. */\nconst MARKS: Readonly<Record<Exclude<IRtAiRunStatus.State, 'running'>, { name: IRtIcon.Name; color: IRtIcon.Color }>> = {\n done: { name: 'check-circle', color: 'success' },\n stopped: { name: 'times-circle', color: 'muted' },\n failed: { name: 'exclamation-circle', color: 'danger' },\n};\n\nlet runStatusIdSeed: number = 0;\n\nfunction nextRunStatusId(): number {\n runStatusIdSeed += 1;\n return runStatusIdSeed;\n}\n\n/**\n * Строка хода работы ИИ-ассистента: значок состояния, подпись текущего шага или итога, мета\n * (время, число шагов) и раскрытие списка пройденных шагов. Пока модель работает, по подписи\n * бежит блик; при `prefers-reduced-motion` подпись стоит ровным цветом.\n *\n * Компонент презентационный: состояние, подпись и шаги приходят готовыми, разбор потока\n * событий модели остаётся в приложении.\n */\n@Component({\n selector: 'rt-ai-run-status',\n templateUrl: './rt-ai-run-status.component.html',\n styleUrl: './rt-ai-run-status.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // angular\n NgTemplateOutlet,\n\n // standalone components / directives\n BlockDirective,\n ElemDirective,\n ModDirective,\n RtIconComponent,\n RtSpinnerComponent,\n RtTimelineComponent,\n RtTooltipDirective,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtAiRunStatusComponent {\n readonly #t_aiShowSteps: Signal<string> = rtKitLabel('aiShowSteps');\n readonly #t_aiHideSteps: Signal<string> = rtKitLabel('aiHideSteps');\n\n protected readonly stepsId: string = `rt-ai-run-status-steps-${nextRunStatusId()}`;\n\n protected readonly hasSteps: Signal<boolean> = computed((): boolean => this.steps().length > 0);\n\n protected readonly isOpen: Signal<boolean> = computed((): boolean => this.hasSteps() && this.expanded());\n\n protected readonly mark: Signal<{ name: IRtIcon.Name; color: IRtIcon.Color } | null> = computed(\n (): { name: IRtIcon.Name; color: IRtIcon.Color } | null => {\n const state: IRtAiRunStatus.State = this.state();\n return state === 'running' ? null : MARKS[state];\n }\n );\n\n protected readonly toggleLabel: Signal<string> = computed((): string =>\n this.isOpen() ? this.#t_aiHideSteps() : this.#t_aiShowSteps()\n );\n\n public readonly state: InputSignal<IRtAiRunStatus.State> = input.required<IRtAiRunStatus.State>();\n\n /** Подпись: текущий шаг, пока модель работает, или итог — «Worked for 31s». */\n public readonly label: InputSignal<string> = input.required<string>();\n\n /** Вторичная строка справа от подписи: время шага или число шагов. Пусто — не рисуется. */\n public readonly meta: InputSignal<string> = input<string>('');\n\n /** Пройденные шаги. Пустой список — строку нельзя раскрыть. */\n public readonly steps: InputSignal<readonly IRtTimeline.Step[]> = input<readonly IRtTimeline.Step[]>([]);\n\n /** Раскрыт ли список шагов. */\n public readonly expanded: ModelSignal<boolean> = model<boolean>(false);\n\n protected onToggle(): void {\n this.expanded.set(!this.expanded());\n }\n}\n","<div rtBlock=\"rt-ai-run-status\" qa-dataid=\"ai-run-status\" [attr.data-state]=\"state()\" [rtMod]=\"{ state: state(), open: isOpen() }\">\n <ng-template #head>\n <span rtElem=\"mark\" aria-hidden=\"true\">\n @if (mark(); as m) {\n <rt-icon size=\"sm\" [name]=\"m.name\" [color]=\"m.color\" />\n } @else {\n <rt-spinner appearance=\"arc\" [diameter]=\"16\" />\n }\n </span>\n <span rtElem=\"label\" qa-dataid=\"ai-run-status-label\" [rtMod]=\"{ state: state() }\">{{ label() }}</span>\n @if (meta()) {\n <span rtElem=\"meta\" qa-dataid=\"ai-run-status-meta\">{{ meta() }}</span>\n }\n </ng-template>\n\n @if (hasSteps()) {\n <button\n rtElem=\"row\"\n type=\"button\"\n qa-dataid=\"ai-run-status-toggle\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"stepsId\"\n [rtTooltip]=\"toggleLabel()\"\n (click)=\"onToggle()\">\n <ng-container [ngTemplateOutlet]=\"head\" />\n <rt-icon rtElem=\"chevron\" size=\"sm\" color=\"muted\" [name]=\"isOpen() ? 'chevron-up' : 'chevron-down'\" />\n </button>\n } @else {\n <div rtElem=\"row\" role=\"status\" qa-dataid=\"ai-run-status-row\">\n <ng-container [ngTemplateOutlet]=\"head\" />\n </div>\n }\n\n @if (isOpen()) {\n <rt-timeline rtElem=\"steps\" qa-dataid=\"ai-run-status-steps\" [id]=\"stepsId\" [steps]=\"steps()\" />\n }\n</div>\n"],"mappings":";;;;;;;;;AAuBA,MAAM,YAAoB;AAG1B,MAAM,QAAkH;CACpH,MAAM;EAAE,MAAM;EAAgB,OAAO;CAAS;CAC9C,SAAS;EAAE,MAAM;EAAgB,OAAO;CAAO;CAC/C,QAAQ;EAAE,MAAM;EAAsB,OAAO;CAAQ;AACxD;AAED,IAAI,kBAA0B;AAE9B,SAAS,kBAAe;CACpB,mBAAmB;CACnB,OAAO;AACX;AAiCA,IAAa,yBAAb,MAAa,uBAAsB;CAvBnC,cAAA;EAwBa,KAAA,iBAAiC,WAAW,aAAa;EACzD,KAAA,iBAAiC,WAAW,aAAa;EAE/C,KAAA,UAAkB,0BAA0B,gBAAe;EAE3D,KAAA,WAA4B,eAAwB,KAAK,MAAK,CAAE,CAAC,SAAS,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;EAE5E,KAAA,SAA0B,eAAwB,KAAK,SAAQ,KAAM,KAAK,SAAQ,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;EAErF,KAAA,OAAoE,eACzB;GACtD,MAAM,QAA8B,KAAK,MAAK;GAC9C,OAAO,UAAU,YAAY,OAAO,MAAM;EAC9C,GACH,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;EAEkB,KAAA,cAA8B,eAC7C,KAAK,OAAM,IAAK,KAAK,eAAc,IAAK,KAAK,eAAc,GAC9D,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;EAEe,KAAA,QAA2C,MAAM,SAAgC,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;EAGjF,KAAA,QAA6B,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;EAGrD,KAAA,OAA4B,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;EAG7C,KAAA,QAAkD,MAAmC,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;EAGxF,KAAA,WAAiC,MAAe,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CAKzE;CArCY;CACA;CAiCC,WAAQ;EACd,KAAK,SAAS,IAAI,CAAC,KAAK,SAAQ,CAAE;CACtC;CArCS;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAsB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAAtB;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAAsB,cAAA;GAAA,UAAA;GAAA,QAAA;IAAA,OAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,OAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,MAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,OAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,UAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;GAAA;GAAA,SAAA,EAAA,UAAA,iBAAA;GAAA,MAAA,EAAA,gBAAA,mBAAA;GAAA,UAAA;GAAA,UCtEnC;GAqCA,QAAA,CAAA,62GAAA;GAAA,cAAA;IAAA;KAAA,MAAA;KAAA,MDkBQ;KAAgB,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;KAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MAGhB;KAAc,UAAA;KAAA,QAAA,CAAA,OAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACd;KAAa,UAAA;KAAA,QAAA,CAAA,OAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACb;KAAY,UAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACZ;KAAe,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACf;KAAkB,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MAClB;KAAmB,UAAA;KAAA,QAAA,CAAA,OAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACnB;KAAkB,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;KAAA,UAAA,CAAA,WAAA;IAAA;GAAA;GAAA,iBAAA,GAAA,wBAAA;GAAA,eAAA,GAAA,kBAAA;EAAA,CAAA;CAAA;;AAMb,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAsB,YAAA,CAAA;EAvBlC,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAkB,iBAGX,wBAAwB;GAAM,eAChC,kBAAkB;GAAI,SAC5B;IAEL;IAGA;IACA;IACA;IACA;IACA;IACA;IACA;GACH;GAAA,MACK,EACF,OAAO,UACV;GAAA,UAAA;GAAA,QAAA,CAAA,62GAAA;EAAA,CAAA"}
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-ai-run-status.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/ai-run-status/rt-ai-run-status.component.ts","../../../projects/ui-kit-v2/src/lib/components/ai-run-status/rt-ai-run-status.component.html"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n input,\n InputSignal,\n model,\n ModelSignal,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { IRtIcon, rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtSpinnerComponent } from '@rt-tools/ui-kit-v2/spinner';\nimport { IRtTimeline, RtTimelineComponent } from '@rt-tools/ui-kit-v2/timeline';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\n\nimport { IRtAiRunStatus } from './rt-ai-run-status.model';\n\nconst BEM_BLOCK: string = 'rt-ai-run-status';\n\n/** Значок и его цвет по состоянию; у `running` значка нет — на его месте крутилка. */\nconst MARKS: Readonly<Record<Exclude<IRtAiRunStatus.State, 'running'>, { name: IRtIcon.Name; color: IRtIcon.Color }>> = {\n done: { name: 'check-circle', color: 'success' },\n stopped: { name: 'times-circle', color: 'muted' },\n failed: { name: 'exclamation-circle', color: 'danger' },\n};\n\nlet runStatusIdSeed: number = 0;\n\nfunction nextRunStatusId(): number {\n runStatusIdSeed += 1;\n return runStatusIdSeed;\n}\n\n/**\n * Строка хода работы ИИ-ассистента: значок состояния, подпись текущего шага или итога, мета\n * (время, число шагов) и раскрытие списка пройденных шагов. Пока модель работает, по подписи\n * бежит блик; при `prefers-reduced-motion` подпись стоит ровным цветом.\n *\n * Компонент презентационный: состояние, подпись и шаги приходят готовыми, разбор потока\n * событий модели остаётся в приложении.\n */\n@Component({\n selector: 'rt-ai-run-status',\n templateUrl: './rt-ai-run-status.component.html',\n styleUrl: './rt-ai-run-status.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // angular\n NgTemplateOutlet,\n\n // standalone components / directives\n BlockDirective,\n ElemDirective,\n ModDirective,\n RtIconComponent,\n RtSpinnerComponent,\n RtTimelineComponent,\n RtTooltipDirective,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtAiRunStatusComponent {\n readonly #t_aiShowSteps: Signal<string> = rtKitLabel('aiShowSteps');\n readonly #t_aiHideSteps: Signal<string> = rtKitLabel('aiHideSteps');\n\n protected readonly stepsId: string = `rt-ai-run-status-steps-${nextRunStatusId()}`;\n\n protected readonly hasSteps: Signal<boolean> = computed((): boolean => this.steps().length > 0);\n\n protected readonly isOpen: Signal<boolean> = computed((): boolean => this.hasSteps() && this.expanded());\n\n protected readonly mark: Signal<{ name: IRtIcon.Name; color: IRtIcon.Color } | null> = computed(\n (): { name: IRtIcon.Name; color: IRtIcon.Color } | null => {\n const state: IRtAiRunStatus.State = this.state();\n return state === 'running' ? null : MARKS[state];\n }\n );\n\n protected readonly toggleLabel: Signal<string> = computed((): string =>\n this.isOpen() ? this.#t_aiHideSteps() : this.#t_aiShowSteps()\n );\n\n public readonly state: InputSignal<IRtAiRunStatus.State> = input.required<IRtAiRunStatus.State>();\n\n /** Подпись: текущий шаг, пока модель работает, или итог — «Worked for 31s». */\n public readonly label: InputSignal<string> = input.required<string>();\n\n /** Вторичная строка справа от подписи: время шага или число шагов. Пусто — не рисуется. */\n public readonly meta: InputSignal<string> = input<string>('');\n\n /** Пройденные шаги. Пустой список — строку нельзя раскрыть. */\n public readonly steps: InputSignal<readonly IRtTimeline.Step[]> = input<readonly IRtTimeline.Step[]>([]);\n\n /** Раскрыт ли список шагов. */\n public readonly expanded: ModelSignal<boolean> = model<boolean>(false);\n\n protected onToggle(): void {\n this.expanded.set(!this.expanded());\n }\n}\n","<div rtBlock=\"rt-ai-run-status\" qa-dataid=\"ai-run-status\" [attr.data-state]=\"state()\" [rtMod]=\"{ state: state(), open: isOpen() }\">\n <ng-template #head>\n <span rtElem=\"mark\" aria-hidden=\"true\">\n @if (mark(); as m) {\n <rt-icon size=\"sm\" [name]=\"m.name\" [color]=\"m.color\" />\n } @else {\n <rt-spinner appearance=\"arc\" [diameter]=\"16\" />\n }\n </span>\n <span rtElem=\"label\" qa-dataid=\"ai-run-status-label\" [rtMod]=\"{ state: state() }\">{{ label() }}</span>\n @if (meta()) {\n <span rtElem=\"meta\" qa-dataid=\"ai-run-status-meta\">{{ meta() }}</span>\n }\n </ng-template>\n\n @if (hasSteps()) {\n <button\n rtElem=\"row\"\n type=\"button\"\n qa-dataid=\"ai-run-status-toggle\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"stepsId\"\n [rtTooltip]=\"toggleLabel()\"\n (click)=\"onToggle()\">\n <ng-container [ngTemplateOutlet]=\"head\" />\n <rt-icon rtElem=\"chevron\" size=\"sm\" color=\"muted\" [name]=\"isOpen() ? 'chevron-up' : 'chevron-down'\" />\n </button>\n } @else {\n <div rtElem=\"row\" role=\"status\" qa-dataid=\"ai-run-status-row\">\n <ng-container [ngTemplateOutlet]=\"head\" />\n </div>\n }\n\n @if (isOpen()) {\n <rt-timeline rtElem=\"steps\" qa-dataid=\"ai-run-status-steps\" [id]=\"stepsId\" [steps]=\"steps()\" />\n }\n</div>\n"],"mappings":"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"}
@@ -344,6 +344,7 @@ var RtAutocompleteComponent = class RtAutocompleteComponent extends RtFormContro
344
344
  "rtPopoverFitViewport",
345
345
  "rtPopoverContext",
346
346
  "rtPopoverPanelClass",
347
+ "rtPopoverBackdropClass",
347
348
  "rtPopoverDisabled",
348
349
  "rtPopoverOffsetY",
349
350
  "rtPopoverOffsetX",
@@ -1 +1 @@
1
- {"version":3,"file":"rt-tools-ui-kit-v2-autocomplete.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/autocomplete/rt-autocomplete.component.ts","../../../projects/ui-kit-v2/src/lib/components/autocomplete/rt-autocomplete.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n computed,\n forwardRef,\n inject,\n input,\n output,\n signal,\n viewChild,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n TemplateRef,\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 { RtFormControlBase } from '@rt-tools/ui-kit-v2/form-control';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtSpinnerComponent } from '@rt-tools/ui-kit-v2/spinner';\nimport { RtPopoverDirective } from '@rt-tools/ui-kit-v2/popover';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { RtOptionList, TRtOptionListAction } from '@rt-tools/ui-kit-v2/core';\nimport { IRtAutocomplete } from './rt-autocomplete.model';\n\n/** Сколько точек до дна панели уже считается концом списка. */\nconst END_THRESHOLD_PX: number = 8;\n\nconst BEM_BLOCK: string = 'rt-autocomplete';\n\nlet panelIdSeed: number = 0;\n\nfunction nextPanelId(): number {\n panelIdSeed += 1;\n return panelIdSeed;\n}\n\n/**\n * Typeahead/autocomplete с server-side filter через `(complete)` event.\n *\n * Panel рендерится через CDK Overlay (`[rtPopover]` trigger=\"manual\" на input'е)\n * — открывается по набору текста (не click/hover), не обрезается overflow.\n * Подписчик получает `(complete)` с текущей строкой и сам грузит подсказки.\n *\n * CVA через общий `RtFormControlBase`. Generic `TItem` — тип подсказки и\n * selected value. Крестик (`clearable`) виден при непустом тексте — очищает и\n * текст, и выбранный объект. Keyboard-nav (activedescendant): ArrowUp/Down —\n * highlight, Enter — выбрать активную, Escape — закрыть. Home/End — deferred.\n */\n@Component({\n selector: 'rt-autocomplete',\n templateUrl: './rt-autocomplete.component.html',\n styleUrl: './rt-autocomplete.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n NgTemplateOutlet,\n\n // standalone components / directives\n RtIconButtonComponent,\n RtIconComponent,\n RtPopoverDirective,\n RtSpinnerComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n providers: [\n // Алиас базового токена — для contentChild(RtFormControlBase) в rt-field.\n { provide: RtFormControlBase, useExisting: forwardRef(() => RtAutocompleteComponent) },\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n '[class.rt-autocomplete--open]': 'isOpen()',\n '[class.rt-autocomplete--disabled]': 'isDisabled()',\n '[class.rt-autocomplete--readonly]': 'isReadonly()',\n '[class.rt-autocomplete--invalid]': 'isInvalid()',\n '[class.rt-autocomplete--borderless]': '!bordered()',\n '[class.rt-autocomplete--size--sm]': \"size() === 'sm'\",\n '[class.rt-autocomplete--size--lg]': \"size() === 'lg'\",\n },\n})\nexport class RtAutocompleteComponent<TItem> extends RtFormControlBase<TItem | null> {\n /** Длина списка, на которой конец уже сообщён: прокрутка у дна до новой страницы его не повторяет. */\n #endReportedAt: number = -1;\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly panelId: string = `rt-autocomplete-panel-${nextPanelId()}`;\n\n protected readonly popover: Signal<RtPopoverDirective> = viewChild.required(RtPopoverDirective);\n\n protected readonly fieldEl: Signal<ElementRef<HTMLInputElement> | undefined> = viewChild<ElementRef<HTMLInputElement>>('fieldEl');\n\n protected readonly inputText: WritableSignal<string> = signal<string>('');\n\n protected readonly isOpen: Signal<boolean> = computed((): boolean => this.popover().isOpen());\n\n /** Клавиатура списка: подсветка, клавиши открытия, id для `aria-activedescendant`, прокрутка к опции. */\n protected readonly optionList: RtOptionList = new RtOptionList({\n panelId: (): string => this.panelId,\n isOpen: (): boolean => this.isOpen(),\n count: (): number => this.suggestions().length,\n chooseKeys: new Set<string>(['Enter']),\n sideKeys: false,\n edgeKeys: false,\n });\n\n protected readonly activeIndex: WritableSignal<number> = this.optionList.activeIndex;\n\n /** Идентификатор подсвеченной опции — тот же, что уходит в `aria-activedescendant`. */\n protected readonly activeOptionId: Signal<string | null> = this.optionList.activeOptionId;\n\n protected readonly hasValue: Signal<boolean> = computed((): boolean => this.inputText() !== '');\n\n public readonly displayText: Signal<string> = computed((): string => this.displayWith()(this.value()));\n\n public readonly suggestions: InputSignal<ReadonlyArray<TItem>> = input<ReadonlyArray<TItem>>([]);\n\n public readonly displayWith: InputSignal<(item: TItem | null) => string> = input<(item: TItem | null) => string>(\n (item: TItem | null): string => String(item ?? '')\n );\n\n public readonly placeholder: InputSignal<string> = input<string>('');\n public readonly minLength: InputSignal<number> = input<number>(1);\n\n /** Префикс-иконка слева в поле (например, `map` для поиска). */\n public readonly iconLeft: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n public readonly openOnFocus: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly itemTemplate: InputSignal<TemplateRef<{ $implicit: TItem }> | null> = input<TemplateRef<{ $implicit: TItem }> | null>(\n null\n );\n\n /**\n * Подсказки грузятся: в панели строка со спиннером — вместо пустого результата при первой загрузке\n * и под списком при подгрузке следующей страницы.\n */\n public readonly loading: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Свой текст пустого результата; `null` — подпись кита `uiNothingFound`. */\n public readonly emptyText: InputSignal<string | null> = input<string | null>(null);\n\n /** Своя разметка пустого результата; сильнее `emptyText`. Обстановка — набранная строка. */\n public readonly emptyTemplate: InputSignal<TemplateRef<{ $implicit: string }> | null> = input<TemplateRef<{\n $implicit: string;\n }> | null>(null);\n\n /**\n * Панель долистали до конца — пора просить следующую страницу. Не приходит, пока идёт загрузка, и\n * приходит один раз на каждую длину списка: прокрутка у дна до прихода страницы её не повторяет.\n */\n public readonly scrolledToEnd: OutputEmitterRef<void> = output<void>();\n\n public readonly complete: OutputEmitterRef<IRtAutocomplete.CompleteEvent> = output<IRtAutocomplete.CompleteEvent>();\n\n public readonly itemSelect: OutputEmitterRef<TItem> = output<TItem>();\n\n public override writeValue(value: TItem | null): void {\n super.writeValue(value);\n this.inputText.set(this.displayWith()(this.value()));\n }\n\n public override setDisabledState(disabled: boolean): void {\n super.setDisabledState(disabled);\n if (disabled) {\n this.popover().close();\n }\n }\n\n protected getEmptyValue(): TItem | null {\n return null;\n }\n\n protected focusAfterClear(): void {\n this.fieldEl()?.nativeElement.focus();\n }\n\n protected override clearValue(): void {\n super.clearValue();\n this.inputText.set('');\n this.#endReportedAt = -1;\n }\n\n protected onInput(event: Event): void {\n const target: HTMLInputElement = event.target as HTMLInputElement;\n const query: string = target.value;\n this.inputText.set(query);\n this.activeIndex.set(-1);\n // Новый запрос — новый список: его первая страница той же длины, что прошлый список, снова\n // сообщает о дне, иначе подгрузка нового запроса не началась бы вовсе.\n this.#endReportedAt = -1;\n if (query.length >= this.minLength()) {\n this.complete.emit({ query, originalEvent: event });\n this.popover().open();\n } else {\n this.popover().close();\n }\n }\n\n protected onFocus(): void {\n if (!this.openOnFocus()) {\n return;\n }\n this.complete.emit({ query: this.inputText(), originalEvent: new Event('focus') });\n this.popover().open();\n }\n\n protected onBlur(): void {\n this.markTouched();\n }\n\n /** Прокрутка панели: у дна — сообщить, что пора следующая страница. */\n protected onPanelScroll(event: Event): void {\n const panel: HTMLElement = event.target as HTMLElement;\n const atEnd: boolean = panel.scrollTop + panel.clientHeight >= panel.scrollHeight - END_THRESHOLD_PX;\n const length: number = this.suggestions().length;\n if (!atEnd || this.loading() || length === this.#endReportedAt) {\n return;\n }\n this.#endReportedAt = length;\n this.scrolledToEnd.emit();\n }\n\n protected onClosed(): void {\n this.activeIndex.set(-1);\n }\n\n protected onSelect(item: TItem): void {\n this.value.set(item);\n this.inputText.set(this.displayWith()(item));\n this.emitChange(item);\n this.itemSelect.emit(item);\n this.popover().close();\n }\n\n protected onInputKeydown(event: KeyboardEvent): void {\n if (this.isDisabled()) {\n return;\n }\n const key: string = event.key;\n if (!this.isOpen()) {\n return;\n }\n const action: TRtOptionListAction = this.optionList.actionOf(key);\n if (action === 'none' || action === 'side') {\n return;\n }\n event.preventDefault();\n switch (action) {\n case 'next':\n this.optionList.move(1);\n break;\n case 'previous':\n this.optionList.move(-1);\n break;\n case 'choose':\n this.#selectActive();\n break;\n case 'close':\n // Escape закрывает один слой: панель. Без остановки событие всплывает до document,\n // и оверлей под панелью — боковая панель, окно — закрывается вместе с ней.\n event.stopPropagation();\n this.popover().close();\n break;\n }\n }\n\n #selectActive(): void {\n const items: ReadonlyArray<TItem> = this.suggestions();\n const index: number = this.activeIndex();\n if (index >= 0 && index < items.length) {\n this.onSelect(items[index]);\n }\n }\n}\n","<ng-container rtBlock=\"rt-autocomplete\">\n @if (isReadonly()) {\n <span rtElem=\"readonly\" qa-dataid=\"autocomplete-readonly\" [rtMod]=\"{ empty: !displayText() }\">{{ displayText() || '—' }}</span>\n }\n <div rtElem=\"field\" rtPopoverTrigger=\"manual\" rtPopoverWidth=\"trigger\" [rtPopover]=\"panelTpl\" (rtPopoverClosed)=\"onClosed()\">\n @if (iconLeft(); as left) {\n <rt-icon rtElem=\"icon-left\" size=\"sm\" color=\"muted\" [name]=\"left\" />\n }\n <input\n #fieldEl\n rtElem=\"input\"\n qa-dataid=\"autocomplete-input\"\n type=\"text\"\n autocomplete=\"off\"\n role=\"combobox\"\n [attr.id]=\"effectiveControlId()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-invalid]=\"isInvalid() || null\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-activedescendant]=\"activeOptionId()\"\n [placeholder]=\"placeholder()\"\n [value]=\"inputText()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onInputKeydown($event)\" />\n @if (showClearButton()) {\n <rt-icon-button\n rtElem=\"clear\"\n qa-dataid=\"autocomplete-clear\"\n icon=\"ico-close\"\n size=\"sm\"\n variant=\"ghost\"\n iconColor=\"muted\"\n [ariaLabel]=\"t().uiClear\"\n [tabIndex]=\"-1\"\n (clicked)=\"clear($event)\" />\n }\n </div>\n\n <ng-template #panelTpl>\n <!--\n Опции выбираются мышью через (click); keyboard-nav — на input'е\n (activedescendant), опции не focusable индивидуально.\n -->\n <!-- eslint-disable @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <ul\n rtElem=\"panel\"\n qa-dataid=\"autocomplete-panel\"\n role=\"listbox\"\n [id]=\"panelId\"\n [attr.aria-busy]=\"loading() || null\"\n (scroll)=\"onPanelScroll($event)\">\n @for (item of suggestions(); track $index; let i = $index) {\n <li\n rtElem=\"option\"\n qa-dataid=\"autocomplete-option\"\n role=\"option\"\n [id]=\"panelId + '-opt-' + i\"\n [rtMod]=\"{ active: i === activeIndex() }\"\n [attr.aria-selected]=\"item === value()\"\n (click)=\"onSelect(item)\">\n @if (itemTemplate(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: item }\" />\n } @else {\n {{ displayWith()(item) }}\n }\n </li>\n } @empty {\n @if (!loading()) {\n <li rtElem=\"empty\" qa-dataid=\"autocomplete-empty\">\n @if (emptyTemplate(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: inputText() }\" />\n } @else {\n {{ emptyText() ?? t().uiNothingFound }}\n }\n </li>\n }\n }\n @if (loading()) {\n <li rtElem=\"loading\" qa-dataid=\"autocomplete-loading\" aria-hidden=\"true\">\n <rt-spinner [diameter]=\"20\" />\n </li>\n }\n </ul>\n </ng-template>\n</ng-container>\n"],"mappings":"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"}
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-autocomplete.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/autocomplete/rt-autocomplete.component.ts","../../../projects/ui-kit-v2/src/lib/components/autocomplete/rt-autocomplete.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n computed,\n forwardRef,\n inject,\n input,\n output,\n signal,\n viewChild,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n TemplateRef,\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 { RtFormControlBase } from '@rt-tools/ui-kit-v2/form-control';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtSpinnerComponent } from '@rt-tools/ui-kit-v2/spinner';\nimport { RtPopoverDirective } from '@rt-tools/ui-kit-v2/popover';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { RtOptionList, TRtOptionListAction } from '@rt-tools/ui-kit-v2/core';\nimport { IRtAutocomplete } from './rt-autocomplete.model';\n\n/** Сколько точек до дна панели уже считается концом списка. */\nconst END_THRESHOLD_PX: number = 8;\n\nconst BEM_BLOCK: string = 'rt-autocomplete';\n\nlet panelIdSeed: number = 0;\n\nfunction nextPanelId(): number {\n panelIdSeed += 1;\n return panelIdSeed;\n}\n\n/**\n * Typeahead/autocomplete с server-side filter через `(complete)` event.\n *\n * Panel рендерится через CDK Overlay (`[rtPopover]` trigger=\"manual\" на input'е)\n * — открывается по набору текста (не click/hover), не обрезается overflow.\n * Подписчик получает `(complete)` с текущей строкой и сам грузит подсказки.\n *\n * CVA через общий `RtFormControlBase`. Generic `TItem` — тип подсказки и\n * selected value. Крестик (`clearable`) виден при непустом тексте — очищает и\n * текст, и выбранный объект. Keyboard-nav (activedescendant): ArrowUp/Down —\n * highlight, Enter — выбрать активную, Escape — закрыть. Home/End — deferred.\n */\n@Component({\n selector: 'rt-autocomplete',\n templateUrl: './rt-autocomplete.component.html',\n styleUrl: './rt-autocomplete.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n NgTemplateOutlet,\n\n // standalone components / directives\n RtIconButtonComponent,\n RtIconComponent,\n RtPopoverDirective,\n RtSpinnerComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n providers: [\n // Алиас базового токена — для contentChild(RtFormControlBase) в rt-field.\n { provide: RtFormControlBase, useExisting: forwardRef(() => RtAutocompleteComponent) },\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n '[class.rt-autocomplete--open]': 'isOpen()',\n '[class.rt-autocomplete--disabled]': 'isDisabled()',\n '[class.rt-autocomplete--readonly]': 'isReadonly()',\n '[class.rt-autocomplete--invalid]': 'isInvalid()',\n '[class.rt-autocomplete--borderless]': '!bordered()',\n '[class.rt-autocomplete--size--sm]': \"size() === 'sm'\",\n '[class.rt-autocomplete--size--lg]': \"size() === 'lg'\",\n },\n})\nexport class RtAutocompleteComponent<TItem> extends RtFormControlBase<TItem | null> {\n /** Длина списка, на которой конец уже сообщён: прокрутка у дна до новой страницы его не повторяет. */\n #endReportedAt: number = -1;\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly panelId: string = `rt-autocomplete-panel-${nextPanelId()}`;\n\n protected readonly popover: Signal<RtPopoverDirective> = viewChild.required(RtPopoverDirective);\n\n protected readonly fieldEl: Signal<ElementRef<HTMLInputElement> | undefined> = viewChild<ElementRef<HTMLInputElement>>('fieldEl');\n\n protected readonly inputText: WritableSignal<string> = signal<string>('');\n\n protected readonly isOpen: Signal<boolean> = computed((): boolean => this.popover().isOpen());\n\n /** Клавиатура списка: подсветка, клавиши открытия, id для `aria-activedescendant`, прокрутка к опции. */\n protected readonly optionList: RtOptionList = new RtOptionList({\n panelId: (): string => this.panelId,\n isOpen: (): boolean => this.isOpen(),\n count: (): number => this.suggestions().length,\n chooseKeys: new Set<string>(['Enter']),\n sideKeys: false,\n edgeKeys: false,\n });\n\n protected readonly activeIndex: WritableSignal<number> = this.optionList.activeIndex;\n\n /** Идентификатор подсвеченной опции — тот же, что уходит в `aria-activedescendant`. */\n protected readonly activeOptionId: Signal<string | null> = this.optionList.activeOptionId;\n\n protected readonly hasValue: Signal<boolean> = computed((): boolean => this.inputText() !== '');\n\n public readonly displayText: Signal<string> = computed((): string => this.displayWith()(this.value()));\n\n public readonly suggestions: InputSignal<ReadonlyArray<TItem>> = input<ReadonlyArray<TItem>>([]);\n\n public readonly displayWith: InputSignal<(item: TItem | null) => string> = input<(item: TItem | null) => string>(\n (item: TItem | null): string => String(item ?? '')\n );\n\n public readonly placeholder: InputSignal<string> = input<string>('');\n public readonly minLength: InputSignal<number> = input<number>(1);\n\n /** Префикс-иконка слева в поле (например, `map` для поиска). */\n public readonly iconLeft: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n public readonly openOnFocus: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly itemTemplate: InputSignal<TemplateRef<{ $implicit: TItem }> | null> = input<TemplateRef<{ $implicit: TItem }> | null>(\n null\n );\n\n /**\n * Подсказки грузятся: в панели строка со спиннером — вместо пустого результата при первой загрузке\n * и под списком при подгрузке следующей страницы.\n */\n public readonly loading: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Свой текст пустого результата; `null` — подпись кита `uiNothingFound`. */\n public readonly emptyText: InputSignal<string | null> = input<string | null>(null);\n\n /** Своя разметка пустого результата; сильнее `emptyText`. Обстановка — набранная строка. */\n public readonly emptyTemplate: InputSignal<TemplateRef<{ $implicit: string }> | null> = input<TemplateRef<{\n $implicit: string;\n }> | null>(null);\n\n /**\n * Панель долистали до конца — пора просить следующую страницу. Не приходит, пока идёт загрузка, и\n * приходит один раз на каждую длину списка: прокрутка у дна до прихода страницы её не повторяет.\n */\n public readonly scrolledToEnd: OutputEmitterRef<void> = output<void>();\n\n public readonly complete: OutputEmitterRef<IRtAutocomplete.CompleteEvent> = output<IRtAutocomplete.CompleteEvent>();\n\n public readonly itemSelect: OutputEmitterRef<TItem> = output<TItem>();\n\n public override writeValue(value: TItem | null): void {\n super.writeValue(value);\n this.inputText.set(this.displayWith()(this.value()));\n }\n\n public override setDisabledState(disabled: boolean): void {\n super.setDisabledState(disabled);\n if (disabled) {\n this.popover().close();\n }\n }\n\n protected getEmptyValue(): TItem | null {\n return null;\n }\n\n protected focusAfterClear(): void {\n this.fieldEl()?.nativeElement.focus();\n }\n\n protected override clearValue(): void {\n super.clearValue();\n this.inputText.set('');\n this.#endReportedAt = -1;\n }\n\n protected onInput(event: Event): void {\n const target: HTMLInputElement = event.target as HTMLInputElement;\n const query: string = target.value;\n this.inputText.set(query);\n this.activeIndex.set(-1);\n // Новый запрос — новый список: его первая страница той же длины, что прошлый список, снова\n // сообщает о дне, иначе подгрузка нового запроса не началась бы вовсе.\n this.#endReportedAt = -1;\n if (query.length >= this.minLength()) {\n this.complete.emit({ query, originalEvent: event });\n this.popover().open();\n } else {\n this.popover().close();\n }\n }\n\n protected onFocus(): void {\n if (!this.openOnFocus()) {\n return;\n }\n this.complete.emit({ query: this.inputText(), originalEvent: new Event('focus') });\n this.popover().open();\n }\n\n protected onBlur(): void {\n this.markTouched();\n }\n\n /** Прокрутка панели: у дна — сообщить, что пора следующая страница. */\n protected onPanelScroll(event: Event): void {\n const panel: HTMLElement = event.target as HTMLElement;\n const atEnd: boolean = panel.scrollTop + panel.clientHeight >= panel.scrollHeight - END_THRESHOLD_PX;\n const length: number = this.suggestions().length;\n if (!atEnd || this.loading() || length === this.#endReportedAt) {\n return;\n }\n this.#endReportedAt = length;\n this.scrolledToEnd.emit();\n }\n\n protected onClosed(): void {\n this.activeIndex.set(-1);\n }\n\n protected onSelect(item: TItem): void {\n this.value.set(item);\n this.inputText.set(this.displayWith()(item));\n this.emitChange(item);\n this.itemSelect.emit(item);\n this.popover().close();\n }\n\n protected onInputKeydown(event: KeyboardEvent): void {\n if (this.isDisabled()) {\n return;\n }\n const key: string = event.key;\n if (!this.isOpen()) {\n return;\n }\n const action: TRtOptionListAction = this.optionList.actionOf(key);\n if (action === 'none' || action === 'side') {\n return;\n }\n event.preventDefault();\n switch (action) {\n case 'next':\n this.optionList.move(1);\n break;\n case 'previous':\n this.optionList.move(-1);\n break;\n case 'choose':\n this.#selectActive();\n break;\n case 'close':\n // Escape закрывает один слой: панель. Без остановки событие всплывает до document,\n // и оверлей под панелью — боковая панель, окно — закрывается вместе с ней.\n event.stopPropagation();\n this.popover().close();\n break;\n }\n }\n\n #selectActive(): void {\n const items: ReadonlyArray<TItem> = this.suggestions();\n const index: number = this.activeIndex();\n if (index >= 0 && index < items.length) {\n this.onSelect(items[index]);\n }\n }\n}\n","<ng-container rtBlock=\"rt-autocomplete\">\n @if (isReadonly()) {\n <span rtElem=\"readonly\" qa-dataid=\"autocomplete-readonly\" [rtMod]=\"{ empty: !displayText() }\">{{ displayText() || '—' }}</span>\n }\n <div rtElem=\"field\" rtPopoverTrigger=\"manual\" rtPopoverWidth=\"trigger\" [rtPopover]=\"panelTpl\" (rtPopoverClosed)=\"onClosed()\">\n @if (iconLeft(); as left) {\n <rt-icon rtElem=\"icon-left\" size=\"sm\" color=\"muted\" [name]=\"left\" />\n }\n <input\n #fieldEl\n rtElem=\"input\"\n qa-dataid=\"autocomplete-input\"\n type=\"text\"\n autocomplete=\"off\"\n role=\"combobox\"\n [attr.id]=\"effectiveControlId()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-invalid]=\"isInvalid() || null\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-activedescendant]=\"activeOptionId()\"\n [placeholder]=\"placeholder()\"\n [value]=\"inputText()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onInputKeydown($event)\" />\n @if (showClearButton()) {\n <rt-icon-button\n rtElem=\"clear\"\n qa-dataid=\"autocomplete-clear\"\n icon=\"ico-close\"\n size=\"sm\"\n variant=\"ghost\"\n iconColor=\"muted\"\n [ariaLabel]=\"t().uiClear\"\n [tabIndex]=\"-1\"\n (clicked)=\"clear($event)\" />\n }\n </div>\n\n <ng-template #panelTpl>\n <!--\n Опции выбираются мышью через (click); keyboard-nav — на input'е\n (activedescendant), опции не focusable индивидуально.\n -->\n <!-- eslint-disable @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <ul\n rtElem=\"panel\"\n qa-dataid=\"autocomplete-panel\"\n role=\"listbox\"\n [id]=\"panelId\"\n [attr.aria-busy]=\"loading() || null\"\n (scroll)=\"onPanelScroll($event)\">\n @for (item of suggestions(); track $index; let i = $index) {\n <li\n rtElem=\"option\"\n qa-dataid=\"autocomplete-option\"\n role=\"option\"\n [id]=\"panelId + '-opt-' + i\"\n [rtMod]=\"{ active: i === activeIndex() }\"\n [attr.aria-selected]=\"item === value()\"\n (click)=\"onSelect(item)\">\n @if (itemTemplate(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: item }\" />\n } @else {\n {{ displayWith()(item) }}\n }\n </li>\n } @empty {\n @if (!loading()) {\n <li rtElem=\"empty\" qa-dataid=\"autocomplete-empty\">\n @if (emptyTemplate(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: inputText() }\" />\n } @else {\n {{ emptyText() ?? t().uiNothingFound }}\n }\n </li>\n }\n }\n @if (loading()) {\n <li rtElem=\"loading\" qa-dataid=\"autocomplete-loading\" aria-hidden=\"true\">\n <rt-spinner [diameter]=\"20\" />\n </li>\n }\n </ul>\n </ng-template>\n</ng-container>\n"],"mappings":"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"}
@@ -250,7 +250,8 @@ var RtBreadcrumbsComponent = class RtBreadcrumbsComponent {
250
250
  "rtTooltipPlacement",
251
251
  "rtTooltipShowDelay",
252
252
  "rtTooltipWhenTruncated",
253
- "rtTooltipHideOnClick"
253
+ "rtTooltipHideOnClick",
254
+ "rtTooltipShowOnTap"
254
255
  ],
255
256
  exportAs: ["rtTooltip"]
256
257
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rt-tools-ui-kit-v2-breadcrumbs.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/breadcrumbs/rt-breadcrumbs.logic.ts","../../../projects/ui-kit-v2/src/lib/components/breadcrumbs/rt-breadcrumbs.component.ts","../../../projects/ui-kit-v2/src/lib/components/breadcrumbs/rt-breadcrumbs.component.html"],"sourcesContent":["import { IRtBreadcrumbs } from './rt-breadcrumbs.model';\n\n/** С какого числа предков середина пути сворачивается на узком экране. */\nexport const RT_BREADCRUMBS_FOLD_FROM: number = 3;\n\n/**\n * Помещаются ли предки рядом с текущим звеном, урезанным до порога или до своей полной подписи,\n * если она короче. Тогда звено сжимается с многоточием и строка не едет; иначе строка встаёт в\n * конец, и предки уезжают влево.\n */\nexport function rtBreadcrumbsFits(room: number, ancestors: number, current: number, floor: number): boolean {\n return room - ancestors >= Math.min(current, floor);\n}\n\n/**\n * Раскладка предков. На узком экране длинный путь оставляет первого и последнего предка ссылками,\n * а середину отдаёт в меню; на широком и при коротком пути свёртки нет.\n */\nexport function rtBreadcrumbsFold(ancestors: readonly IRtBreadcrumbs.Crumb[], narrow: boolean): IRtBreadcrumbs.Fold {\n if (!narrow || ancestors.length < RT_BREADCRUMBS_FOLD_FROM) {\n return { head: ancestors, hidden: [], tail: [] };\n }\n\n return {\n head: ancestors.slice(0, 1),\n hidden: ancestors.slice(1, -1),\n tail: ancestors.slice(-1),\n };\n}\n","import {\n afterRenderEffect,\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n Signal,\n signal,\n viewChild,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { BreakpointsService, rtKitLabel, TRtKitLabelParams } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtMenuComponent, RtMenuItemComponent } from '@rt-tools/ui-kit-v2/menu';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\n\nimport { rtBreadcrumbsFits, rtBreadcrumbsFold } from './rt-breadcrumbs.logic';\nimport { IRtBreadcrumbs } from './rt-breadcrumbs.model';\n\nconst BEM_BLOCK: string = 'rt-breadcrumbs';\n\n/**\n * Путь до открытой страницы: предки ссылками, текущее звено текстом.\n *\n * Цепочку отдаёт приложение: имя открытой записи приходит с ответом сервера, и знает его только\n * страница. Текущее звено рисуется в строке пути или заголовком строкой ниже — тогда рядом с ним\n * встаёт то, что страница спроецировала. На узком экране середина длинного пути уходит в меню.\n */\n@Component({\n selector: 'rt-breadcrumbs',\n templateUrl: './rt-breadcrumbs.component.html',\n styleUrl: './rt-breadcrumbs.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // angular\n RouterLink,\n\n // standalone components / directives\n BlockDirective,\n ElemDirective,\n ModDirective,\n RtIconComponent,\n RtMenuComponent,\n RtMenuItemComponent,\n RtTooltipDirective,\n ],\n host: {\n class: BEM_BLOCK,\n role: 'navigation',\n '[attr.aria-label]': 'landmarkLabel()',\n '[class.rt-breadcrumbs--heading]': \"look() === 'heading'\",\n },\n})\nexport class RtBreadcrumbsComponent {\n #itemsWatch: ResizeObserver | null = null;\n\n readonly #narrow: Signal<boolean> = inject(BreakpointsService).narrow;\n\n readonly #ancestors: Signal<readonly IRtBreadcrumbs.Crumb[]> = computed((): readonly IRtBreadcrumbs.Crumb[] =>\n this.crumbs().slice(0, -1)\n );\n\n readonly #backParams: Signal<TRtKitLabelParams> = computed((): TRtKitLabelParams => ({ name: this.backCrumb()?.label ?? '' }));\n\n /** Строка звеньев: её прокрутку ставит в конец эффект после отрисовки. `#`-поле `viewChild` не принимает. */\n protected readonly list: Signal<ElementRef<HTMLElement> | undefined> = viewChild<ElementRef<HTMLElement>>('list');\n\n /** Начало пути уехало влево за край строки. */\n protected readonly clipped: WritableSignal<boolean> = signal<boolean>(false);\n\n /** Предки помещаются рядом с урезанным текущим звеном: звено сжимается, строка не едет. */\n protected readonly fitted: WritableSignal<boolean> = signal<boolean>(false);\n\n protected readonly landmarkLabel: Signal<string> = rtKitLabel('breadcrumbsLabel');\n protected readonly foldLabel: Signal<string> = rtKitLabel('breadcrumbsHidden');\n protected readonly backLabel: Signal<string> = rtKitLabel('breadcrumbsBack', this.#backParams);\n\n protected readonly fold: Signal<IRtBreadcrumbs.Fold> = computed((): IRtBreadcrumbs.Fold =>\n rtBreadcrumbsFold(this.#ancestors(), this.#narrow())\n );\n\n protected readonly current: Signal<IRtBreadcrumbs.Crumb | null> = computed(\n (): IRtBreadcrumbs.Crumb | null => this.crumbs().at(-1) ?? null\n );\n\n /** Строка пути нужна, пока в ней есть что рисовать: у одного заголовка её нет. */\n protected readonly rowShown: Signal<boolean> = computed((): boolean => this.look() === 'inline' || this.#ancestors().length > 0);\n\n /** Куда ведёт кнопка «назад»: к последнему предку, а без предков кнопки нет. */\n protected readonly backCrumb: Signal<IRtBreadcrumbs.Crumb | null> = computed((): IRtBreadcrumbs.Crumb | null =>\n this.back() ? (this.#ancestors().at(-1) ?? null) : null\n );\n\n /** Путь от верха до открытой страницы; последнее звено — сама страница. */\n public readonly crumbs: InputSignal<readonly IRtBreadcrumbs.Crumb[]> = input.required<readonly IRtBreadcrumbs.Crumb[]>();\n\n /** Как рисуется текущее звено: в строке пути или заголовком строкой ниже. */\n public readonly look: InputSignal<IRtBreadcrumbs.Look> = input<IRtBreadcrumbs.Look>('inline');\n\n /** Кнопка «назад» перед путём; ведёт к последнему предку. */\n public readonly back: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n\n /** Знак между звеньями. */\n public readonly separator: InputSignal<string> = input<string>('/');\n\n constructor() {\n // Длинный путь едет внутри своей строки, и видна должна быть открытая страница, а не верх\n // пути. Строка встаёт в конец при смене цепочки и при смене ширины звеньев: шрифт страницы\n // приходит позже первой отрисовки и раздвигает звенья уже после неё.\n afterRenderEffect((): void => {\n this.crumbs();\n this.fold();\n this.#watchItems();\n this.#scrollToEnd();\n });\n\n inject(DestroyRef).onDestroy((): void => this.#itemsWatch?.disconnect());\n }\n\n protected onListScroll(): void {\n const list: HTMLElement | undefined = this.list()?.nativeElement;\n this.clipped.set(list !== undefined && list.scrollLeft > 0);\n }\n\n #watchItems(): void {\n const list: HTMLElement | undefined = this.list()?.nativeElement;\n if (list === undefined || typeof ResizeObserver === 'undefined') {\n return;\n }\n this.#itemsWatch?.disconnect();\n this.#itemsWatch = new ResizeObserver((): void => this.#scrollToEnd());\n Array.from(list.children).forEach((item: Element): void => this.#itemsWatch?.observe(item));\n }\n\n #scrollToEnd(): void {\n const list: HTMLElement | undefined = this.list()?.nativeElement;\n if (list !== undefined) {\n this.fitted.set(this.#measureFit(list));\n list.scrollLeft = list.scrollWidth;\n this.clipped.set(list.scrollLeft > 0);\n }\n }\n\n /**\n * Ширина строки без внутренних полей, предки целиком и полная подпись текущего звена против\n * порога из свойства блока. Без текущего звена в строке сжимать нечего.\n */\n #measureFit(list: HTMLElement): boolean {\n const items: readonly Element[] = Array.from(list.children);\n const current: Element | null = items.at(-1)?.querySelector('.rt-breadcrumbs__current') ?? null;\n if (current === null) {\n return false;\n }\n const listStyle: CSSStyleDeclaration = getComputedStyle(list);\n const room: number = list.clientWidth - parseFloat(listStyle.paddingInlineStart) - parseFloat(listStyle.paddingInlineEnd);\n const ancestors: number = items\n .slice(0, -1)\n .reduce((sum: number, item: Element): number => sum + item.getBoundingClientRect().width, 0);\n const floor: number = parseFloat(listStyle.getPropertyValue('--rt-breadcrumbs-current-min')) || 0;\n\n return rtBreadcrumbsFits(room, ancestors, current.scrollWidth, floor);\n }\n}\n","<ng-container rtBlock=\"rt-breadcrumbs\">\n @if (rowShown()) {\n <div rtElem=\"row\">\n @if (backCrumb(); as backTo) {\n <a rtElem=\"back\" qa-dataid=\"breadcrumbs-back\" [routerLink]=\"backTo.link\" [attr.aria-label]=\"backLabel()\">\n <rt-icon name=\"arrow-left\" size=\"md\" />\n </a>\n }\n\n <ol\n #list\n rtElem=\"list\"\n qa-dataid=\"breadcrumbs-list\"\n [rtMod]=\"{ clipped: clipped(), fitted: fitted() }\"\n (scroll)=\"onListScroll()\">\n @for (crumb of fold().head; track $index) {\n <li rtElem=\"item\">\n <a rtElem=\"link\" qa-dataid=\"breadcrumbs-link\" [routerLink]=\"crumb.link\">{{ crumb.label }}</a>\n <span rtElem=\"separator\" aria-hidden=\"true\">{{ separator() }}</span>\n </li>\n }\n\n @if (fold().hidden.length) {\n <li rtElem=\"item\" qa-dataid=\"breadcrumbs-fold\">\n <span rtElem=\"fold\">\n <rt-menu size=\"sm\" align=\"start\" [ariaLabel]=\"foldLabel()\">\n @for (crumb of fold().hidden; track $index) {\n <rt-menu-item qa-dataid=\"breadcrumbs-fold-item\" [label]=\"crumb.label\" [link]=\"crumb.link ?? null\" />\n }\n </rt-menu>\n </span>\n <span rtElem=\"separator\" aria-hidden=\"true\">{{ separator() }}</span>\n </li>\n }\n\n @for (crumb of fold().tail; track $index) {\n <li rtElem=\"item\">\n <a rtElem=\"link\" qa-dataid=\"breadcrumbs-link\" [routerLink]=\"crumb.link\">{{ crumb.label }}</a>\n <span rtElem=\"separator\" aria-hidden=\"true\">{{ separator() }}</span>\n </li>\n }\n\n @if (look() === 'inline' && current(); as page) {\n <li rtElem=\"item\">\n <span\n rtElem=\"current\"\n qa-dataid=\"breadcrumbs-current\"\n aria-current=\"page\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"page.label\">\n {{ page.label }}\n </span>\n </li>\n }\n </ol>\n </div>\n }\n\n @if (look() === 'heading' && current(); as page) {\n <div rtElem=\"heading\">\n <h1 rtElem=\"title\" qa-dataid=\"breadcrumbs-current\" aria-current=\"page\" rtTooltipWhenTruncated [rtTooltip]=\"page.label\">\n {{ page.label }}\n </h1>\n <ng-content />\n </div>\n }\n</ng-container>\n"],"mappings":";;;;;;;;AAGA,MAAa,2BAAmC;AAOhD,SAAgB,kBAAkB,MAAc,WAAmB,SAAiB,OAAa;CAC7F,OAAO,OAAO,aAAa,KAAK,IAAI,SAAS,KAAK;AACtD;AAMA,SAAgB,kBAAkB,WAA4C,QAAe;CACzF,IAAI,CAAC,UAAU,UAAU,SAAA,GACrB,OAAO;EAAE,MAAM;EAAW,QAAQ,CAAA;EAAI,MAAM,CAAA;CAAE;CAGlD,OAAO;EACH,MAAM,UAAU,MAAM,GAAG,CAAC;EAC1B,QAAQ,UAAU,MAAM,GAAG,EAAE;EAC7B,MAAM,UAAU,MAAM,EAAE;CAC3B;AACL;ACEA,MAAM,YAAoB;AAmC1B,IAAa,yBAAb,MAAa,uBAAsB;CAC/B;CAES;CAEA;CAIA;CA6CT,cAAA;EArDA,KAAA,cAAqC;EAE5B,KAAA,UAA2B,OAAO,kBAAkB,CAAC,CAAC;EAEtD,KAAA,aAAsD,eAC3D,KAAK,OAAM,CAAE,CAAC,MAAM,GAAG,EAAE,GAC5B,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;EAEQ,KAAA,cAAyC,gBAAmC,EAAE,MAAM,KAAK,UAAS,CAAE,EAAE,SAAS,GAAE,IAAI,GAAA,YAAA,CAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;EAG3G,KAAA,OAAoD,UAAmC,QAAO,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;EAG9F,KAAA,UAAmC,OAAgB,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;EAGzD,KAAA,SAAkC,OAAgB,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;EAExD,KAAA,gBAAgC,WAAW,kBAAkB;EAC7D,KAAA,YAA4B,WAAW,mBAAmB;EAC1D,KAAA,YAA4B,WAAW,mBAAmB,KAAK,WAAW;EAE1E,KAAA,OAAoC,eACnD,kBAAkB,KAAK,WAAU,GAAI,KAAK,QAAO,CAAE,GACtD,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;EAEkB,KAAA,UAA+C,eAC3B,KAAK,OAAM,CAAE,CAAC,GAAG,EAAE,KAAK,MAC9D,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;EAGkB,KAAA,WAA4B,eAAwB,KAAK,KAAI,MAAO,YAAY,KAAK,WAAU,CAAE,CAAC,SAAS,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;EAG7G,KAAA,YAAiD,eAChE,KAAK,KAAI,IAAM,KAAK,WAAU,CAAE,CAAC,GAAG,EAAE,KAAK,OAAQ,MACtD,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;EAGe,KAAA,SAAuD,MAAM,SAA2C,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;EAGxG,KAAA,OAAyC,MAA2B,UAAS,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;EAG7E,KAAA,OAAmD,MAAwB,OAAK;GAAA,GAAA,YAAA,EAAA,WAAA,OAAA,+BAAA,CAAA;GAC5F,WAAW;EAAgB,CAAA;EAIf,KAAA,YAAiC,MAAc,KAAI,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;EAM/D,wBAA6B;GACzB,KAAK,OAAM;GACX,KAAK,KAAI;GACT,KAAK,YAAW;GAChB,KAAK,aAAY;EACrB,CAAC;EAED,OAAO,UAAU,CAAC,CAAC,gBAAsB,KAAK,aAAa,WAAU,CAAE;CAC3E;CAEU,eAAY;EAClB,MAAM,OAAgC,KAAK,KAAI,CAAE,EAAE;EACnD,KAAK,QAAQ,IAAI,SAAS,UAAa,KAAK,aAAa,CAAC;CAC9D;CAEA,cAAW;EACP,MAAM,OAAgC,KAAK,KAAI,CAAE,EAAE;EACnD,IAAI,SAAS,UAAa,OAAO,mBAAmB,aAChD;EAEJ,KAAK,aAAa,WAAU;EAC5B,KAAK,cAAc,IAAI,qBAA2B,KAAK,aAAY,CAAE;EACrE,MAAM,KAAK,KAAK,QAAQ,CAAC,CAAC,SAAS,SAAwB,KAAK,aAAa,QAAQ,IAAI,CAAC;CAC9F;CAEA,eAAY;EACR,MAAM,OAAgC,KAAK,KAAI,CAAE,EAAE;EACnD,IAAI,SAAS,QAAW;GACpB,KAAK,OAAO,IAAI,KAAK,YAAY,IAAI,CAAC;GACtC,KAAK,aAAa,KAAK;GACvB,KAAK,QAAQ,IAAI,KAAK,aAAa,CAAC;EACxC;CACJ;CAMA,YAAY,MAAiB;EACzB,MAAM,QAA4B,MAAM,KAAK,KAAK,QAAQ;EAC1D,MAAM,UAA0B,MAAM,GAAG,EAAE,CAAC,EAAE,cAAc,0BAA0B,KAAK;EAC3F,IAAI,YAAY,MACZ,OAAO;EAEX,MAAM,YAAiC,iBAAiB,IAAI;EAC5D,MAAM,OAAe,KAAK,cAAc,WAAW,UAAU,kBAAkB,IAAI,WAAW,UAAU,gBAAgB;EACxH,MAAM,YAAoB,MACrB,MAAM,GAAG,EAAE,CAAC,CACZ,QAAQ,KAAa,SAA0B,MAAM,KAAK,sBAAqB,CAAE,CAAC,OAAO,CAAC;EAC/F,MAAM,QAAgB,WAAW,UAAU,iBAAiB,8BAA8B,CAAC,KAAK;EAEhG,OAAO,kBAAkB,MAAM,WAAW,QAAQ,aAAa,KAAK;CACxE;CA9GS;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAsB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAAtB;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAAsB,cAAA;GAAA,UAAA;GAAA,QAAA;IAAA,QAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,MAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,MAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,WAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;GAAA;GAAA,MAAA;IAAA,YAAA,EAAA,QAAA,aAAA;IAAA,YAAA;KAAA,mBAAA;KAAA,iCAAA;IAAA;IAAA,gBAAA;GAAA;GAAA,aAAA,CAAA;IAAA,cAAA;IAAA,OAAA;IAAA,WAAA,CAAA,MAAA;IAAA,aAAA;IAAA,UAAA;GAAA,CAAA;GAAA,UAAA;GAAA,UCjEnC;GAmEA,QAAA,CAAA,ixJAAA;GAAA,cAAA;IAAA;KAAA,MAAA;KAAA,MDpBQ;KAAU,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MAGV;KAAc,UAAA;KAAA,QAAA,CAAA,OAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACd;KAAa,UAAA;KAAA,QAAA,CAAA,OAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACb;KAAY,UAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACZ;KAAe,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACf;KAAe,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;KAAA,SAAA,CAAA,cAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACf;KAAmB,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;KAAA,SAAA,CAAA,UAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACnB;KAAkB,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;KAAA,UAAA,CAAA,WAAA;IAAA;GAAA;GAAA,iBAAA,GAAA,wBAAA;GAAA,eAAA,GAAA,kBAAA;EAAA,CAAA;CAAA;;AASb,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAsB,YAAA,CAAA;EA1BlC,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAgB,iBAGT,wBAAwB;GAAM,eAChC,kBAAkB;GAAI,SAC5B;IAEL;IAGA;IACA;IACA;IACA;IACA;IACA;IACA;GACH;GAAA,MACK;IACF,OAAO;IACP,MAAM;IACN,qBAAqB;IACrB,mCAAmC;GACtC;GAAA,UAAA;GAAA,QAAA,CAAA,ixJAAA;EAAA,CAAA;CAcyG,CAAA;CAAA,sBAAA,CAAA;CAAA,gBAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,QAAM,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,QAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,MAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,WAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;CAAA;AAAA,CAAA"}
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-breadcrumbs.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/breadcrumbs/rt-breadcrumbs.logic.ts","../../../projects/ui-kit-v2/src/lib/components/breadcrumbs/rt-breadcrumbs.component.ts","../../../projects/ui-kit-v2/src/lib/components/breadcrumbs/rt-breadcrumbs.component.html"],"sourcesContent":["import { IRtBreadcrumbs } from './rt-breadcrumbs.model';\n\n/** С какого числа предков середина пути сворачивается на узком экране. */\nexport const RT_BREADCRUMBS_FOLD_FROM: number = 3;\n\n/**\n * Помещаются ли предки рядом с текущим звеном, урезанным до порога или до своей полной подписи,\n * если она короче. Тогда звено сжимается с многоточием и строка не едет; иначе строка встаёт в\n * конец, и предки уезжают влево.\n */\nexport function rtBreadcrumbsFits(room: number, ancestors: number, current: number, floor: number): boolean {\n return room - ancestors >= Math.min(current, floor);\n}\n\n/**\n * Раскладка предков. На узком экране длинный путь оставляет первого и последнего предка ссылками,\n * а середину отдаёт в меню; на широком и при коротком пути свёртки нет.\n */\nexport function rtBreadcrumbsFold(ancestors: readonly IRtBreadcrumbs.Crumb[], narrow: boolean): IRtBreadcrumbs.Fold {\n if (!narrow || ancestors.length < RT_BREADCRUMBS_FOLD_FROM) {\n return { head: ancestors, hidden: [], tail: [] };\n }\n\n return {\n head: ancestors.slice(0, 1),\n hidden: ancestors.slice(1, -1),\n tail: ancestors.slice(-1),\n };\n}\n","import {\n afterRenderEffect,\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n Signal,\n signal,\n viewChild,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { BreakpointsService, rtKitLabel, TRtKitLabelParams } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtMenuComponent, RtMenuItemComponent } from '@rt-tools/ui-kit-v2/menu';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\n\nimport { rtBreadcrumbsFits, rtBreadcrumbsFold } from './rt-breadcrumbs.logic';\nimport { IRtBreadcrumbs } from './rt-breadcrumbs.model';\n\nconst BEM_BLOCK: string = 'rt-breadcrumbs';\n\n/**\n * Путь до открытой страницы: предки ссылками, текущее звено текстом.\n *\n * Цепочку отдаёт приложение: имя открытой записи приходит с ответом сервера, и знает его только\n * страница. Текущее звено рисуется в строке пути или заголовком строкой ниже — тогда рядом с ним\n * встаёт то, что страница спроецировала. На узком экране середина длинного пути уходит в меню.\n */\n@Component({\n selector: 'rt-breadcrumbs',\n templateUrl: './rt-breadcrumbs.component.html',\n styleUrl: './rt-breadcrumbs.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // angular\n RouterLink,\n\n // standalone components / directives\n BlockDirective,\n ElemDirective,\n ModDirective,\n RtIconComponent,\n RtMenuComponent,\n RtMenuItemComponent,\n RtTooltipDirective,\n ],\n host: {\n class: BEM_BLOCK,\n role: 'navigation',\n '[attr.aria-label]': 'landmarkLabel()',\n '[class.rt-breadcrumbs--heading]': \"look() === 'heading'\",\n },\n})\nexport class RtBreadcrumbsComponent {\n #itemsWatch: ResizeObserver | null = null;\n\n readonly #narrow: Signal<boolean> = inject(BreakpointsService).narrow;\n\n readonly #ancestors: Signal<readonly IRtBreadcrumbs.Crumb[]> = computed((): readonly IRtBreadcrumbs.Crumb[] =>\n this.crumbs().slice(0, -1)\n );\n\n readonly #backParams: Signal<TRtKitLabelParams> = computed((): TRtKitLabelParams => ({ name: this.backCrumb()?.label ?? '' }));\n\n /** Строка звеньев: её прокрутку ставит в конец эффект после отрисовки. `#`-поле `viewChild` не принимает. */\n protected readonly list: Signal<ElementRef<HTMLElement> | undefined> = viewChild<ElementRef<HTMLElement>>('list');\n\n /** Начало пути уехало влево за край строки. */\n protected readonly clipped: WritableSignal<boolean> = signal<boolean>(false);\n\n /** Предки помещаются рядом с урезанным текущим звеном: звено сжимается, строка не едет. */\n protected readonly fitted: WritableSignal<boolean> = signal<boolean>(false);\n\n protected readonly landmarkLabel: Signal<string> = rtKitLabel('breadcrumbsLabel');\n protected readonly foldLabel: Signal<string> = rtKitLabel('breadcrumbsHidden');\n protected readonly backLabel: Signal<string> = rtKitLabel('breadcrumbsBack', this.#backParams);\n\n protected readonly fold: Signal<IRtBreadcrumbs.Fold> = computed((): IRtBreadcrumbs.Fold =>\n rtBreadcrumbsFold(this.#ancestors(), this.#narrow())\n );\n\n protected readonly current: Signal<IRtBreadcrumbs.Crumb | null> = computed(\n (): IRtBreadcrumbs.Crumb | null => this.crumbs().at(-1) ?? null\n );\n\n /** Строка пути нужна, пока в ней есть что рисовать: у одного заголовка её нет. */\n protected readonly rowShown: Signal<boolean> = computed((): boolean => this.look() === 'inline' || this.#ancestors().length > 0);\n\n /** Куда ведёт кнопка «назад»: к последнему предку, а без предков кнопки нет. */\n protected readonly backCrumb: Signal<IRtBreadcrumbs.Crumb | null> = computed((): IRtBreadcrumbs.Crumb | null =>\n this.back() ? (this.#ancestors().at(-1) ?? null) : null\n );\n\n /** Путь от верха до открытой страницы; последнее звено — сама страница. */\n public readonly crumbs: InputSignal<readonly IRtBreadcrumbs.Crumb[]> = input.required<readonly IRtBreadcrumbs.Crumb[]>();\n\n /** Как рисуется текущее звено: в строке пути или заголовком строкой ниже. */\n public readonly look: InputSignal<IRtBreadcrumbs.Look> = input<IRtBreadcrumbs.Look>('inline');\n\n /** Кнопка «назад» перед путём; ведёт к последнему предку. */\n public readonly back: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n transform: booleanAttribute,\n });\n\n /** Знак между звеньями. */\n public readonly separator: InputSignal<string> = input<string>('/');\n\n constructor() {\n // Длинный путь едет внутри своей строки, и видна должна быть открытая страница, а не верх\n // пути. Строка встаёт в конец при смене цепочки и при смене ширины звеньев: шрифт страницы\n // приходит позже первой отрисовки и раздвигает звенья уже после неё.\n afterRenderEffect((): void => {\n this.crumbs();\n this.fold();\n this.#watchItems();\n this.#scrollToEnd();\n });\n\n inject(DestroyRef).onDestroy((): void => this.#itemsWatch?.disconnect());\n }\n\n protected onListScroll(): void {\n const list: HTMLElement | undefined = this.list()?.nativeElement;\n this.clipped.set(list !== undefined && list.scrollLeft > 0);\n }\n\n #watchItems(): void {\n const list: HTMLElement | undefined = this.list()?.nativeElement;\n if (list === undefined || typeof ResizeObserver === 'undefined') {\n return;\n }\n this.#itemsWatch?.disconnect();\n this.#itemsWatch = new ResizeObserver((): void => this.#scrollToEnd());\n Array.from(list.children).forEach((item: Element): void => this.#itemsWatch?.observe(item));\n }\n\n #scrollToEnd(): void {\n const list: HTMLElement | undefined = this.list()?.nativeElement;\n if (list !== undefined) {\n this.fitted.set(this.#measureFit(list));\n list.scrollLeft = list.scrollWidth;\n this.clipped.set(list.scrollLeft > 0);\n }\n }\n\n /**\n * Ширина строки без внутренних полей, предки целиком и полная подпись текущего звена против\n * порога из свойства блока. Без текущего звена в строке сжимать нечего.\n */\n #measureFit(list: HTMLElement): boolean {\n const items: readonly Element[] = Array.from(list.children);\n const current: Element | null = items.at(-1)?.querySelector('.rt-breadcrumbs__current') ?? null;\n if (current === null) {\n return false;\n }\n const listStyle: CSSStyleDeclaration = getComputedStyle(list);\n const room: number = list.clientWidth - parseFloat(listStyle.paddingInlineStart) - parseFloat(listStyle.paddingInlineEnd);\n const ancestors: number = items\n .slice(0, -1)\n .reduce((sum: number, item: Element): number => sum + item.getBoundingClientRect().width, 0);\n const floor: number = parseFloat(listStyle.getPropertyValue('--rt-breadcrumbs-current-min')) || 0;\n\n return rtBreadcrumbsFits(room, ancestors, current.scrollWidth, floor);\n }\n}\n","<ng-container rtBlock=\"rt-breadcrumbs\">\n @if (rowShown()) {\n <div rtElem=\"row\">\n @if (backCrumb(); as backTo) {\n <a rtElem=\"back\" qa-dataid=\"breadcrumbs-back\" [routerLink]=\"backTo.link\" [attr.aria-label]=\"backLabel()\">\n <rt-icon name=\"arrow-left\" size=\"md\" />\n </a>\n }\n\n <ol\n #list\n rtElem=\"list\"\n qa-dataid=\"breadcrumbs-list\"\n [rtMod]=\"{ clipped: clipped(), fitted: fitted() }\"\n (scroll)=\"onListScroll()\">\n @for (crumb of fold().head; track $index) {\n <li rtElem=\"item\">\n <a rtElem=\"link\" qa-dataid=\"breadcrumbs-link\" [routerLink]=\"crumb.link\">{{ crumb.label }}</a>\n <span rtElem=\"separator\" aria-hidden=\"true\">{{ separator() }}</span>\n </li>\n }\n\n @if (fold().hidden.length) {\n <li rtElem=\"item\" qa-dataid=\"breadcrumbs-fold\">\n <span rtElem=\"fold\">\n <rt-menu size=\"sm\" align=\"start\" [ariaLabel]=\"foldLabel()\">\n @for (crumb of fold().hidden; track $index) {\n <rt-menu-item qa-dataid=\"breadcrumbs-fold-item\" [label]=\"crumb.label\" [link]=\"crumb.link ?? null\" />\n }\n </rt-menu>\n </span>\n <span rtElem=\"separator\" aria-hidden=\"true\">{{ separator() }}</span>\n </li>\n }\n\n @for (crumb of fold().tail; track $index) {\n <li rtElem=\"item\">\n <a rtElem=\"link\" qa-dataid=\"breadcrumbs-link\" [routerLink]=\"crumb.link\">{{ crumb.label }}</a>\n <span rtElem=\"separator\" aria-hidden=\"true\">{{ separator() }}</span>\n </li>\n }\n\n @if (look() === 'inline' && current(); as page) {\n <li rtElem=\"item\">\n <span\n rtElem=\"current\"\n qa-dataid=\"breadcrumbs-current\"\n aria-current=\"page\"\n rtTooltipWhenTruncated\n [rtTooltip]=\"page.label\">\n {{ page.label }}\n </span>\n </li>\n }\n </ol>\n </div>\n }\n\n @if (look() === 'heading' && current(); as page) {\n <div rtElem=\"heading\">\n <h1 rtElem=\"title\" qa-dataid=\"breadcrumbs-current\" aria-current=\"page\" rtTooltipWhenTruncated [rtTooltip]=\"page.label\">\n {{ page.label }}\n </h1>\n <ng-content />\n </div>\n }\n</ng-container>\n"],"mappings":"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"}
@@ -666,6 +666,7 @@ var RtColorPaletteComponent = class RtColorPaletteComponent extends RtFormContro
666
666
  "rtPopoverFitViewport",
667
667
  "rtPopoverContext",
668
668
  "rtPopoverPanelClass",
669
+ "rtPopoverBackdropClass",
669
670
  "rtPopoverDisabled",
670
671
  "rtPopoverOffsetY",
671
672
  "rtPopoverOffsetX",