@rt-tools/ui-kit-v2 0.28.0 → 0.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs +2 -2
  2. package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs.map +1 -1
  3. package/fesm2022/rt-tools-ui-kit-v2-container.mjs +9 -4
  4. package/fesm2022/rt-tools-ui-kit-v2-container.mjs.map +1 -1
  5. package/fesm2022/rt-tools-ui-kit-v2-core.mjs +37 -4
  6. package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -1
  7. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs +2 -2
  8. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs.map +1 -1
  9. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs +1 -1
  10. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs.map +1 -1
  11. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs +1 -1
  12. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs.map +1 -1
  13. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs +2 -2
  14. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs.map +1 -1
  15. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +1 -1
  16. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -1
  17. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs +2 -2
  18. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs.map +1 -1
  19. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +367 -23
  20. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -1
  21. package/fesm2022/rt-tools-ui-kit-v2-pdf-viewer.mjs +2 -2
  22. package/fesm2022/rt-tools-ui-kit-v2-pdf-viewer.mjs.map +1 -1
  23. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs +4 -0
  24. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs.map +1 -1
  25. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +2 -2
  26. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  27. package/fesm2022/rt-tools-ui-kit-v2-table.mjs +4 -1
  28. package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
  29. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs +2 -2
  30. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs.map +1 -1
  31. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs +2 -2
  32. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs.map +1 -1
  33. package/package.json +1 -1
  34. package/src/lib/components/calendar/rt-calendar.component.scss +3 -2
  35. package/src/lib/components/container/CONTEXT.md +6 -0
  36. package/src/lib/components/container/rt-container.component.scss +4 -0
  37. package/src/lib/components/data-list/toolbar/rt-data-list-toolbar.component.scss +1 -1
  38. package/src/lib/components/dynamic-list/rt-dynamic-list.component.scss +1 -1
  39. package/src/lib/components/filter-control/rt-filter-control.component.scss +4 -2
  40. package/src/lib/components/page-header/CONTEXT.md +12 -0
  41. package/src/lib/components/page-header/more/rt-page-header-more.component.scss +7 -0
  42. package/src/lib/components/page-header/rt-page-header-mobile.scss +24 -0
  43. package/src/lib/components/page-header/rt-page-header.component.scss +25 -3
  44. package/src/lib/components/pdf-viewer/rt-pdf-viewer.component.scss +1 -1
  45. package/src/lib/components/popover/CONTEXT.md +2 -1
  46. package/src/lib/components/toolbar/rt-toolbar.component.scss +3 -1
  47. package/src/lib/components/workspace/rt-workspace.component.scss +8 -6
  48. package/src/rich-editor/lib/components/chat/rt-chat.component.scss +5 -3
  49. package/src/styles/_breakpoints.scss +19 -0
  50. package/src/styles/_index.scss +4 -0
  51. package/src/styles/_place.scss +7 -0
  52. package/styles/tokens.css +8 -0
  53. package/types/rt-tools-ui-kit-v2-core.d.ts +24 -5
  54. package/types/rt-tools-ui-kit-v2-page-header.d.ts +60 -6
  55. package/types/rt-tools-ui-kit-v2-table.d.ts +4 -0
@@ -174,7 +174,7 @@ var RtToolbarComponent = class RtToolbarComponent {
174
174
  ],
175
175
  ngImport: i0,
176
176
  template: "@if (leftTpl() || centerTpl() || rightTpl()) {\n <ng-container rtBlock=\"rt-toolbar\">\n <div rtElem=\"bars\">\n @if (leftTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"left\" [rtMod]=\"{ left: true }\">\n <ng-container [ngTemplateOutlet]=\"leftTpl() ?? null\" />\n </div>\n }\n\n @if (centerTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"center\" [rtMod]=\"{ center: true }\">\n <ng-container [ngTemplateOutlet]=\"centerTpl() ?? null\" />\n </div>\n }\n\n @if (rightTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"right\" [rtMod]=\"{ right: true }\">\n <ng-container [ngTemplateOutlet]=\"rightTpl() ?? null\" />\n </div>\n }\n </div>\n </ng-container>\n}\n",
177
- styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-toolbar{--rt-toolbar-padding-top: var(--rt-space-2);--rt-toolbar-padding-bottom: var(--rt-space-2);--rt-toolbar-padding-inline: 0;--rt-toolbar-height: auto;--rt-toolbar-border-bottom: none;--rt-toolbar-gap: var(--rt-space-2);--rt-toolbar-center-justify: flex-end;--rt-toolbar-center-overflow: visible;--rt-toolbar-field-width: var(--rt-size-100);display:block}.rt-toolbar__bars{display:flex;width:100%;min-height:var(--rt-toolbar-height);box-sizing:border-box;flex-direction:row;align-items:center;justify-content:space-between;padding:var(--rt-toolbar-padding-top) var(--rt-toolbar-padding-inline) var(--rt-toolbar-padding-bottom);border-bottom:var(--rt-toolbar-border-bottom);gap:var(--rt-toolbar-gap)}.rt-toolbar__bar{display:flex;align-items:center}.rt-toolbar__bar--left{min-width:0;flex:0 0 auto;gap:var(--rt-space-2)}.rt-toolbar__bar--left>rt-input{width:var(--rt-toolbar-field-width);max-width:100%}.rt-toolbar__bar--center{overflow:var(--rt-toolbar-center-overflow);flex:1 1 auto;justify-content:var(--rt-toolbar-center-justify);gap:var(--rt-space-2)}.rt-toolbar__bar--center rt-input,.rt-toolbar__bar--center rt-select{width:100%}.rt-toolbar__bar--right{flex:0 1 auto;margin-left:auto;gap:var(--rt-space-sm)}.rt-toolbar--dense .rt-toolbar__bar--left{min-width:0;flex:0 1 auto}@media(width<=768px){.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bars{flex-direction:column;align-items:stretch;gap:var(--rt-space-sm)}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar{flex-wrap:wrap}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar--center{justify-content:stretch}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar--right{justify-content:flex-end;margin-left:0}}}\n"],
177
+ styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-toolbar{--rt-toolbar-padding-top: var(--rt-space-2);--rt-toolbar-padding-bottom: var(--rt-space-2);--rt-toolbar-padding-inline: 0;--rt-toolbar-height: auto;--rt-toolbar-border-bottom: none;--rt-toolbar-gap: var(--rt-space-2);--rt-toolbar-center-justify: flex-end;--rt-toolbar-center-overflow: visible;--rt-toolbar-field-width: var(--rt-size-100);display:block}.rt-toolbar__bars{display:flex;width:100%;min-height:var(--rt-toolbar-height);box-sizing:border-box;flex-direction:row;align-items:center;justify-content:space-between;padding:var(--rt-toolbar-padding-top) var(--rt-toolbar-padding-inline) var(--rt-toolbar-padding-bottom);border-bottom:var(--rt-toolbar-border-bottom);gap:var(--rt-toolbar-gap)}.rt-toolbar__bar{display:flex;align-items:center}.rt-toolbar__bar--left{min-width:0;flex:0 0 auto;gap:var(--rt-space-2)}.rt-toolbar__bar--left>rt-input{width:var(--rt-toolbar-field-width);max-width:100%}.rt-toolbar__bar--center{overflow:var(--rt-toolbar-center-overflow);flex:1 1 auto;justify-content:var(--rt-toolbar-center-justify);gap:var(--rt-space-2)}.rt-toolbar__bar--center rt-input,.rt-toolbar__bar--center rt-select{width:100%}.rt-toolbar__bar--right{flex:0 1 auto;margin-left:auto;gap:var(--rt-space-sm)}.rt-toolbar--dense .rt-toolbar__bar--left{min-width:0;flex:0 1 auto}@container rt-place (width <= 768px){.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bars{flex-direction:column;align-items:stretch;gap:var(--rt-space-sm)}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar{flex-wrap:wrap}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar--center{justify-content:stretch}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar--right{justify-content:flex-end;margin-left:0}}}\n"],
178
178
  dependencies: [
179
179
  {
180
180
  kind: "directive",
@@ -231,7 +231,7 @@ i0.ɵɵngDeclareClassMetadata({
231
231
  "[class.rt-toolbar--dense]": "dense()"
232
232
  },
233
233
  template: "@if (leftTpl() || centerTpl() || rightTpl()) {\n <ng-container rtBlock=\"rt-toolbar\">\n <div rtElem=\"bars\">\n @if (leftTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"left\" [rtMod]=\"{ left: true }\">\n <ng-container [ngTemplateOutlet]=\"leftTpl() ?? null\" />\n </div>\n }\n\n @if (centerTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"center\" [rtMod]=\"{ center: true }\">\n <ng-container [ngTemplateOutlet]=\"centerTpl() ?? null\" />\n </div>\n }\n\n @if (rightTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"right\" [rtMod]=\"{ right: true }\">\n <ng-container [ngTemplateOutlet]=\"rightTpl() ?? null\" />\n </div>\n }\n </div>\n </ng-container>\n}\n",
234
- styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-toolbar{--rt-toolbar-padding-top: var(--rt-space-2);--rt-toolbar-padding-bottom: var(--rt-space-2);--rt-toolbar-padding-inline: 0;--rt-toolbar-height: auto;--rt-toolbar-border-bottom: none;--rt-toolbar-gap: var(--rt-space-2);--rt-toolbar-center-justify: flex-end;--rt-toolbar-center-overflow: visible;--rt-toolbar-field-width: var(--rt-size-100);display:block}.rt-toolbar__bars{display:flex;width:100%;min-height:var(--rt-toolbar-height);box-sizing:border-box;flex-direction:row;align-items:center;justify-content:space-between;padding:var(--rt-toolbar-padding-top) var(--rt-toolbar-padding-inline) var(--rt-toolbar-padding-bottom);border-bottom:var(--rt-toolbar-border-bottom);gap:var(--rt-toolbar-gap)}.rt-toolbar__bar{display:flex;align-items:center}.rt-toolbar__bar--left{min-width:0;flex:0 0 auto;gap:var(--rt-space-2)}.rt-toolbar__bar--left>rt-input{width:var(--rt-toolbar-field-width);max-width:100%}.rt-toolbar__bar--center{overflow:var(--rt-toolbar-center-overflow);flex:1 1 auto;justify-content:var(--rt-toolbar-center-justify);gap:var(--rt-space-2)}.rt-toolbar__bar--center rt-input,.rt-toolbar__bar--center rt-select{width:100%}.rt-toolbar__bar--right{flex:0 1 auto;margin-left:auto;gap:var(--rt-space-sm)}.rt-toolbar--dense .rt-toolbar__bar--left{min-width:0;flex:0 1 auto}@media(width<=768px){.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bars{flex-direction:column;align-items:stretch;gap:var(--rt-space-sm)}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar{flex-wrap:wrap}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar--center{justify-content:stretch}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar--right{justify-content:flex-end;margin-left:0}}}\n"]
234
+ styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-toolbar{--rt-toolbar-padding-top: var(--rt-space-2);--rt-toolbar-padding-bottom: var(--rt-space-2);--rt-toolbar-padding-inline: 0;--rt-toolbar-height: auto;--rt-toolbar-border-bottom: none;--rt-toolbar-gap: var(--rt-space-2);--rt-toolbar-center-justify: flex-end;--rt-toolbar-center-overflow: visible;--rt-toolbar-field-width: var(--rt-size-100);display:block}.rt-toolbar__bars{display:flex;width:100%;min-height:var(--rt-toolbar-height);box-sizing:border-box;flex-direction:row;align-items:center;justify-content:space-between;padding:var(--rt-toolbar-padding-top) var(--rt-toolbar-padding-inline) var(--rt-toolbar-padding-bottom);border-bottom:var(--rt-toolbar-border-bottom);gap:var(--rt-toolbar-gap)}.rt-toolbar__bar{display:flex;align-items:center}.rt-toolbar__bar--left{min-width:0;flex:0 0 auto;gap:var(--rt-space-2)}.rt-toolbar__bar--left>rt-input{width:var(--rt-toolbar-field-width);max-width:100%}.rt-toolbar__bar--center{overflow:var(--rt-toolbar-center-overflow);flex:1 1 auto;justify-content:var(--rt-toolbar-center-justify);gap:var(--rt-space-2)}.rt-toolbar__bar--center rt-input,.rt-toolbar__bar--center rt-select{width:100%}.rt-toolbar__bar--right{flex:0 1 auto;margin-left:auto;gap:var(--rt-space-sm)}.rt-toolbar--dense .rt-toolbar__bar--left{min-width:0;flex:0 1 auto}@container rt-place (width <= 768px){.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bars{flex-direction:column;align-items:stretch;gap:var(--rt-space-sm)}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar{flex-wrap:wrap}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar--center{justify-content:stretch}.rt-toolbar:not(.rt-toolbar--dense) .rt-toolbar__bar--right{justify-content:flex-end;margin-left:0}}}\n"]
235
235
  }]
236
236
  }],
237
237
  propDecorators: {
@@ -1 +1 @@
1
- {"version":3,"file":"rt-tools-ui-kit-v2-toolbar.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/toolbar/rt-toolbar.component.ts","../../../projects/ui-kit-v2/src/lib/components/toolbar/rt-toolbar.component.html"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n contentChild,\n Directive,\n input,\n InputSignalWithTransform,\n Signal,\n TemplateRef,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\n/**\n * Маркер-директива для контента в левой секции тулбара.\n *\n * @example\n * ```html\n * <rt-toolbar>\n * <ng-template rtToolbarLeft>\n * <button rtButton label=\"Создать\" />\n * </ng-template>\n * </rt-toolbar>\n * ```\n */\n@Directive({\n selector: '[rtToolbarLeft]',\n})\nexport class RtToolbarLeftDirective {}\n\n/**\n * Маркер-директива для контента в центральной секции тулбара.\n *\n * @example\n * ```html\n * <rt-toolbar>\n * <ng-template rtToolbarCenter>\n * <span>Заголовок страницы</span>\n * </ng-template>\n * </rt-toolbar>\n * ```\n */\n@Directive({\n selector: '[rtToolbarCenter]',\n})\nexport class RtToolbarCenterDirective {}\n\n/**\n * Маркер-директива для контента в правой секции тулбара.\n *\n * @example\n * ```html\n * <rt-toolbar>\n * <ng-template rtToolbarRight>\n * <input type=\"search\" placeholder=\"Поиск\" />\n * </ng-template>\n * </rt-toolbar>\n * ```\n */\n@Directive({\n selector: '[rtToolbarRight]',\n})\nexport class RtToolbarRightDirective {}\n\n/**\n * Универсальный тулбар с тремя секциями: left, center, right.\n * Секции задаются `<ng-template>` с директивами-маркерами и подставляются через `ngTemplateOutlet`.\n * Каждый модуль/фича подключает `rt-toolbar` в своём layout и наполняет нужные секции.\n *\n * @example\n * ```html\n * <rt-toolbar>\n * <ng-template rtToolbarLeft>\n * <button rtButton label=\"Создать\" />\n * <button rtButton label=\"Удалить\" appearance=\"text\" />\n * </ng-template>\n *\n * <ng-template rtToolbarCenter>\n * <span>Заявки</span>\n * </ng-template>\n *\n * <ng-template rtToolbarRight>\n * <input type=\"search\" [formControl]=\"searchCtrl\" />\n * </ng-template>\n * </rt-toolbar>\n * ```\n */\nconst BEM_BLOCK: string = 'rt-toolbar';\n\n@Component({\n selector: 'rt-toolbar',\n templateUrl: './rt-toolbar.component.html',\n styleUrls: ['./rt-toolbar.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 ],\n host: {\n class: BEM_BLOCK,\n '[class.rt-toolbar--dense]': 'dense()',\n },\n})\nexport class RtToolbarComponent {\n protected readonly leftTpl: Signal<TemplateRef<unknown> | undefined> = contentChild(RtToolbarLeftDirective, { read: TemplateRef });\n\n protected readonly centerTpl: Signal<TemplateRef<unknown> | undefined> = contentChild(RtToolbarCenterDirective, { read: TemplateRef });\n\n protected readonly rightTpl: Signal<TemplateRef<unknown> | undefined> = contentChild(RtToolbarRightDirective, { read: TemplateRef });\n\n /**\n * Компактная шапка (заголовок + иконки-действия): зоны остаются в одну строку\n * даже на мобилке. Без этого трёхзонный list-тулбар стекается в колонку на\n * ≤768px, что для узкой шапки (напр. rt-chat) неверно.\n */\n public readonly dense: InputSignalWithTransform<boolean, boolean | string> = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n}\n","@if (leftTpl() || centerTpl() || rightTpl()) {\n <ng-container rtBlock=\"rt-toolbar\">\n <div rtElem=\"bars\">\n @if (leftTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"left\" [rtMod]=\"{ left: true }\">\n <ng-container [ngTemplateOutlet]=\"leftTpl() ?? null\" />\n </div>\n }\n\n @if (centerTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"center\" [rtMod]=\"{ center: true }\">\n <ng-container [ngTemplateOutlet]=\"centerTpl() ?? null\" />\n </div>\n }\n\n @if (rightTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"right\" [rtMod]=\"{ right: true }\">\n <ng-container [ngTemplateOutlet]=\"rightTpl() ?? null\" />\n </div>\n }\n </div>\n </ng-container>\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-toolbar.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/toolbar/rt-toolbar.component.ts","../../../projects/ui-kit-v2/src/lib/components/toolbar/rt-toolbar.component.html"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n contentChild,\n Directive,\n input,\n InputSignalWithTransform,\n Signal,\n TemplateRef,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\n/**\n * Маркер-директива для контента в левой секции тулбара.\n *\n * @example\n * ```html\n * <rt-toolbar>\n * <ng-template rtToolbarLeft>\n * <button rtButton label=\"Создать\" />\n * </ng-template>\n * </rt-toolbar>\n * ```\n */\n@Directive({\n selector: '[rtToolbarLeft]',\n})\nexport class RtToolbarLeftDirective {}\n\n/**\n * Маркер-директива для контента в центральной секции тулбара.\n *\n * @example\n * ```html\n * <rt-toolbar>\n * <ng-template rtToolbarCenter>\n * <span>Заголовок страницы</span>\n * </ng-template>\n * </rt-toolbar>\n * ```\n */\n@Directive({\n selector: '[rtToolbarCenter]',\n})\nexport class RtToolbarCenterDirective {}\n\n/**\n * Маркер-директива для контента в правой секции тулбара.\n *\n * @example\n * ```html\n * <rt-toolbar>\n * <ng-template rtToolbarRight>\n * <input type=\"search\" placeholder=\"Поиск\" />\n * </ng-template>\n * </rt-toolbar>\n * ```\n */\n@Directive({\n selector: '[rtToolbarRight]',\n})\nexport class RtToolbarRightDirective {}\n\n/**\n * Универсальный тулбар с тремя секциями: left, center, right.\n * Секции задаются `<ng-template>` с директивами-маркерами и подставляются через `ngTemplateOutlet`.\n * Каждый модуль/фича подключает `rt-toolbar` в своём layout и наполняет нужные секции.\n *\n * @example\n * ```html\n * <rt-toolbar>\n * <ng-template rtToolbarLeft>\n * <button rtButton label=\"Создать\" />\n * <button rtButton label=\"Удалить\" appearance=\"text\" />\n * </ng-template>\n *\n * <ng-template rtToolbarCenter>\n * <span>Заявки</span>\n * </ng-template>\n *\n * <ng-template rtToolbarRight>\n * <input type=\"search\" [formControl]=\"searchCtrl\" />\n * </ng-template>\n * </rt-toolbar>\n * ```\n */\nconst BEM_BLOCK: string = 'rt-toolbar';\n\n@Component({\n selector: 'rt-toolbar',\n templateUrl: './rt-toolbar.component.html',\n styleUrls: ['./rt-toolbar.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 ],\n host: {\n class: BEM_BLOCK,\n '[class.rt-toolbar--dense]': 'dense()',\n },\n})\nexport class RtToolbarComponent {\n protected readonly leftTpl: Signal<TemplateRef<unknown> | undefined> = contentChild(RtToolbarLeftDirective, { read: TemplateRef });\n\n protected readonly centerTpl: Signal<TemplateRef<unknown> | undefined> = contentChild(RtToolbarCenterDirective, { read: TemplateRef });\n\n protected readonly rightTpl: Signal<TemplateRef<unknown> | undefined> = contentChild(RtToolbarRightDirective, { read: TemplateRef });\n\n /**\n * Компактная шапка (заголовок + иконки-действия): зоны остаются в одну строку\n * даже на мобилке. Без этого трёхзонный list-тулбар стекается в колонку на\n * ≤768px, что для узкой шапки (напр. rt-chat) неверно.\n */\n public readonly dense: InputSignalWithTransform<boolean, boolean | string> = input<boolean, boolean | string>(false, {\n transform: booleanAttribute,\n });\n}\n","@if (leftTpl() || centerTpl() || rightTpl()) {\n <ng-container rtBlock=\"rt-toolbar\">\n <div rtElem=\"bars\">\n @if (leftTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"left\" [rtMod]=\"{ left: true }\">\n <ng-container [ngTemplateOutlet]=\"leftTpl() ?? null\" />\n </div>\n }\n\n @if (centerTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"center\" [rtMod]=\"{ center: true }\">\n <ng-container [ngTemplateOutlet]=\"centerTpl() ?? null\" />\n </div>\n }\n\n @if (rightTpl()) {\n <div rtElem=\"bar\" qa-dataid=\"toolbar-bar\" data-slot=\"right\" [rtMod]=\"{ right: true }\">\n <ng-container [ngTemplateOutlet]=\"rightTpl() ?? null\" />\n </div>\n }\n </div>\n </ng-container>\n}\n"],"mappings":"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"}
@@ -448,7 +448,7 @@ var RtWorkspaceComponent = class RtWorkspaceComponent {
448
448
  ],
449
449
  ngImport: i0,
450
450
  template: "<ng-container rtBlock=\"rt-workspace\">\n @if (listSlot()) {\n <section rtElem=\"list\" qa-dataid=\"workspace-list\">\n <ng-container [ngTemplateOutlet]=\"listSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n\n <div\n rtElem=\"handle\"\n qa-dataid=\"workspace-handle-list\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n tabindex=\"0\"\n [attr.aria-label]=\"t().uiResizeList\"\n [rtMod]=\"{ list: true }\"\n [attr.aria-valuenow]=\"listWidth()\"\n [attr.aria-valuemin]=\"listMinWidth()\"\n [attr.aria-valuemax]=\"listMaxWidth()\"\n (pointerdown)=\"onHandlePointerDown($event, 'list')\"\n (dblclick)=\"onHandleReset('list')\"\n (keydown)=\"onHandleKeydown($event, 'list')\"></div>\n }\n\n <section rtElem=\"center\" qa-dataid=\"workspace-center\">\n @if (hasActive()) {\n <div rtElem=\"mobile-toolbar\">\n <rt-icon-button\n qa-dataid=\"workspace-back\"\n icon=\"arrow-left\"\n variant=\"secondary\"\n [ariaLabel]=\"t().uiBackToList\"\n [tooltip]=\"t().uiToList\"\n (clicked)=\"onBackClicked()\" />\n <rt-icon-button\n qa-dataid=\"workspace-open-details\"\n icon=\"info-circle\"\n variant=\"secondary\"\n [ariaLabel]=\"t().uiShowDetails\"\n [tooltip]=\"t().uiDetails\"\n (clicked)=\"openAside()\" />\n </div>\n }\n <ng-container [ngTemplateOutlet]=\"centerSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n\n @if (asideSlot()) {\n <div\n rtElem=\"handle\"\n qa-dataid=\"workspace-handle-aside\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n tabindex=\"0\"\n [attr.aria-label]=\"t().uiResizeDetails\"\n [rtMod]=\"{ aside: true }\"\n [attr.aria-valuenow]=\"asideWidth()\"\n [attr.aria-valuemin]=\"asideMinWidth()\"\n [attr.aria-valuemax]=\"asideMaxWidth()\"\n (pointerdown)=\"onHandlePointerDown($event, 'aside')\"\n (dblclick)=\"onHandleReset('aside')\"\n (keydown)=\"onHandleKeydown($event, 'aside')\"></div>\n\n <section rtElem=\"aside\" qa-dataid=\"workspace-aside\" [rtMod]=\"{ open: asideOpen() }\">\n <ng-container [ngTemplateOutlet]=\"asideSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n }\n</ng-container>\n",
451
- styles: ["@layer rt-kit.components{.rt-workspace{--rt-workspace-border-width: var(--rt-border-width-thin);--rt-workspace-handle-line-width: var(--rt-border-width-medium);--rt-workspace-handle-transition-duration: var(--rt-duration-fast);--rt-workspace-panel-transition-duration: var(--rt-duration-base);--rt-workspace-aside-shadow: var(--rt-shadow-md);position:relative;display:flex;flex-direction:row;block-size:calc(100dvh - var(--rt-header-height, 0px));min-block-size:0}.rt-workspace__list{display:flex;flex:0 0 var(--rt-workspace-list-size, 320px);flex-direction:column;border-inline-end:var(--rt-workspace-border-width) solid var(--rt-color-border-strong);min-inline-size:0}.rt-workspace__center{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;min-inline-size:0;padding-inline:var(--rt-space-4)}.rt-workspace__mobile-toolbar{display:none}.rt-workspace__aside{display:flex;flex:0 0 var(--rt-workspace-aside-size, 360px);flex-direction:column;border-inline-start:var(--rt-workspace-border-width) solid var(--rt-color-border-strong);min-inline-size:0}.rt-workspace__handle{position:relative;z-index:1;flex:0 0 auto;background:transparent;cursor:col-resize;inline-size:var(--rt-space-2);margin-inline:calc(-1 * var(--rt-space-1));touch-action:none}.rt-workspace__handle:before{position:absolute;background:transparent;content:\"\";inline-size:var(--rt-workspace-handle-line-width);inset-block:0;inset-inline-start:50%;transform:translate(-50%);transition:background var(--rt-workspace-handle-transition-duration) ease}.rt-workspace__handle:hover:before,.rt-workspace__handle:focus-visible:before{background:var(--rt-color-border-strong)}.rt-workspace__handle:focus-visible{outline:none}.rt-workspace__handle:focus-visible:before{background:var(--rt-color-border-focus)}@media(width<=1080px){.rt-workspace__desktop-only{display:none}}@media(width<=1080px){.rt-workspace__mobile-toolbar{display:flex;justify-content:space-between;padding:var(--rt-space-2) var(--rt-space-4) 0}.rt-workspace__handle{display:none}.rt-workspace__aside{position:absolute;z-index:2;flex-basis:360px;background:var(--rt-color-bg-surface);box-shadow:var(--rt-workspace-aside-shadow);inset-block:0;inset-inline-end:0;max-inline-size:90%;transform:translate(100%);transition:transform var(--rt-workspace-panel-transition-duration) ease}.rt-workspace__aside--open{transform:translate(0)}}@media(width<=768px){.rt-workspace__list{flex-basis:100%}}@media(width>1080px){.rt-workspace__aside{overflow:hidden;transition:flex-basis var(--rt-workspace-panel-transition-duration) ease,border-inline-start-width var(--rt-workspace-panel-transition-duration) ease,opacity var(--rt-workspace-panel-transition-duration) ease;will-change:flex-basis}}@media(width<=768px){.rt-workspace--has-active .rt-workspace__list{display:none}.rt-workspace--has-active .rt-workspace__center{flex-basis:100%}}@media(width>1080px){.rt-workspace--aside-collapsed .rt-workspace__aside{flex-basis:0;border-inline-start-width:0;min-inline-size:0;opacity:0;pointer-events:none;transition:flex-basis var(--rt-workspace-panel-transition-duration) ease,border-inline-start-width var(--rt-workspace-panel-transition-duration) ease,opacity var(--rt-workspace-panel-transition-duration) ease,visibility 0s linear var(--rt-workspace-panel-transition-duration);visibility:hidden}.rt-workspace--aside-collapsed .rt-workspace__handle--aside{display:none}}.rt-workspace--resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.rt-workspace--resizing .rt-workspace__list,.rt-workspace--resizing .rt-workspace__aside{transition:none}@media(prefers-reduced-motion:reduce){.rt-workspace__aside{transition:none}}}\n"],
451
+ styles: ["@layer rt-kit.components{.rt-workspace{--rt-workspace-border-width: var(--rt-border-width-thin);--rt-workspace-handle-line-width: var(--rt-border-width-medium);--rt-workspace-handle-transition-duration: var(--rt-duration-fast);--rt-workspace-panel-transition-duration: var(--rt-duration-base);--rt-workspace-aside-shadow: var(--rt-shadow-md);position:relative;display:flex;flex-direction:row;block-size:calc(100dvh - var(--rt-header-height, 0px));min-block-size:0}.rt-workspace__list{display:flex;flex:0 0 var(--rt-workspace-list-size, 320px);flex-direction:column;border-inline-end:var(--rt-workspace-border-width) solid var(--rt-color-border-strong);min-inline-size:0}.rt-workspace__center{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;min-inline-size:0;padding-inline:var(--rt-space-4)}.rt-workspace__mobile-toolbar{display:none}.rt-workspace__aside{display:flex;flex:0 0 var(--rt-workspace-aside-size, 360px);flex-direction:column;border-inline-start:var(--rt-workspace-border-width) solid var(--rt-color-border-strong);min-inline-size:0}.rt-workspace__handle{position:relative;z-index:1;flex:0 0 auto;background:transparent;cursor:col-resize;inline-size:var(--rt-space-2);margin-inline:calc(-1 * var(--rt-space-1));touch-action:none}.rt-workspace__handle:before{position:absolute;background:transparent;content:\"\";inline-size:var(--rt-workspace-handle-line-width);inset-block:0;inset-inline-start:50%;transform:translate(-50%);transition:background var(--rt-workspace-handle-transition-duration) ease}.rt-workspace__handle:hover:before,.rt-workspace__handle:focus-visible:before{background:var(--rt-color-border-strong)}.rt-workspace__handle:focus-visible{outline:none}.rt-workspace__handle:focus-visible:before{background:var(--rt-color-border-focus)}@container rt-place (width <= 1080px){.rt-workspace__desktop-only{display:none}}@container rt-place (width <= 1080px){.rt-workspace__mobile-toolbar{display:flex;justify-content:space-between;padding:var(--rt-space-2) var(--rt-space-4) 0}.rt-workspace__handle{display:none}.rt-workspace__aside{position:absolute;z-index:2;flex-basis:360px;background:var(--rt-color-bg-surface);box-shadow:var(--rt-workspace-aside-shadow);inset-block:0;inset-inline-end:0;max-inline-size:90%;transform:translate(100%);transition:transform var(--rt-workspace-panel-transition-duration) ease}.rt-workspace__aside--open{transform:translate(0)}}@container rt-place (width <= 768px){.rt-workspace__list{flex-basis:100%}}@container rt-place (width > 1080px){.rt-workspace__aside{overflow:hidden;transition:flex-basis var(--rt-workspace-panel-transition-duration) ease,border-inline-start-width var(--rt-workspace-panel-transition-duration) ease,opacity var(--rt-workspace-panel-transition-duration) ease;will-change:flex-basis}}@container rt-place (width <= 768px){.rt-workspace--has-active .rt-workspace__list{display:none}.rt-workspace--has-active .rt-workspace__center{flex-basis:100%}}@container rt-place (width > 1080px){.rt-workspace--aside-collapsed .rt-workspace__aside{flex-basis:0;border-inline-start-width:0;min-inline-size:0;opacity:0;pointer-events:none;transition:flex-basis var(--rt-workspace-panel-transition-duration) ease,border-inline-start-width var(--rt-workspace-panel-transition-duration) ease,opacity var(--rt-workspace-panel-transition-duration) ease,visibility 0s linear var(--rt-workspace-panel-transition-duration);visibility:hidden}.rt-workspace--aside-collapsed .rt-workspace__handle--aside{display:none}}.rt-workspace--resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.rt-workspace--resizing .rt-workspace__list,.rt-workspace--resizing .rt-workspace__aside{transition:none}@media(prefers-reduced-motion:reduce){.rt-workspace__aside{transition:none}}}\n"],
452
452
  dependencies: [
453
453
  {
454
454
  kind: "directive",
@@ -535,7 +535,7 @@ i0.ɵɵngDeclareClassMetadata({
535
535
  "[style.--rt-workspace-aside-size]": "asideWidth() + 'px'"
536
536
  },
537
537
  template: "<ng-container rtBlock=\"rt-workspace\">\n @if (listSlot()) {\n <section rtElem=\"list\" qa-dataid=\"workspace-list\">\n <ng-container [ngTemplateOutlet]=\"listSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n\n <div\n rtElem=\"handle\"\n qa-dataid=\"workspace-handle-list\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n tabindex=\"0\"\n [attr.aria-label]=\"t().uiResizeList\"\n [rtMod]=\"{ list: true }\"\n [attr.aria-valuenow]=\"listWidth()\"\n [attr.aria-valuemin]=\"listMinWidth()\"\n [attr.aria-valuemax]=\"listMaxWidth()\"\n (pointerdown)=\"onHandlePointerDown($event, 'list')\"\n (dblclick)=\"onHandleReset('list')\"\n (keydown)=\"onHandleKeydown($event, 'list')\"></div>\n }\n\n <section rtElem=\"center\" qa-dataid=\"workspace-center\">\n @if (hasActive()) {\n <div rtElem=\"mobile-toolbar\">\n <rt-icon-button\n qa-dataid=\"workspace-back\"\n icon=\"arrow-left\"\n variant=\"secondary\"\n [ariaLabel]=\"t().uiBackToList\"\n [tooltip]=\"t().uiToList\"\n (clicked)=\"onBackClicked()\" />\n <rt-icon-button\n qa-dataid=\"workspace-open-details\"\n icon=\"info-circle\"\n variant=\"secondary\"\n [ariaLabel]=\"t().uiShowDetails\"\n [tooltip]=\"t().uiDetails\"\n (clicked)=\"openAside()\" />\n </div>\n }\n <ng-container [ngTemplateOutlet]=\"centerSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n\n @if (asideSlot()) {\n <div\n rtElem=\"handle\"\n qa-dataid=\"workspace-handle-aside\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n tabindex=\"0\"\n [attr.aria-label]=\"t().uiResizeDetails\"\n [rtMod]=\"{ aside: true }\"\n [attr.aria-valuenow]=\"asideWidth()\"\n [attr.aria-valuemin]=\"asideMinWidth()\"\n [attr.aria-valuemax]=\"asideMaxWidth()\"\n (pointerdown)=\"onHandlePointerDown($event, 'aside')\"\n (dblclick)=\"onHandleReset('aside')\"\n (keydown)=\"onHandleKeydown($event, 'aside')\"></div>\n\n <section rtElem=\"aside\" qa-dataid=\"workspace-aside\" [rtMod]=\"{ open: asideOpen() }\">\n <ng-container [ngTemplateOutlet]=\"asideSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n }\n</ng-container>\n",
538
- styles: ["@layer rt-kit.components{.rt-workspace{--rt-workspace-border-width: var(--rt-border-width-thin);--rt-workspace-handle-line-width: var(--rt-border-width-medium);--rt-workspace-handle-transition-duration: var(--rt-duration-fast);--rt-workspace-panel-transition-duration: var(--rt-duration-base);--rt-workspace-aside-shadow: var(--rt-shadow-md);position:relative;display:flex;flex-direction:row;block-size:calc(100dvh - var(--rt-header-height, 0px));min-block-size:0}.rt-workspace__list{display:flex;flex:0 0 var(--rt-workspace-list-size, 320px);flex-direction:column;border-inline-end:var(--rt-workspace-border-width) solid var(--rt-color-border-strong);min-inline-size:0}.rt-workspace__center{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;min-inline-size:0;padding-inline:var(--rt-space-4)}.rt-workspace__mobile-toolbar{display:none}.rt-workspace__aside{display:flex;flex:0 0 var(--rt-workspace-aside-size, 360px);flex-direction:column;border-inline-start:var(--rt-workspace-border-width) solid var(--rt-color-border-strong);min-inline-size:0}.rt-workspace__handle{position:relative;z-index:1;flex:0 0 auto;background:transparent;cursor:col-resize;inline-size:var(--rt-space-2);margin-inline:calc(-1 * var(--rt-space-1));touch-action:none}.rt-workspace__handle:before{position:absolute;background:transparent;content:\"\";inline-size:var(--rt-workspace-handle-line-width);inset-block:0;inset-inline-start:50%;transform:translate(-50%);transition:background var(--rt-workspace-handle-transition-duration) ease}.rt-workspace__handle:hover:before,.rt-workspace__handle:focus-visible:before{background:var(--rt-color-border-strong)}.rt-workspace__handle:focus-visible{outline:none}.rt-workspace__handle:focus-visible:before{background:var(--rt-color-border-focus)}@media(width<=1080px){.rt-workspace__desktop-only{display:none}}@media(width<=1080px){.rt-workspace__mobile-toolbar{display:flex;justify-content:space-between;padding:var(--rt-space-2) var(--rt-space-4) 0}.rt-workspace__handle{display:none}.rt-workspace__aside{position:absolute;z-index:2;flex-basis:360px;background:var(--rt-color-bg-surface);box-shadow:var(--rt-workspace-aside-shadow);inset-block:0;inset-inline-end:0;max-inline-size:90%;transform:translate(100%);transition:transform var(--rt-workspace-panel-transition-duration) ease}.rt-workspace__aside--open{transform:translate(0)}}@media(width<=768px){.rt-workspace__list{flex-basis:100%}}@media(width>1080px){.rt-workspace__aside{overflow:hidden;transition:flex-basis var(--rt-workspace-panel-transition-duration) ease,border-inline-start-width var(--rt-workspace-panel-transition-duration) ease,opacity var(--rt-workspace-panel-transition-duration) ease;will-change:flex-basis}}@media(width<=768px){.rt-workspace--has-active .rt-workspace__list{display:none}.rt-workspace--has-active .rt-workspace__center{flex-basis:100%}}@media(width>1080px){.rt-workspace--aside-collapsed .rt-workspace__aside{flex-basis:0;border-inline-start-width:0;min-inline-size:0;opacity:0;pointer-events:none;transition:flex-basis var(--rt-workspace-panel-transition-duration) ease,border-inline-start-width var(--rt-workspace-panel-transition-duration) ease,opacity var(--rt-workspace-panel-transition-duration) ease,visibility 0s linear var(--rt-workspace-panel-transition-duration);visibility:hidden}.rt-workspace--aside-collapsed .rt-workspace__handle--aside{display:none}}.rt-workspace--resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.rt-workspace--resizing .rt-workspace__list,.rt-workspace--resizing .rt-workspace__aside{transition:none}@media(prefers-reduced-motion:reduce){.rt-workspace__aside{transition:none}}}\n"]
538
+ styles: ["@layer rt-kit.components{.rt-workspace{--rt-workspace-border-width: var(--rt-border-width-thin);--rt-workspace-handle-line-width: var(--rt-border-width-medium);--rt-workspace-handle-transition-duration: var(--rt-duration-fast);--rt-workspace-panel-transition-duration: var(--rt-duration-base);--rt-workspace-aside-shadow: var(--rt-shadow-md);position:relative;display:flex;flex-direction:row;block-size:calc(100dvh - var(--rt-header-height, 0px));min-block-size:0}.rt-workspace__list{display:flex;flex:0 0 var(--rt-workspace-list-size, 320px);flex-direction:column;border-inline-end:var(--rt-workspace-border-width) solid var(--rt-color-border-strong);min-inline-size:0}.rt-workspace__center{display:flex;flex:1 1 auto;flex-direction:column;min-block-size:0;min-inline-size:0;padding-inline:var(--rt-space-4)}.rt-workspace__mobile-toolbar{display:none}.rt-workspace__aside{display:flex;flex:0 0 var(--rt-workspace-aside-size, 360px);flex-direction:column;border-inline-start:var(--rt-workspace-border-width) solid var(--rt-color-border-strong);min-inline-size:0}.rt-workspace__handle{position:relative;z-index:1;flex:0 0 auto;background:transparent;cursor:col-resize;inline-size:var(--rt-space-2);margin-inline:calc(-1 * var(--rt-space-1));touch-action:none}.rt-workspace__handle:before{position:absolute;background:transparent;content:\"\";inline-size:var(--rt-workspace-handle-line-width);inset-block:0;inset-inline-start:50%;transform:translate(-50%);transition:background var(--rt-workspace-handle-transition-duration) ease}.rt-workspace__handle:hover:before,.rt-workspace__handle:focus-visible:before{background:var(--rt-color-border-strong)}.rt-workspace__handle:focus-visible{outline:none}.rt-workspace__handle:focus-visible:before{background:var(--rt-color-border-focus)}@container rt-place (width <= 1080px){.rt-workspace__desktop-only{display:none}}@container rt-place (width <= 1080px){.rt-workspace__mobile-toolbar{display:flex;justify-content:space-between;padding:var(--rt-space-2) var(--rt-space-4) 0}.rt-workspace__handle{display:none}.rt-workspace__aside{position:absolute;z-index:2;flex-basis:360px;background:var(--rt-color-bg-surface);box-shadow:var(--rt-workspace-aside-shadow);inset-block:0;inset-inline-end:0;max-inline-size:90%;transform:translate(100%);transition:transform var(--rt-workspace-panel-transition-duration) ease}.rt-workspace__aside--open{transform:translate(0)}}@container rt-place (width <= 768px){.rt-workspace__list{flex-basis:100%}}@container rt-place (width > 1080px){.rt-workspace__aside{overflow:hidden;transition:flex-basis var(--rt-workspace-panel-transition-duration) ease,border-inline-start-width var(--rt-workspace-panel-transition-duration) ease,opacity var(--rt-workspace-panel-transition-duration) ease;will-change:flex-basis}}@container rt-place (width <= 768px){.rt-workspace--has-active .rt-workspace__list{display:none}.rt-workspace--has-active .rt-workspace__center{flex-basis:100%}}@container rt-place (width > 1080px){.rt-workspace--aside-collapsed .rt-workspace__aside{flex-basis:0;border-inline-start-width:0;min-inline-size:0;opacity:0;pointer-events:none;transition:flex-basis var(--rt-workspace-panel-transition-duration) ease,border-inline-start-width var(--rt-workspace-panel-transition-duration) ease,opacity var(--rt-workspace-panel-transition-duration) ease,visibility 0s linear var(--rt-workspace-panel-transition-duration);visibility:hidden}.rt-workspace--aside-collapsed .rt-workspace__handle--aside{display:none}}.rt-workspace--resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.rt-workspace--resizing .rt-workspace__list,.rt-workspace--resizing .rt-workspace__aside{transition:none}@media(prefers-reduced-motion:reduce){.rt-workspace__aside{transition:none}}}\n"]
539
539
  }]
540
540
  }],
541
541
  ctorParameters: () => [],
@@ -1 +1 @@
1
- {"version":3,"file":"rt-tools-ui-kit-v2-workspace.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/workspace/rt-workspace.directives.ts","../../../projects/ui-kit-v2/src/lib/components/workspace/rt-workspace.component.ts","../../../projects/ui-kit-v2/src/lib/components/workspace/rt-workspace.component.html"],"sourcesContent":["import { Directive, inject, TemplateRef } from '@angular/core';\n\nimport { IRtWorkspace } from './rt-workspace.model';\n\n@Directive({\n selector: '[rtWorkspaceDesktopOnly]',\n host: {\n class: 'rt-workspace__desktop-only',\n },\n})\nexport class RtWorkspaceDesktopOnlyDirective {}\n\n@Directive({\n selector: '[rtWorkspaceList]',\n})\nexport class RtWorkspaceListDirective {\n public readonly templateRef: TemplateRef<IRtWorkspace.SlotContext> = inject<TemplateRef<IRtWorkspace.SlotContext>>(TemplateRef);\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- второй довод стража контекста шаблона стоит только в типе-предикате; убрать его нечем, подпись задаёт каркас\n public static ngTemplateContextGuard(_directive: RtWorkspaceListDirective, context: unknown): context is IRtWorkspace.SlotContext {\n return true;\n }\n}\n\n@Directive({\n selector: '[rtWorkspaceCenter]',\n})\nexport class RtWorkspaceCenterDirective {\n public readonly templateRef: TemplateRef<IRtWorkspace.SlotContext> = inject<TemplateRef<IRtWorkspace.SlotContext>>(TemplateRef);\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- второй довод стража контекста шаблона стоит только в типе-предикате; убрать его нечем, подпись задаёт каркас\n public static ngTemplateContextGuard(_directive: RtWorkspaceCenterDirective, context: unknown): context is IRtWorkspace.SlotContext {\n return true;\n }\n}\n\n@Directive({\n selector: '[rtWorkspaceAside]',\n})\nexport class RtWorkspaceAsideDirective {\n public readonly templateRef: TemplateRef<IRtWorkspace.SlotContext> = inject<TemplateRef<IRtWorkspace.SlotContext>>(TemplateRef);\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- второй довод стража контекста шаблона стоит только в типе-предикате; убрать его нечем, подпись задаёт каркас\n public static ngTemplateContextGuard(_directive: RtWorkspaceAsideDirective, context: unknown): context is IRtWorkspace.SlotContext {\n return true;\n }\n}\n","import { BooleanInput } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n DestroyRef,\n effect,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n numberAttribute,\n output,\n OutputEmitterRef,\n Renderer2,\n signal,\n Signal,\n untracked,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { StorageService } from '@rt-tools/core';\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtWorkspaceAsideDirective, RtWorkspaceCenterDirective, RtWorkspaceListDirective } from './rt-workspace.directives';\nimport { IRtWorkspace } from './rt-workspace.model';\n\nconst BEM_BLOCK: string = 'rt-workspace';\nconst STORAGE_PREFIX: string = 'rt-workspace:';\nconst KEYBOARD_STEP: number = 16;\n\ninterface IDragState {\n kind: IRtWorkspace.PanelKind;\n startX: number;\n startWidth: number;\n}\n\n@Component({\n selector: 'rt-workspace',\n templateUrl: './rt-workspace.component.html',\n styleUrls: ['./rt-workspace.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n NgTemplateOutlet,\n\n // standalone components / directives\n RtIconButtonComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n host: {\n class: BEM_BLOCK,\n '[class.rt-workspace--has-active]': 'hasActive()',\n '[class.rt-workspace--aside-collapsed]': 'asideCollapsed()',\n '[class.rt-workspace--resizing]': 'resizing()',\n '[style.--rt-workspace-list-size]': \"listWidth() + 'px'\",\n '[style.--rt-workspace-aside-size]': \"asideWidth() + 'px'\",\n },\n})\nexport class RtWorkspaceComponent implements IRtWorkspace.PanelApi {\n readonly #storage: StorageService = inject(StorageService);\n\n readonly #renderer: Renderer2 = inject(Renderer2);\n\n readonly #hostRef: ElementRef<HTMLElement> = inject(ElementRef);\n\n readonly #destroyRef: DestroyRef = inject(DestroyRef);\n\n readonly #listWidthOverride: WritableSignal<number | null> = signal<number | null>(null);\n\n readonly #asideWidthOverride: WritableSignal<number | null> = signal<number | null>(null);\n\n readonly #asideCollapsed: WritableSignal<boolean> = signal<boolean>(false);\n\n readonly #asideOpen: WritableSignal<boolean> = signal<boolean>(false);\n\n readonly #resizing: WritableSignal<boolean> = signal<boolean>(false);\n\n #restoredKey: string | null = null;\n\n #dragState: IDragState | null = null;\n\n #detachDragListeners: (() => void) | null = null;\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly listSlot: Signal<RtWorkspaceListDirective | undefined> = contentChild(RtWorkspaceListDirective);\n\n protected readonly centerSlot: Signal<RtWorkspaceCenterDirective | undefined> = contentChild(RtWorkspaceCenterDirective);\n\n protected readonly asideSlot: Signal<RtWorkspaceAsideDirective | undefined> = contentChild(RtWorkspaceAsideDirective);\n\n protected readonly resizing: Signal<boolean> = this.#resizing.asReadonly();\n\n protected readonly slotContext: IRtWorkspace.SlotContext = { $implicit: this };\n\n public readonly storageKey: InputSignal<string | null> = input<string | null>(null);\n\n public readonly hasActive: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly listMinWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(240, {\n transform: numberAttribute,\n });\n\n public readonly listMaxWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(480, {\n transform: numberAttribute,\n });\n\n public readonly listDefaultWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(320, {\n transform: numberAttribute,\n });\n\n public readonly asideMinWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(280, {\n transform: numberAttribute,\n });\n\n public readonly asideMaxWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(560, {\n transform: numberAttribute,\n });\n\n public readonly asideDefaultWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(360, {\n transform: numberAttribute,\n });\n\n public readonly centerMinWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(360, {\n transform: numberAttribute,\n });\n\n public readonly backClicked: OutputEmitterRef<void> = output<void>();\n\n public readonly listWidth: Signal<number> = computed((): number => this.#listWidthOverride() ?? this.listDefaultWidth());\n\n public readonly asideWidth: Signal<number> = computed((): number => this.#asideWidthOverride() ?? this.asideDefaultWidth());\n\n public readonly asideCollapsed: Signal<boolean> = this.#asideCollapsed.asReadonly();\n\n public readonly asideOpen: Signal<boolean> = this.#asideOpen.asReadonly();\n\n constructor() {\n effect((): void => {\n const key: string | null = this.storageKey();\n if (key === null || key === this.#restoredKey) {\n return;\n }\n this.#restoredKey = key;\n untracked((): void => this.#restoreFromStorage(key));\n });\n\n this.#destroyRef.onDestroy((): void => this.#stopDragging());\n }\n\n public toggleAsideCollapsed(): void {\n this.#asideCollapsed.update((collapsed: boolean): boolean => !collapsed);\n this.#persist();\n }\n\n public openAside(): void {\n this.#asideOpen.set(true);\n }\n\n public closeAside(): void {\n this.#asideOpen.set(false);\n }\n\n public toggleAside(): void {\n this.#asideOpen.update((open: boolean): boolean => !open);\n }\n\n protected onBackClicked(): void {\n this.closeAside();\n this.backClicked.emit();\n }\n\n protected onHandlePointerDown(event: PointerEvent, kind: IRtWorkspace.PanelKind): void {\n if (event.button !== 0) {\n return;\n }\n event.preventDefault();\n this.#dragState = {\n kind,\n startX: event.clientX,\n startWidth: kind === 'list' ? this.listWidth() : this.asideWidth(),\n };\n this.#resizing.set(true);\n\n const detachMove: () => void = this.#renderer.listen('document', 'pointermove', (moveEvent: PointerEvent): void =>\n this.#onDragMove(moveEvent)\n );\n const detachUp: () => void = this.#renderer.listen('document', 'pointerup', (): void => {\n this.#persist();\n this.#stopDragging();\n });\n this.#detachDragListeners = (): void => {\n detachMove();\n detachUp();\n };\n }\n\n protected onHandleKeydown(event: KeyboardEvent, kind: IRtWorkspace.PanelKind): void {\n let delta: number;\n if (event.key === 'ArrowRight') {\n delta = kind === 'list' ? KEYBOARD_STEP : -KEYBOARD_STEP;\n } else if (event.key === 'ArrowLeft') {\n delta = kind === 'list' ? -KEYBOARD_STEP : KEYBOARD_STEP;\n } else {\n return;\n }\n event.preventDefault();\n const current: number = kind === 'list' ? this.listWidth() : this.asideWidth();\n this.#applyWidth(kind, current + delta);\n this.#persist();\n }\n\n protected onHandleReset(kind: IRtWorkspace.PanelKind): void {\n const override: WritableSignal<number | null> = kind === 'list' ? this.#listWidthOverride : this.#asideWidthOverride;\n override.set(null);\n this.#persist();\n }\n\n #onDragMove(event: PointerEvent): void {\n const drag: IDragState | null = this.#dragState;\n if (drag === null) {\n return;\n }\n const dx: number = event.clientX - drag.startX;\n const rawWidth: number = drag.kind === 'list' ? drag.startWidth + dx : drag.startWidth - dx;\n this.#applyWidth(drag.kind, rawWidth);\n }\n\n #applyWidth(kind: IRtWorkspace.PanelKind, rawWidth: number): void {\n const override: WritableSignal<number | null> = kind === 'list' ? this.#listWidthOverride : this.#asideWidthOverride;\n override.set(this.#clampWidth(kind, rawWidth));\n }\n\n #clampWidth(kind: IRtWorkspace.PanelKind, rawWidth: number): number {\n const min: number = kind === 'list' ? this.listMinWidth() : this.asideMinWidth();\n const configMax: number = kind === 'list' ? this.listMaxWidth() : this.asideMaxWidth();\n // Место соседней панели вычитается, только когда она объявлена: без её слота ширина\n // соседки — число из умолчаний, а места она не занимает вовсе.\n const otherWidth: number = this.#occupiedWidth(kind === 'list' ? 'aside' : 'list');\n const hostWidth: number = this.#hostRef.nativeElement.clientWidth;\n const available: number = hostWidth > 0 ? hostWidth - otherWidth - this.centerMinWidth() : Number.POSITIVE_INFINITY;\n const max: number = Math.max(min, Math.min(configMax, available));\n return Math.round(Math.min(max, Math.max(min, rawWidth)));\n }\n\n /** Сколько ширины занимает панель: необъявленная не занимает ничего. */\n #occupiedWidth(kind: IRtWorkspace.PanelKind): number {\n if (kind === 'list') {\n return this.listSlot() ? this.listWidth() : 0;\n }\n\n return this.asideSlot() ? this.asideWidth() : 0;\n }\n\n #stopDragging(): void {\n this.#detachDragListeners?.();\n this.#detachDragListeners = null;\n this.#dragState = null;\n this.#resizing.set(false);\n }\n\n #restoreFromStorage(key: string): void {\n const stored: IRtWorkspace.PersistedState | null =\n this.#storage.getItem<IRtWorkspace.PersistedState>(`${STORAGE_PREFIX}${key}`) ?? null;\n if (stored === null || typeof stored !== 'object') {\n return;\n }\n if (typeof stored.listWidth === 'number') {\n this.#listWidthOverride.set(this.#clampWidth('list', stored.listWidth));\n }\n if (typeof stored.asideWidth === 'number') {\n this.#asideWidthOverride.set(this.#clampWidth('aside', stored.asideWidth));\n }\n this.#asideCollapsed.set(stored.asideCollapsed === true);\n }\n\n #persist(): void {\n const key: string | null = this.storageKey();\n if (key === null) {\n return;\n }\n const state: IRtWorkspace.PersistedState = {\n listWidth: this.listWidth(),\n asideWidth: this.asideWidth(),\n asideCollapsed: this.asideCollapsed(),\n };\n this.#storage.setItem(`${STORAGE_PREFIX}${key}`, state);\n }\n}\n","<ng-container rtBlock=\"rt-workspace\">\n @if (listSlot()) {\n <section rtElem=\"list\" qa-dataid=\"workspace-list\">\n <ng-container [ngTemplateOutlet]=\"listSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n\n <div\n rtElem=\"handle\"\n qa-dataid=\"workspace-handle-list\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n tabindex=\"0\"\n [attr.aria-label]=\"t().uiResizeList\"\n [rtMod]=\"{ list: true }\"\n [attr.aria-valuenow]=\"listWidth()\"\n [attr.aria-valuemin]=\"listMinWidth()\"\n [attr.aria-valuemax]=\"listMaxWidth()\"\n (pointerdown)=\"onHandlePointerDown($event, 'list')\"\n (dblclick)=\"onHandleReset('list')\"\n (keydown)=\"onHandleKeydown($event, 'list')\"></div>\n }\n\n <section rtElem=\"center\" qa-dataid=\"workspace-center\">\n @if (hasActive()) {\n <div rtElem=\"mobile-toolbar\">\n <rt-icon-button\n qa-dataid=\"workspace-back\"\n icon=\"arrow-left\"\n variant=\"secondary\"\n [ariaLabel]=\"t().uiBackToList\"\n [tooltip]=\"t().uiToList\"\n (clicked)=\"onBackClicked()\" />\n <rt-icon-button\n qa-dataid=\"workspace-open-details\"\n icon=\"info-circle\"\n variant=\"secondary\"\n [ariaLabel]=\"t().uiShowDetails\"\n [tooltip]=\"t().uiDetails\"\n (clicked)=\"openAside()\" />\n </div>\n }\n <ng-container [ngTemplateOutlet]=\"centerSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n\n @if (asideSlot()) {\n <div\n rtElem=\"handle\"\n qa-dataid=\"workspace-handle-aside\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n tabindex=\"0\"\n [attr.aria-label]=\"t().uiResizeDetails\"\n [rtMod]=\"{ aside: true }\"\n [attr.aria-valuenow]=\"asideWidth()\"\n [attr.aria-valuemin]=\"asideMinWidth()\"\n [attr.aria-valuemax]=\"asideMaxWidth()\"\n (pointerdown)=\"onHandlePointerDown($event, 'aside')\"\n (dblclick)=\"onHandleReset('aside')\"\n (keydown)=\"onHandleKeydown($event, 'aside')\"></div>\n\n <section rtElem=\"aside\" qa-dataid=\"workspace-aside\" [rtMod]=\"{ open: asideOpen() }\">\n <ng-container [ngTemplateOutlet]=\"asideSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n }\n</ng-container>\n"],"mappings":"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"}
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-workspace.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/workspace/rt-workspace.directives.ts","../../../projects/ui-kit-v2/src/lib/components/workspace/rt-workspace.component.ts","../../../projects/ui-kit-v2/src/lib/components/workspace/rt-workspace.component.html"],"sourcesContent":["import { Directive, inject, TemplateRef } from '@angular/core';\n\nimport { IRtWorkspace } from './rt-workspace.model';\n\n@Directive({\n selector: '[rtWorkspaceDesktopOnly]',\n host: {\n class: 'rt-workspace__desktop-only',\n },\n})\nexport class RtWorkspaceDesktopOnlyDirective {}\n\n@Directive({\n selector: '[rtWorkspaceList]',\n})\nexport class RtWorkspaceListDirective {\n public readonly templateRef: TemplateRef<IRtWorkspace.SlotContext> = inject<TemplateRef<IRtWorkspace.SlotContext>>(TemplateRef);\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- второй довод стража контекста шаблона стоит только в типе-предикате; убрать его нечем, подпись задаёт каркас\n public static ngTemplateContextGuard(_directive: RtWorkspaceListDirective, context: unknown): context is IRtWorkspace.SlotContext {\n return true;\n }\n}\n\n@Directive({\n selector: '[rtWorkspaceCenter]',\n})\nexport class RtWorkspaceCenterDirective {\n public readonly templateRef: TemplateRef<IRtWorkspace.SlotContext> = inject<TemplateRef<IRtWorkspace.SlotContext>>(TemplateRef);\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- второй довод стража контекста шаблона стоит только в типе-предикате; убрать его нечем, подпись задаёт каркас\n public static ngTemplateContextGuard(_directive: RtWorkspaceCenterDirective, context: unknown): context is IRtWorkspace.SlotContext {\n return true;\n }\n}\n\n@Directive({\n selector: '[rtWorkspaceAside]',\n})\nexport class RtWorkspaceAsideDirective {\n public readonly templateRef: TemplateRef<IRtWorkspace.SlotContext> = inject<TemplateRef<IRtWorkspace.SlotContext>>(TemplateRef);\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- второй довод стража контекста шаблона стоит только в типе-предикате; убрать его нечем, подпись задаёт каркас\n public static ngTemplateContextGuard(_directive: RtWorkspaceAsideDirective, context: unknown): context is IRtWorkspace.SlotContext {\n return true;\n }\n}\n","import { BooleanInput } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n DestroyRef,\n effect,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n numberAttribute,\n output,\n OutputEmitterRef,\n Renderer2,\n signal,\n Signal,\n untracked,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { StorageService } from '@rt-tools/core';\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtWorkspaceAsideDirective, RtWorkspaceCenterDirective, RtWorkspaceListDirective } from './rt-workspace.directives';\nimport { IRtWorkspace } from './rt-workspace.model';\n\nconst BEM_BLOCK: string = 'rt-workspace';\nconst STORAGE_PREFIX: string = 'rt-workspace:';\nconst KEYBOARD_STEP: number = 16;\n\ninterface IDragState {\n kind: IRtWorkspace.PanelKind;\n startX: number;\n startWidth: number;\n}\n\n@Component({\n selector: 'rt-workspace',\n templateUrl: './rt-workspace.component.html',\n styleUrls: ['./rt-workspace.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n NgTemplateOutlet,\n\n // standalone components / directives\n RtIconButtonComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n host: {\n class: BEM_BLOCK,\n '[class.rt-workspace--has-active]': 'hasActive()',\n '[class.rt-workspace--aside-collapsed]': 'asideCollapsed()',\n '[class.rt-workspace--resizing]': 'resizing()',\n '[style.--rt-workspace-list-size]': \"listWidth() + 'px'\",\n '[style.--rt-workspace-aside-size]': \"asideWidth() + 'px'\",\n },\n})\nexport class RtWorkspaceComponent implements IRtWorkspace.PanelApi {\n readonly #storage: StorageService = inject(StorageService);\n\n readonly #renderer: Renderer2 = inject(Renderer2);\n\n readonly #hostRef: ElementRef<HTMLElement> = inject(ElementRef);\n\n readonly #destroyRef: DestroyRef = inject(DestroyRef);\n\n readonly #listWidthOverride: WritableSignal<number | null> = signal<number | null>(null);\n\n readonly #asideWidthOverride: WritableSignal<number | null> = signal<number | null>(null);\n\n readonly #asideCollapsed: WritableSignal<boolean> = signal<boolean>(false);\n\n readonly #asideOpen: WritableSignal<boolean> = signal<boolean>(false);\n\n readonly #resizing: WritableSignal<boolean> = signal<boolean>(false);\n\n #restoredKey: string | null = null;\n\n #dragState: IDragState | null = null;\n\n #detachDragListeners: (() => void) | null = null;\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly listSlot: Signal<RtWorkspaceListDirective | undefined> = contentChild(RtWorkspaceListDirective);\n\n protected readonly centerSlot: Signal<RtWorkspaceCenterDirective | undefined> = contentChild(RtWorkspaceCenterDirective);\n\n protected readonly asideSlot: Signal<RtWorkspaceAsideDirective | undefined> = contentChild(RtWorkspaceAsideDirective);\n\n protected readonly resizing: Signal<boolean> = this.#resizing.asReadonly();\n\n protected readonly slotContext: IRtWorkspace.SlotContext = { $implicit: this };\n\n public readonly storageKey: InputSignal<string | null> = input<string | null>(null);\n\n public readonly hasActive: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly listMinWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(240, {\n transform: numberAttribute,\n });\n\n public readonly listMaxWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(480, {\n transform: numberAttribute,\n });\n\n public readonly listDefaultWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(320, {\n transform: numberAttribute,\n });\n\n public readonly asideMinWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(280, {\n transform: numberAttribute,\n });\n\n public readonly asideMaxWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(560, {\n transform: numberAttribute,\n });\n\n public readonly asideDefaultWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(360, {\n transform: numberAttribute,\n });\n\n public readonly centerMinWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(360, {\n transform: numberAttribute,\n });\n\n public readonly backClicked: OutputEmitterRef<void> = output<void>();\n\n public readonly listWidth: Signal<number> = computed((): number => this.#listWidthOverride() ?? this.listDefaultWidth());\n\n public readonly asideWidth: Signal<number> = computed((): number => this.#asideWidthOverride() ?? this.asideDefaultWidth());\n\n public readonly asideCollapsed: Signal<boolean> = this.#asideCollapsed.asReadonly();\n\n public readonly asideOpen: Signal<boolean> = this.#asideOpen.asReadonly();\n\n constructor() {\n effect((): void => {\n const key: string | null = this.storageKey();\n if (key === null || key === this.#restoredKey) {\n return;\n }\n this.#restoredKey = key;\n untracked((): void => this.#restoreFromStorage(key));\n });\n\n this.#destroyRef.onDestroy((): void => this.#stopDragging());\n }\n\n public toggleAsideCollapsed(): void {\n this.#asideCollapsed.update((collapsed: boolean): boolean => !collapsed);\n this.#persist();\n }\n\n public openAside(): void {\n this.#asideOpen.set(true);\n }\n\n public closeAside(): void {\n this.#asideOpen.set(false);\n }\n\n public toggleAside(): void {\n this.#asideOpen.update((open: boolean): boolean => !open);\n }\n\n protected onBackClicked(): void {\n this.closeAside();\n this.backClicked.emit();\n }\n\n protected onHandlePointerDown(event: PointerEvent, kind: IRtWorkspace.PanelKind): void {\n if (event.button !== 0) {\n return;\n }\n event.preventDefault();\n this.#dragState = {\n kind,\n startX: event.clientX,\n startWidth: kind === 'list' ? this.listWidth() : this.asideWidth(),\n };\n this.#resizing.set(true);\n\n const detachMove: () => void = this.#renderer.listen('document', 'pointermove', (moveEvent: PointerEvent): void =>\n this.#onDragMove(moveEvent)\n );\n const detachUp: () => void = this.#renderer.listen('document', 'pointerup', (): void => {\n this.#persist();\n this.#stopDragging();\n });\n this.#detachDragListeners = (): void => {\n detachMove();\n detachUp();\n };\n }\n\n protected onHandleKeydown(event: KeyboardEvent, kind: IRtWorkspace.PanelKind): void {\n let delta: number;\n if (event.key === 'ArrowRight') {\n delta = kind === 'list' ? KEYBOARD_STEP : -KEYBOARD_STEP;\n } else if (event.key === 'ArrowLeft') {\n delta = kind === 'list' ? -KEYBOARD_STEP : KEYBOARD_STEP;\n } else {\n return;\n }\n event.preventDefault();\n const current: number = kind === 'list' ? this.listWidth() : this.asideWidth();\n this.#applyWidth(kind, current + delta);\n this.#persist();\n }\n\n protected onHandleReset(kind: IRtWorkspace.PanelKind): void {\n const override: WritableSignal<number | null> = kind === 'list' ? this.#listWidthOverride : this.#asideWidthOverride;\n override.set(null);\n this.#persist();\n }\n\n #onDragMove(event: PointerEvent): void {\n const drag: IDragState | null = this.#dragState;\n if (drag === null) {\n return;\n }\n const dx: number = event.clientX - drag.startX;\n const rawWidth: number = drag.kind === 'list' ? drag.startWidth + dx : drag.startWidth - dx;\n this.#applyWidth(drag.kind, rawWidth);\n }\n\n #applyWidth(kind: IRtWorkspace.PanelKind, rawWidth: number): void {\n const override: WritableSignal<number | null> = kind === 'list' ? this.#listWidthOverride : this.#asideWidthOverride;\n override.set(this.#clampWidth(kind, rawWidth));\n }\n\n #clampWidth(kind: IRtWorkspace.PanelKind, rawWidth: number): number {\n const min: number = kind === 'list' ? this.listMinWidth() : this.asideMinWidth();\n const configMax: number = kind === 'list' ? this.listMaxWidth() : this.asideMaxWidth();\n // Место соседней панели вычитается, только когда она объявлена: без её слота ширина\n // соседки — число из умолчаний, а места она не занимает вовсе.\n const otherWidth: number = this.#occupiedWidth(kind === 'list' ? 'aside' : 'list');\n const hostWidth: number = this.#hostRef.nativeElement.clientWidth;\n const available: number = hostWidth > 0 ? hostWidth - otherWidth - this.centerMinWidth() : Number.POSITIVE_INFINITY;\n const max: number = Math.max(min, Math.min(configMax, available));\n return Math.round(Math.min(max, Math.max(min, rawWidth)));\n }\n\n /** Сколько ширины занимает панель: необъявленная не занимает ничего. */\n #occupiedWidth(kind: IRtWorkspace.PanelKind): number {\n if (kind === 'list') {\n return this.listSlot() ? this.listWidth() : 0;\n }\n\n return this.asideSlot() ? this.asideWidth() : 0;\n }\n\n #stopDragging(): void {\n this.#detachDragListeners?.();\n this.#detachDragListeners = null;\n this.#dragState = null;\n this.#resizing.set(false);\n }\n\n #restoreFromStorage(key: string): void {\n const stored: IRtWorkspace.PersistedState | null =\n this.#storage.getItem<IRtWorkspace.PersistedState>(`${STORAGE_PREFIX}${key}`) ?? null;\n if (stored === null || typeof stored !== 'object') {\n return;\n }\n if (typeof stored.listWidth === 'number') {\n this.#listWidthOverride.set(this.#clampWidth('list', stored.listWidth));\n }\n if (typeof stored.asideWidth === 'number') {\n this.#asideWidthOverride.set(this.#clampWidth('aside', stored.asideWidth));\n }\n this.#asideCollapsed.set(stored.asideCollapsed === true);\n }\n\n #persist(): void {\n const key: string | null = this.storageKey();\n if (key === null) {\n return;\n }\n const state: IRtWorkspace.PersistedState = {\n listWidth: this.listWidth(),\n asideWidth: this.asideWidth(),\n asideCollapsed: this.asideCollapsed(),\n };\n this.#storage.setItem(`${STORAGE_PREFIX}${key}`, state);\n }\n}\n","<ng-container rtBlock=\"rt-workspace\">\n @if (listSlot()) {\n <section rtElem=\"list\" qa-dataid=\"workspace-list\">\n <ng-container [ngTemplateOutlet]=\"listSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n\n <div\n rtElem=\"handle\"\n qa-dataid=\"workspace-handle-list\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n tabindex=\"0\"\n [attr.aria-label]=\"t().uiResizeList\"\n [rtMod]=\"{ list: true }\"\n [attr.aria-valuenow]=\"listWidth()\"\n [attr.aria-valuemin]=\"listMinWidth()\"\n [attr.aria-valuemax]=\"listMaxWidth()\"\n (pointerdown)=\"onHandlePointerDown($event, 'list')\"\n (dblclick)=\"onHandleReset('list')\"\n (keydown)=\"onHandleKeydown($event, 'list')\"></div>\n }\n\n <section rtElem=\"center\" qa-dataid=\"workspace-center\">\n @if (hasActive()) {\n <div rtElem=\"mobile-toolbar\">\n <rt-icon-button\n qa-dataid=\"workspace-back\"\n icon=\"arrow-left\"\n variant=\"secondary\"\n [ariaLabel]=\"t().uiBackToList\"\n [tooltip]=\"t().uiToList\"\n (clicked)=\"onBackClicked()\" />\n <rt-icon-button\n qa-dataid=\"workspace-open-details\"\n icon=\"info-circle\"\n variant=\"secondary\"\n [ariaLabel]=\"t().uiShowDetails\"\n [tooltip]=\"t().uiDetails\"\n (clicked)=\"openAside()\" />\n </div>\n }\n <ng-container [ngTemplateOutlet]=\"centerSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n\n @if (asideSlot()) {\n <div\n rtElem=\"handle\"\n qa-dataid=\"workspace-handle-aside\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n tabindex=\"0\"\n [attr.aria-label]=\"t().uiResizeDetails\"\n [rtMod]=\"{ aside: true }\"\n [attr.aria-valuenow]=\"asideWidth()\"\n [attr.aria-valuemin]=\"asideMinWidth()\"\n [attr.aria-valuemax]=\"asideMaxWidth()\"\n (pointerdown)=\"onHandlePointerDown($event, 'aside')\"\n (dblclick)=\"onHandleReset('aside')\"\n (keydown)=\"onHandleKeydown($event, 'aside')\"></div>\n\n <section rtElem=\"aside\" qa-dataid=\"workspace-aside\" [rtMod]=\"{ open: asideOpen() }\">\n <ng-container [ngTemplateOutlet]=\"asideSlot()?.templateRef ?? null\" [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n }\n</ng-container>\n"],"mappings":";;;;;;AAUA,IAAa,kCAAb,MAAa,gCAA+B;CAA/B;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAA+B,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAA/B;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAA+B,cAAA;GAAA,UAAA;GAAA,MAAA,EAAA,gBAAA,6BAAA;GAAA,UAAA;EAAA,CAAA;CAAA;;AAA/B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA+B,YAAA,CAAA;EAN3C,MAAA;EAAU,MAAA,CAAA;GACP,UAAU;GACV,MAAM,EACF,OAAO,6BACV;EACJ,CAAA;;;AAMD,IAAa,2BAAb,MAAa,yBAAwB;CAHrC,cAAA;EAIoB,KAAA,cAAqD,OAA8C,WAAW;CAMjI;CAHU,OAAO,uBAAuB,YAAsC,SAAgB;EACvF,OAAO;CACX;CANS;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAwB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAAxB;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAAwB,cAAA;GAAA,UAAA;GAAA,UAAA;EAAA,CAAA;CAAA;;AAAxB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAwB,YAAA,CAAA;EAHpC,MAAA;EAAU,MAAA,CAAA,EACP,UAAU,oBACb,CAAA;;;AAaD,IAAa,6BAAb,MAAa,2BAA0B;CAHvC,cAAA;EAIoB,KAAA,cAAqD,OAA8C,WAAW;CAMjI;CAHU,OAAO,uBAAuB,YAAwC,SAAgB;EACzF,OAAO;CACX;CANS;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAA0B,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAA1B;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAA0B,cAAA;GAAA,UAAA;GAAA,UAAA;EAAA,CAAA;CAAA;;AAA1B,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAA0B,YAAA,CAAA;EAHtC,MAAA;EAAU,MAAA,CAAA,EACP,UAAU,sBACb,CAAA;;;AAaD,IAAa,4BAAb,MAAa,0BAAyB;CAHtC,cAAA;EAIoB,KAAA,cAAqD,OAA8C,WAAW;CAMjI;CAHU,OAAO,uBAAuB,YAAuC,SAAgB;EACxF,OAAO;CACX;CANS;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAyB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAAzB;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAAyB,cAAA;GAAA,UAAA;GAAA,UAAA;EAAA,CAAA;CAAA;;AAAzB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAyB,YAAA,CAAA;EAHrC,MAAA;EAAU,MAAA,CAAA,EACP,UAAU,qBACb,CAAA;;;ACJD,MAAM,YAAoB;AAC1B,MAAM,iBAAyB;AAC/B,MAAM,gBAAwB;AAiC9B,IAAa,uBAAb,MAAa,qBAAoB;CACpB;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA;CAET;CAEA;CAEA;CA0DA,cAAA;EAhFS,KAAA,WAA2B,OAAO,cAAc;EAEhD,KAAA,YAAuB,OAAO,SAAS;EAEvC,KAAA,WAAoC,OAAO,UAAU;EAErD,KAAA,cAA0B,OAAO,UAAU;EAE3C,KAAA,qBAAoD,OAAsB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,qBAAA,CAAA,+BAAA,CAAA,CAAA;EAE/E,KAAA,sBAAqD,OAAsB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,sBAAA,CAAA,+BAAA,CAAA,CAAA;EAEhF,KAAA,kBAA2C,OAAgB,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,kBAAA,CAAA,+BAAA,CAAA,CAAA;EAEjE,KAAA,aAAsC,OAAgB,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;EAE5D,KAAA,YAAqC,OAAgB,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;EAEpE,KAAA,eAA8B;EAE9B,KAAA,aAAgC;EAEhC,KAAA,uBAA4C;EAEzB,KAAA,IAA4B,OAAO,aAAa;EAEhD,KAAA,WAAyD,aAAa,0BAAyB,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;EAE/F,KAAA,aAA6D,aAAa,4BAA2B,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;EAErG,KAAA,YAA2D,aAAa,2BAA0B,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;EAElG,KAAA,WAA4B,KAAK,UAAU,WAAU;EAErD,KAAA,cAAwC,EAAE,WAAW,KAAI;EAE5D,KAAA,aAAyC,MAAqB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;EAEnE,KAAA,YAA6D,MAA6B,OAAK;GAAA,GAAA,YAAA,EAAA,WAAA,YAAA,+BAAA,CAAA;GAC3G,WAAW;EAAgB,CAAA;EAGf,KAAA,eAAkE,MAA+B,KAAG;GAAA,GAAA,YAAA,EAAA,WAAA,eAAA,+BAAA,CAAA;GAChH,WAAW;EAAe,CAAA;EAGd,KAAA,eAAkE,MAA+B,KAAG;GAAA,GAAA,YAAA,EAAA,WAAA,eAAA,+BAAA,CAAA;GAChH,WAAW;EAAe,CAAA;EAGd,KAAA,mBAAsE,MAA+B,KAAG;GAAA,GAAA,YAAA,EAAA,WAAA,mBAAA,+BAAA,CAAA;GACpH,WAAW;EAAe,CAAA;EAGd,KAAA,gBAAmE,MAA+B,KAAG;GAAA,GAAA,YAAA,EAAA,WAAA,gBAAA,+BAAA,CAAA;GACjH,WAAW;EAAe,CAAA;EAGd,KAAA,gBAAmE,MAA+B,KAAG;GAAA,GAAA,YAAA,EAAA,WAAA,gBAAA,+BAAA,CAAA;GACjH,WAAW;EAAe,CAAA;EAGd,KAAA,oBAAuE,MAA+B,KAAG;GAAA,GAAA,YAAA,EAAA,WAAA,oBAAA,+BAAA,CAAA;GACrH,WAAW;EAAe,CAAA;EAGd,KAAA,iBAAoE,MAA+B,KAAG;GAAA,GAAA,YAAA,EAAA,WAAA,iBAAA,+BAAA,CAAA;GAClH,WAAW;EAAe,CAAA;EAGd,KAAA,cAAsC,OAAM;EAE5C,KAAA,YAA4B,eAAuB,KAAK,mBAAkB,KAAM,KAAK,iBAAgB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;EAExG,KAAA,aAA6B,eAAuB,KAAK,oBAAmB,KAAM,KAAK,kBAAiB,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;EAE3G,KAAA,iBAAkC,KAAK,gBAAgB,WAAU;EAEjE,KAAA,YAA6B,KAAK,WAAW,WAAU;EAGnE,aAAkB;GACd,MAAM,MAAqB,KAAK,WAAU;GAC1C,IAAI,QAAQ,QAAQ,QAAQ,KAAK,cAC7B;GAEJ,KAAK,eAAe;GACpB,gBAAsB,KAAK,oBAAoB,GAAG,CAAC;EACvD,CAAC;EAED,KAAK,YAAY,gBAAsB,KAAK,cAAa,CAAE;CAC/D;CAEO,uBAAoB;EACvB,KAAK,gBAAgB,QAAQ,cAAgC,CAAC,SAAS;EACvE,KAAK,SAAQ;CACjB;CAEO,YAAS;EACZ,KAAK,WAAW,IAAI,IAAI;CAC5B;CAEO,aAAU;EACb,KAAK,WAAW,IAAI,KAAK;CAC7B;CAEO,cAAW;EACd,KAAK,WAAW,QAAQ,SAA2B,CAAC,IAAI;CAC5D;CAEU,gBAAa;EACnB,KAAK,WAAU;EACf,KAAK,YAAY,KAAI;CACzB;CAEU,oBAAoB,OAAqB,MAA4B;EAC3E,IAAI,MAAM,WAAW,GACjB;EAEJ,MAAM,eAAc;EACpB,KAAK,aAAa;GACd;GACA,QAAQ,MAAM;GACd,YAAY,SAAS,SAAS,KAAK,UAAS,IAAK,KAAK,WAAU;EACnE;EACD,KAAK,UAAU,IAAI,IAAI;EAEvB,MAAM,aAAyB,KAAK,UAAU,OAAO,YAAY,gBAAgB,cAC7E,KAAK,YAAY,SAAS,CAAC;EAE/B,MAAM,WAAuB,KAAK,UAAU,OAAO,YAAY,mBAAwB;GACnF,KAAK,SAAQ;GACb,KAAK,cAAa;EACtB,CAAC;EACD,KAAK,6BAAkC;GACnC,WAAU;GACV,SAAQ;EACZ;CACJ;CAEU,gBAAgB,OAAsB,MAA4B;EACxE,IAAI;EACJ,IAAI,MAAM,QAAQ,cACd,QAAQ,SAAS,SAAS,gBAAgB;OACvC,IAAI,MAAM,QAAQ,aACrB,QAAQ,SAAS,SAAS,MAAiB;OAE3C;EAEJ,MAAM,eAAc;EACpB,MAAM,UAAkB,SAAS,SAAS,KAAK,UAAS,IAAK,KAAK,WAAU;EAC5E,KAAK,YAAY,MAAM,UAAU,KAAK;EACtC,KAAK,SAAQ;CACjB;CAEU,cAAc,MAA4B;EAEhD,CADgD,SAAS,SAAS,KAAK,qBAAqB,KAAK,oBACjG,CAAS,IAAI,IAAI;EACjB,KAAK,SAAQ;CACjB;CAEA,YAAY,OAAmB;EAC3B,MAAM,OAA0B,KAAK;EACrC,IAAI,SAAS,MACT;EAEJ,MAAM,KAAa,MAAM,UAAU,KAAK;EACxC,MAAM,WAAmB,KAAK,SAAS,SAAS,KAAK,aAAa,KAAK,KAAK,aAAa;EACzF,KAAK,YAAY,KAAK,MAAM,QAAQ;CACxC;CAEA,YAAY,MAA8B,UAAgB;EAEtD,CADgD,SAAS,SAAS,KAAK,qBAAqB,KAAK,oBACjG,CAAS,IAAI,KAAK,YAAY,MAAM,QAAQ,CAAC;CACjD;CAEA,YAAY,MAA8B,UAAgB;EACtD,MAAM,MAAc,SAAS,SAAS,KAAK,aAAY,IAAK,KAAK,cAAa;EAC9E,MAAM,YAAoB,SAAS,SAAS,KAAK,aAAY,IAAK,KAAK,cAAa;EAGpF,MAAM,aAAqB,KAAK,eAAe,SAAS,SAAS,UAAU,MAAM;EACjF,MAAM,YAAoB,KAAK,SAAS,cAAc;EACtD,MAAM,YAAoB,YAAY,IAAI,YAAY,aAAa,KAAK,eAAc,IAAK,OAAO;EAElG,OAAO,KAAK,MAAM,KAAK,IADH,KAAK,IAAI,KAAK,KAAK,IAAI,WAAW,SAAS,CACpC,GAAK,KAAK,IAAI,KAAK,QAAQ,CAAC,CAAC;CAC5D;CAGA,eAAe,MAA4B;EACvC,IAAI,SAAS,QACT,OAAO,KAAK,SAAQ,IAAK,KAAK,UAAS,IAAK;EAGhD,OAAO,KAAK,UAAS,IAAK,KAAK,WAAU,IAAK;CAClD;CAEA,gBAAa;EACT,KAAK,uBAAsB;EAC3B,KAAK,uBAAuB;EAC5B,KAAK,aAAa;EAClB,KAAK,UAAU,IAAI,KAAK;CAC5B;CAEA,oBAAoB,KAAW;EAC3B,MAAM,SACF,KAAK,SAAS,QAAqC,GAAG,iBAAiB,KAAK,KAAK;EACrF,IAAI,WAAW,QAAQ,OAAO,WAAW,UACrC;EAEJ,IAAI,OAAO,OAAO,cAAc,UAC5B,KAAK,mBAAmB,IAAI,KAAK,YAAY,QAAQ,OAAO,SAAS,CAAC;EAE1E,IAAI,OAAO,OAAO,eAAe,UAC7B,KAAK,oBAAoB,IAAI,KAAK,YAAY,SAAS,OAAO,UAAU,CAAC;EAE7E,KAAK,gBAAgB,IAAI,OAAO,mBAAmB,IAAI;CAC3D;CAEA,WAAQ;EACJ,MAAM,MAAqB,KAAK,WAAU;EAC1C,IAAI,QAAQ,MACR;EAEJ,MAAM,QAAqC;GACvC,WAAW,KAAK,UAAS;GACzB,YAAY,KAAK,WAAU;GAC3B,gBAAgB,KAAK,eAAc;EACtC;EACD,KAAK,SAAS,QAAQ,GAAG,iBAAiB,OAAO,KAAK;CAC1D;CAvOS;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAoB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAApB;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAAoB,cAAA;GAAA,UAAA;GAAA,QAAA;IAAA,YAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,WAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,cAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,cAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,kBAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,eAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,eAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,mBAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,gBAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;GAAA;GAAA,SAAA,EAAA,aAAA,cAAA;GAAA,MAAA;IAAA,YAAA;KAAA,kCAAA;KAAA,uCAAA;KAAA,gCAAA;KAAA,kCAAA;KAAA,mCAAA;IAAA;IAAA,gBAAA;GAAA;GAAA,SAAA;IAAA;KAAA,cAAA;KAAA,OAAA;KAAA,WA2B4D;KAAwB,aAAA;KAAA,UAAA;IAAA;IAAA;KAAA,cAAA;KAAA,OAAA;KAAA,WAEpB;KAA0B,aAAA;KAAA,UAAA;IAAA;IAAA;KAAA,cAAA;KAAA,OAAA;KAAA,WAE5B;KAAyB,aAAA;KAAA,UAAA;IAAA;GAAA;GAAA,UAAA;GAAA,UCpGxH;GAiEA,QAAA,CAAA,+qHAAA;GAAA,cAAA;IAAA;KAAA,MAAA;KAAA,MDbQ;KAAgB,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;KAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MAGhB;KAAqB,UAAA;KAAA,QAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA;KAAA;KAAA,SAAA,CAAA,SAAA;IAAA;IAAA;KAAA,MAAA;KAAA,MACrB;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;GAAA;GAAA,iBAAA,GAAA,wBAAA;GAAA,eAAA,GAAA,kBAAA;EAAA,CAAA;CAAA;;AAWP,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAoB,YAAA,CAAA;EAzBhC,MAAA;EACa,MAAA,CAAA;GAAA,UAAA;GAAc,iBAGP,wBAAwB;GAAM,eAChC,kBAAkB;GAAI,SAC5B;IAEL;IAGA;IACA;IACA;IACA;GACH;GAAA,MACK;IACF,OAAO;IACP,oCAAoC;IACpC,yCAAyC;IACzC,kCAAkC;IAClC,oCAAoC;IACpC,qCAAqC;GACxC;GAAA,UAAA;GAAA,QAAA,CAAA,+qHAAA;EAAA,CAAA;CA6BwF,CAAA;CAAA,sBAAA,CAAA;CAAA,gBAAA;EAAA,UAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBAAA,wBAAwB,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,YAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBAEpB,0BAA0B,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,WAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,GAAA,iBAE5B,yBAAyB,GAAA,EAAA,UAAA,KAAA,CAAA;EAAA,CAAA;EAAA,YAAA,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;EAAA,cAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,cAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,kBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,eAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,eAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,mBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,gBAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA;IAAA,UAAA;IAAA,OAAA;IAAA,UAAA;GAAA,CAAA;EAAA,CAAA;EAAA,aAAA,CAAA;GAAA,MAAA,GAAA;GAAA,MAAA,CAAA,aAAA;EAAA,CAAA;CAAA;AAAA,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rt-tools/ui-kit-v2",
3
- "version": "0.28.0",
3
+ "version": "0.29.1",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Yauheni Krumin",
6
6
  "type": "module",
@@ -1,4 +1,5 @@
1
1
  @use '../../../styles/mixins' as kv;
2
+ @use '../../../styles/breakpoints' as bp;
2
3
 
3
4
  @layer rt-kit.components {
4
5
  /* rt-calendar — ViewEncapsulation.None: правила таргетируют BEM-класс блока.
@@ -179,7 +180,7 @@
179
180
  opacity: 0.75;
180
181
  }
181
182
 
182
- @media (width <= 640px) {
183
+ @include bp.place-max(640px) {
183
184
  &__months {
184
185
  grid-template-columns: 1fr;
185
186
  }
@@ -194,7 +195,7 @@
194
195
  разделены неразрывным пробелом, и перенести её нечем. Освобождаем
195
196
  ширину боковыми отступами клетки и ступенью кегля, а не прячем цену:
196
197
  без неё календарь перестаёт быть прайс-листом */
197
- @media (width <= 374px) {
198
+ @include bp.place-max(374px) {
198
199
  &__day {
199
200
  padding-inline: 0;
200
201
  }
@@ -26,6 +26,12 @@
26
26
  **Необъявленная зона не создаёт пустого узла** — каркас состоит ровно из того, что передали.
27
27
  Зоны рисуются смысловыми тегами: `<header>`, `<aside>`, `<main>`.
28
28
 
29
+ **Каркас — место страницы.** Компоненты кита внутри него считают пороги 480, 768, 1080 и 1380
30
+ от его ширины, и `BreakpointsService.narrow` отвечает по ней же. Боковая панель приложения рядом с
31
+ каркасом сужает его, и вид внутри сужается вместе с ним. Ширину каркас берёт от родителя: в
32
+ родителе, который считает ширину по содержимому, он схлопывается. Окна и списки поверх экрана
33
+ считают пороги от окна: `BreakpointsService.viewportNarrow`.
34
+
29
35
  **Правая панель существует, только когда её зона объявлена.** Оверлей под неё создаётся заранее
30
36
  (`rightOverlayReady()`), а `openRight()` без объявленной зоны — no-op.
31
37
 
@@ -12,6 +12,10 @@
12
12
  flex: 1 1 auto;
13
13
  background-color: var(--rt-color-bg-page);
14
14
  color: var(--rt-color-text-primary);
15
+
16
+ /* Контейнер — место страницы: компоненты внутри считают пороги от его ширины. Боковая
17
+ панель приложения рядом сужает его, и вид внутри сужается вместе с ним. */
18
+ container: rt-place / inline-size;
15
19
  grid-template: 'header header' auto 'left-sidenav toolbar' auto 'left-sidenav content' 1fr / auto 1fr;
16
20
 
17
21
  &__header {
@@ -115,7 +115,7 @@
115
115
  --rt-input-fill-radius: var(--rt-list-search-radius);
116
116
  }
117
117
 
118
- @media (width <= #{bp.$rt-bp-lg}) {
118
+ @include bp.place-max(bp.$rt-bp-lg) {
119
119
  &__right {
120
120
  flex-wrap: wrap;
121
121
  }
@@ -110,7 +110,7 @@
110
110
 
111
111
  // Узкий экран объявлен запросом, а не условием в разметке. Порог тот же, о котором
112
112
  // отвечает служба порогов кита, и берётся он из общего файла порогов.
113
- @media (width <= #{bp.$rt-bp-lg}) {
113
+ @include bp.place-max(bp.$rt-bp-lg) {
114
114
  &__right {
115
115
  flex-wrap: wrap;
116
116
  }
@@ -1,10 +1,12 @@
1
+ @use '../../../styles/breakpoints' as bp;
2
+
1
3
  @layer rt-kit.components {
2
4
  .rt-filter-control {
3
5
  display: inline-flex;
4
6
 
5
7
  // узкий экран: контрол — компактный select с капом --rt-input-max-width
6
8
  // (как строка поиска). В ряду тулбара (768–1080px) ширина по контенту.
7
- @media (width <= 1080px) {
9
+ @include bp.place-max(1080px) {
8
10
  display: block;
9
11
 
10
12
  .rt-select {
@@ -15,7 +17,7 @@
15
17
 
16
18
  // стекнутый тулбар (≤768px): host занимает всю ширину столбца, select
17
19
  // вытягивается ровно как строка поиска (width:100% до --rt-input-max-width).
18
- @media (width <= 768px) {
20
+ @include bp.place-max(768px) {
19
21
  inline-size: 100%;
20
22
  }
21
23
  }
@@ -29,6 +29,18 @@
29
29
  **Своего отступа от краёв страницы у шапки нет.** Его задаёт тот, кто её ставит. Поставленной прямо
30
30
  в зону шапки `rt-container` его даёт каркас; в своей полосе приложения — сама полоса.
31
31
 
32
+ **Ряд разделов всегда стоит в одну строку.** Разделы, которым не хватило ширины, уходят в пункт
33
+ «Ещё» (`header-nav-more`) в конце ряда; «Ещё» появляется, только когда не встал хоть один раздел,
34
+ и порядок оставшихся не меняется. Очередь ухода задаёт поле `priority` пункта: меньшее число уходит
35
+ раньше, по умолчанию `0`, а при равной важности первым уходит стоящий дальше от начала списка.
36
+ Выбранный раздел внутри «Ещё» подсвечивает сам «Ещё» тем же видом, что выбранный пункт ряда.
37
+ Панель «Ещё» (`header-nav-more-list`) открывается поповером по наведению и по нажатию; её пункты —
38
+ `header-nav-more-item`, а раздел с панелью стоит в ней заголовком (`header-nav-more-section`) с
39
+ пунктами своих групп (`header-nav-more-group`) под ним, как в меню узкого экрана. Ряд
40
+ пересчитывается наблюдателем размера при смене ширины шапки, а также при смене состава и подписей;
41
+ расчёт — чистая функция `fitRow`. Ушедший раздел остаётся в разметке вынутым из ряда, чтобы его
42
+ ширину можно было мерить. Подпись «Ещё» — ключ кита `uiNavMore`.
43
+
32
44
  **Узкая разметка отдельная**, а не свёрнутая стилями: те же разделы доступны через кнопку-бургер
33
45
  (`header-nav-burger`), и оба варианта живут в DOM одновременно.
34
46
 
@@ -0,0 +1,7 @@
1
+ @layer rt-kit.components {
2
+ /* Хост «Ещё» коробки не даёт: кнопка внутри — пункт верхнего ряда и встаёт в его плашку,
3
+ как ссылки соседних разделов. Панель рисуется в оверлее блоком меню узкого экрана. */
4
+ .rt-page-header-more {
5
+ display: contents;
6
+ }
7
+ }
@@ -160,5 +160,29 @@
160
160
  &__icon {
161
161
  flex-shrink: 0;
162
162
  }
163
+
164
+ /* Панель пункта «Ещё» — тот же блок без аккордеона: раздел с панелью стоит
165
+ заголовком, пункты его групп идут под ним сразу, без отступа вложенности. */
166
+ &__heading {
167
+ display: flex;
168
+ min-height: var(--rt-nav-panel-item-height);
169
+ align-items: center;
170
+ padding: var(--rt-nav-panel-item-padding);
171
+ color: var(--rt-nav-item-color);
172
+ cursor: default;
173
+ font-size: var(--rt-nav-item-font-size);
174
+ font-weight: var(--rt-nav-item-font-weight);
175
+ line-height: var(--rt-leading-tight);
176
+ white-space: nowrap;
177
+ }
178
+
179
+ &--more &__children {
180
+ padding-left: 0;
181
+ }
182
+
183
+ &--more &__group-title {
184
+ letter-spacing: var(--rt-letter-spacing-wide);
185
+ text-transform: uppercase;
186
+ }
163
187
  }
164
188
  }
@@ -1,3 +1,5 @@
1
+ @use '../../../styles/breakpoints' as bp;
2
+
1
3
  @layer rt-kit.components {
2
4
  /* Цвет плашки вынесен в локальный override `--rt-page-header-bg`, дефолт
3
5
  берётся из семантики навигации. Отступ от краёв страницы задаёт тот, кто
@@ -24,12 +26,21 @@
24
26
  color: var(--rt-nav-item-color);
25
27
  gap: var(--rt-space-2);
26
28
 
29
+ /* Навигация занимает всё свободное место полосы. По этой ширине шапка решает, сколько разделов
30
+ встаёт в ряд, и ушедший в «Ещё» раздел её не меняет. */
27
31
  &__nav {
28
32
  min-width: 0;
29
- flex: 1 1 auto;
33
+ flex: 1 1 0;
30
34
  }
31
35
 
36
+ /* Ряд всегда в одну строку: перенос удваивал высоту шапки. Что не встало, уходит в
37
+ пункт «Ещё» в конце ряда. */
38
+
39
+ /* Перенос оставлен ради ширины по содержимому: без него ряд объявил бы сумму всех пунктов
40
+ и распёр бы контейнер, который считает свою ширину по шапке. Во вторую строку пункт не
41
+ встаёт, его раньше уводит в «Ещё» расчёт ряда. */
32
42
  &__list {
43
+ position: relative;
33
44
  display: flex;
34
45
  flex-flow: row wrap;
35
46
  align-items: center;
@@ -43,12 +54,23 @@
43
54
  видно — проступает только активный раздел, у которого фон белый. */
44
55
  &__item {
45
56
  display: inline-flex;
57
+ flex-shrink: 0;
46
58
  align-items: center;
47
59
  border: var(--rt-nav-item-border-width) solid var(--rt-nav-item-color-border);
48
60
  border-radius: var(--rt-nav-item-radius);
49
61
  background-color: var(--rt-nav-item-color-bg);
50
62
  }
51
63
 
64
+ /* Раздел, ушедший в «Ещё», и «Ещё», когда уходить некому, из ряда вынуты, но стоят в
65
+ разметке: их ширину шапка меряет и в таком виде, чтобы знать, встанут ли они обратно. */
66
+ &__item--is-overflow {
67
+ position: absolute;
68
+ top: 0;
69
+ left: 0;
70
+ pointer-events: none;
71
+ visibility: hidden;
72
+ }
73
+
52
74
  &__disabled-slot {
53
75
  display: inline-flex;
54
76
  flex-direction: column;
@@ -185,7 +207,7 @@
185
207
  без иконок: подпись раздела нужнее картинки рядом с ней. Замер в Chrome
186
208
  2026-08-02: на 1081px ряд с иконками занимает 938.7px при доступных
187
209
  798.4, без иконок — 762.7. */
188
- @media (width <= 1380px) {
210
+ @include bp.place-max(1380px) {
189
211
  /* Селектор из двух классов, а не одного: `.rt-icon` задаёт иконке
190
212
  `display`, и порядок стилей двух компонентов кита между собой не
191
213
  закреплён ничем. */
@@ -195,7 +217,7 @@
195
217
  }
196
218
 
197
219
  /* Узкий вьюпорт: инлайн-навигация уступает место гамбургеру. */
198
- @media (width <= 1080px) {
220
+ @include bp.place-max(1080px) {
199
221
  &__nav {
200
222
  display: none;
201
223
  }
@@ -196,7 +196,7 @@
196
196
  --rt-btn-bg-hover: var(--rt-pdf-viewer-control-bg-hover);
197
197
  }
198
198
 
199
- @media (width <= #{bp.$rt-bp-sm}) {
199
+ @include bp.place-max(bp.$rt-bp-sm) {
200
200
  --rt-pdf-viewer-bar-height: var(--rt-control-height-xl);
201
201
 
202
202
  &__fit,
@@ -43,7 +43,8 @@
43
43
  наведение на панель отсрочку гасит.
44
44
  - `fitViewport` **выключен по умолчанию**: панель стоит там, куда её ставит привязка к триггеру,
45
45
  даже если часть ушла за экран. Включать для широких и высоких панелей, иначе их содержимое
46
- остаётся недостижимым.
46
+ остаётся недостижимым. Порог 120 точек решает только, сдвинуть панель или ужать: короткая
47
+ панель остаётся высотой со своё содержимое.
47
48
  - `rtPopoverPanelClass` добавляется **к** базовому `rt-popover-panel`, а не вместо него.
48
49
  - Escape и клик мимо закрывают панель во всех режимах.
49
50
  - `rtPopoverPositions` даёт свои места вокруг host'а — первое главное, остальные запасные. Заданные
@@ -1,3 +1,5 @@
1
+ @use '../../../styles/breakpoints' as bp;
2
+
1
3
  @layer rt-kit.components {
2
4
  .rt-toolbar {
3
5
  /* Раскладка полосы — свойства блока: обёртка и приложение переставляют их снаружи.
@@ -93,7 +95,7 @@
93
95
  // Мобилка: три зоны не влезают в строку — стекаем в колонку на всю ширину
94
96
  // (фильтр → поиск → действия), поиск растягивается. `--dense` (компактная
95
97
  // шапка вроде rt-chat) из стекинга исключён — остаётся в одну строку.
96
- @media (width <= 768px) {
98
+ @include bp.place-max(768px) {
97
99
  .rt-toolbar:not(.rt-toolbar--dense) {
98
100
  .rt-toolbar__bars {
99
101
  flex-direction: column;
@@ -1,3 +1,5 @@
1
+ @use '../../../styles/breakpoints' as bp;
2
+
1
3
  @layer rt-kit.components {
2
4
  .rt-workspace {
3
5
  --rt-workspace-border-width: var(--rt-border-width-thin);
@@ -77,12 +79,12 @@
77
79
  }
78
80
 
79
81
  &__desktop-only {
80
- @media (width <= 1080px) {
82
+ @include bp.place-max(1080px) {
81
83
  display: none;
82
84
  }
83
85
  }
84
86
 
85
- @media (width <= 1080px) {
87
+ @include bp.place-max(1080px) {
86
88
  &__mobile-toolbar {
87
89
  display: flex;
88
90
  justify-content: space-between;
@@ -111,13 +113,13 @@
111
113
  }
112
114
  }
113
115
 
114
- @media (width <= 768px) {
116
+ @include bp.place-max(768px) {
115
117
  &__list {
116
118
  flex-basis: 100%;
117
119
  }
118
120
  }
119
121
 
120
- @media (width > 1080px) {
122
+ @include bp.place-min(1080px) {
121
123
  &__aside {
122
124
  overflow: hidden;
123
125
  transition:
@@ -129,7 +131,7 @@
129
131
  }
130
132
 
131
133
  &--has-active {
132
- @media (width <= 768px) {
134
+ @include bp.place-max(768px) {
133
135
  .rt-workspace__list {
134
136
  display: none;
135
137
  }
@@ -141,7 +143,7 @@
141
143
  }
142
144
 
143
145
  &--aside-collapsed {
144
- @media (width > 1080px) {
146
+ @include bp.place-min(1080px) {
145
147
  .rt-workspace__aside {
146
148
  flex-basis: 0;
147
149
  border-inline-start-width: 0;