@rt-tools/ui-kit-v2 0.42.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/fesm2022/rt-tools-ui-kit-v2-core.mjs +22 -0
  2. package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -1
  3. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +1778 -18
  4. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -1
  5. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +19 -5
  6. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  7. package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs +34 -11
  8. package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs.map +1 -1
  9. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +725 -47
  10. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -1
  11. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs +6 -0
  12. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs.map +1 -1
  13. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs +217 -6
  14. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs.map +1 -1
  15. package/package.json +1 -1
  16. package/src/lib/components/page-header/CONTEXT.md +35 -1
  17. package/src/lib/components/page-header/bar/rt-page-bar.component.scss +161 -0
  18. package/src/lib/components/page-header/rail/rt-page-actions.component.scss +115 -0
  19. package/src/lib/components/page-header/rail/rt-page-phone-menu.component.scss +129 -0
  20. package/src/lib/components/page-header/rail/rt-page-rail.component.scss +281 -0
  21. package/src/lib/components/page-header/rail/rt-page-user.component.scss +76 -0
  22. package/src/lib/components/page-header/rt-page-header.component.scss +5 -0
  23. package/src/lib/components/page-header/stories/component/test-page-header-vertical.component.scss +72 -0
  24. package/src/lib/components/page-header/stories/component/test-page-table.component.scss +81 -0
  25. package/src/lib/components/page-header/user/rt-page-header-user.component.scss +6 -0
  26. package/src/lib/components/stepper/CONTEXT.md +34 -2
  27. package/src/lib/components/stepper/rt-stepper.component.scss +62 -43
  28. package/src/lib/components/tabs/CONTEXT.md +30 -1
  29. package/src/lib/components/tabs/rt-tabs-arrows.scss +140 -0
  30. package/src/lib/components/tabs/rt-tabs-more-menu.scss +126 -0
  31. package/src/lib/components/tabs/rt-tabs-more.component.scss +29 -0
  32. package/src/lib/components/tabs/rt-tabs.component.scss +18 -61
  33. package/src/lib/components/workspace/CONTEXT.md +11 -1
  34. package/src/lib/components/workspace/rt-workspace.component.scss +51 -3
  35. package/src/rich-editor/lib/components/chat/CONTEXT.md +11 -1
  36. package/src/rich-editor/lib/components/chat/rt-chat-messenger.scss +9 -3
  37. package/src/rich-editor/lib/components/chat/rt-chat-translation.scss +92 -0
  38. package/types/rt-tools-ui-kit-v2-core.d.ts +9 -1
  39. package/types/rt-tools-ui-kit-v2-page-header.d.ts +202 -2
  40. package/types/rt-tools-ui-kit-v2-rich-editor.d.ts +23 -0
  41. package/types/rt-tools-ui-kit-v2-stepper.d.ts +20 -6
  42. package/types/rt-tools-ui-kit-v2-tabs.d.ts +120 -1
  43. package/types/rt-tools-ui-kit-v2-workspace.d.ts +33 -1
@@ -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--cards]': 'cards()',\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 /** Колонки стоят отдельными карточками с зазором, без линий между ними */\n public readonly cards: 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":["BEM_BLOCK"],"sources":["../../../projects/ui-kit-v2/src/lib/components/workspace/rt-workspace-aside-overlay.component.ts","../../../projects/ui-kit-v2/src/lib/components/workspace/rt-workspace-aside-overlay.component.html","../../../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 { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, inject, Injector, Signal, ViewEncapsulation } from '@angular/core';\n\nimport { RT_ASIDE_DATA, RtAsideComponent, RtAsideFooterComponent, RtAsideRef } from '@rt-tools/ui-kit-v2/aside';\nimport { RtButtonDirective } from '@rt-tools/ui-kit-v2/button';\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { IRtWorkspace } from './rt-workspace.model';\n\nconst BEM_BLOCK: string = 'rt-workspace-aside-overlay';\n\n/**\n * Панель сведений рабочего стола, открытая поверх окна: шаблон панели приложения в рамке `rt-aside`\n * с кнопкой «Закрыть» в подвале. Открывает её сам рабочий стол; наружу компонент не отдаётся.\n */\n@Component({\n selector: 'rt-workspace-aside-overlay',\n templateUrl: './rt-workspace-aside-overlay.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n NgTemplateOutlet,\n\n // standalone components / directives\n RtAsideComponent,\n RtAsideFooterComponent,\n RtButtonDirective,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtWorkspaceAsideOverlayComponent {\n readonly #asideRef: RtAsideRef<void> = inject<RtAsideRef<void>>(RtAsideRef);\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly data: IRtWorkspace.AsideOverlayData = inject<IRtWorkspace.AsideOverlayData>(RT_ASIDE_DATA);\n\n /** Шаблон приложения получает инжектор панели: кнопки внутри него могут закрыть её сами */\n protected readonly injector: Injector = inject(Injector);\n\n /** Панель не шире окна: на телефонной ширине она занимает его целиком */\n protected readonly width: string = `min(${this.data.width}px, 100dvw)`;\n\n protected close(): void {\n this.#asideRef.close();\n }\n}\n","<rt-aside modal trapFocus [width]=\"width\" [style.--rt-aside-narrow-width]=\"width\" [ariaLabel]=\"t().uiDetails\">\n <ng-container [ngTemplateOutlet]=\"data.template\" [ngTemplateOutletContext]=\"data.context\" [ngTemplateOutletInjector]=\"injector\" />\n <rt-aside-footer>\n <button\n rtButton\n asideDismiss\n qa-dataid=\"workspace-aside-overlay-close\"\n type=\"button\"\n [label]=\"t().uiClose\"\n [attr.aria-label]=\"t().uiClose\"\n (click)=\"close()\"></button>\n </rt-aside-footer>\n</rt-aside>\n","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 { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';\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 Injector,\n input,\n InputSignal,\n InputSignalWithTransform,\n numberAttribute,\n output,\n OutputEmitterRef,\n Renderer2,\n signal,\n Signal,\n TemplateRef,\n untracked,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\nimport { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';\n\nimport { map, mergeMap, Observable, of, Subject, switchMap } from 'rxjs';\n\nimport { StorageService } from '@rt-tools/core';\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RtAsideRef, RtAsideService } from '@rt-tools/ui-kit-v2/aside';\nimport { BreakpointsService, RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtWorkspaceAsideOverlayComponent } from './rt-workspace-aside-overlay.component';\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;\nconst ASIDE_OVERLAY_PANE: string = 'rt-workspace-aside-pane';\n\n/** Что принимает вход порога: число, строка атрибута или `null` */\ntype TBreakpointInput = number | string | null;\n\n/** Порог одной колонки из входа: пустое значение оставляет порог стилей. */\nfunction breakpointAttribute(value: TBreakpointInput): number | null {\n return value === null || value === '' ? null : numberAttribute(value);\n}\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--cards]': 'cards()',\n '[class.rt-workspace--breakpoint]': 'singleColumnBreakpoint() !== null',\n '[class.rt-workspace--single]': 'singleColumn()',\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 #breakpoints: BreakpointsService = inject(BreakpointsService);\n\n readonly #observer: BreakpointObserver = inject(BreakpointObserver);\n\n readonly #asides: RtAsideService = inject(RtAsideService);\n\n readonly #injector: Injector = inject(Injector);\n\n /** Открытая поверх окна панель сведений: её закрытие догоняет состояние в конструкторе */\n readonly #overlayOpenedSource: Subject<RtAsideRef<void>> = new Subject<RtAsideRef<void>>();\n\n /**\n * Окно не шире порога из входа: отвечает, когда место страницы не объявлено. Вход читается\n * через `computed`: поле стоит выше входа, и напрямую его ещё нет.\n */\n readonly #viewportSingle: Signal<boolean> = toSignal(\n toObservable(computed((): number | null => this.singleColumnBreakpoint())).pipe(\n switchMap((breakpoint: number | null): Observable<boolean> =>\n breakpoint === null\n ? of(false)\n : this.#observer.observe(`(max-width: ${breakpoint}px)`).pipe(map((state: BreakpointState): boolean => state.matches))\n )\n ),\n { initialValue: false }\n );\n\n #overlayRef: RtAsideRef<void> | null = null;\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 /** Одна колонка по порогу из входа; без входа вид держат стили, и здесь всегда `false` */\n protected readonly singleColumn: Signal<boolean> = computed((): boolean => {\n const breakpoint: number | null = this.singleColumnBreakpoint();\n if (breakpoint === null) {\n return false;\n }\n const placeWidth: number | null = this.#breakpoints.placeWidth();\n\n return placeWidth === null ? this.#viewportSingle() : placeWidth <= breakpoint;\n });\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 /** Колонки стоят отдельными карточками с зазором, без линий между ними */\n public readonly cards: 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 /**\n * Порог одной колонки, пиксели места страницы. Без входа порог держат стили: 768. С входом\n * выше порога список и середина стоят рядом, а панель сведений, которой не хватает места\n * третьей колонкой, открывается поверх окна. Порог выше 1080 смысла не имеет.\n */\n public readonly singleColumnBreakpoint: InputSignalWithTransform<number | null, TBreakpointInput> = input<\n number | null,\n TBreakpointInput\n >(null, { transform: breakpointAttribute });\n\n /** Ширина панели сведений, открытой поверх окна */\n public readonly asideOverlayWidth: InputSignalWithTransform<number, number | string> = input<number, number | string>(540, {\n transform: numberAttribute,\n });\n\n public readonly backClicked: OutputEmitterRef<void> = output<void>();\n\n public readonly asideOverlay: Signal<boolean> = computed(\n (): boolean => this.singleColumnBreakpoint() !== null && this.#breakpoints.narrow() && !this.singleColumn()\n );\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 // Панель поверх окна живёт, пока она открыта и вид её требует: смена ширины её закрывает\n effect((): void => {\n const template: TemplateRef<IRtWorkspace.SlotContext> | undefined = this.asideSlot()?.templateRef;\n const shown: boolean = this.#asideOpen() && this.asideOverlay();\n untracked((): void => (shown && template ? this.#openOverlay(template) : this.#closeOverlay()));\n });\n\n // Затемнение, Esc и кнопка «Закрыть» закрывают панель сами: состояние догоняет их\n this.#overlayOpenedSource\n .pipe(\n mergeMap((ref: RtAsideRef<void>): Observable<RtAsideRef<void>> => ref.afterClosed().pipe(map((): RtAsideRef<void> => ref))),\n takeUntilDestroyed()\n )\n .subscribe((ref: RtAsideRef<void>): void => {\n if (this.#overlayRef === ref) {\n this.#overlayRef = null;\n }\n this.#asideOpen.set(false);\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 #openOverlay(template: TemplateRef<IRtWorkspace.SlotContext>): void {\n if (this.#overlayRef !== null) {\n return;\n }\n const data: IRtWorkspace.AsideOverlayData = {\n template,\n context: this.slotContext,\n width: this.asideOverlayWidth(),\n };\n const ref: RtAsideRef<void> = this.#asides.open<RtWorkspaceAsideOverlayComponent, IRtWorkspace.AsideOverlayData, void>(\n RtWorkspaceAsideOverlayComponent,\n { data, injector: this.#injector, panelClass: ASIDE_OVERLAY_PANE }\n );\n this.#overlayRef = ref;\n this.#overlayOpenedSource.next(ref);\n }\n\n #closeOverlay(): void {\n const ref: RtAsideRef<void> | null = this.#overlayRef;\n this.#overlayRef = null;\n ref?.close();\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 <!-- Панель, открытая поверх окна, рисует тот же шаблон сама: дважды он не выводится -->\n <section rtElem=\"aside\" qa-dataid=\"workspace-aside\" [rtMod]=\"{ open: asideOpen(), overlay: asideOverlay() }\">\n <ng-container\n [ngTemplateOutlet]=\"asideOverlay() ? null : (asideSlot()?.templateRef ?? null)\"\n [ngTemplateOutletContext]=\"slotContext\" />\n </section>\n }\n</ng-container>\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rt-tools/ui-kit-v2",
3
- "version": "0.42.0",
3
+ "version": "0.43.0",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Yauheni Krumin",
6
6
  "type": "module",
@@ -50,7 +50,41 @@
50
50
  раздел без иконки в круг не попадает. «Ещё» открывает ту же панель, что и бургер. Прилипание
51
51
  ловит наблюдатель пересечения: верх шапки стоит на пиксель выше края, и, прилипнув, она теряет
52
52
  его из видимой области — так работает и внутри прокручиваемого контейнера. Без входа разметка и
53
- поведение прежние.
53
+ поведение прежние. Наблюдатель стоит при любом `layout`: вид, сменённый на горизонтальный на ходу,
54
+ сжимается так же. В вертикальном виде сжатой полосы нет.
55
+
56
+ **Вход `layout="vertical"` рисует вместо ряда рейку `rt-page-rail`.** Разделы те же и в том же
57
+ порядке, подсветка считается шапкой. Рейка стоит по левому краю окна шириной 50, хост шапки в
58
+ раскладке не участвует (`display: contents`). Панель раздела шириной 220 стоит поверх страницы и
59
+ вкладок и открывается наведением или нажатием; закрывают её уход указателя, Escape, щелчок мимо и
60
+ выбор пункта. Касание открывает панель с первого раза: касание шлёт наведение и сразу нажатие, и
61
+ нажатие после такого наведения панель оставляет. Второе касание или клавиша по тому же разделу её
62
+ закрывает, нажатие мышью — никогда. Раздел без значка показывает первую букву названия. Подвал рейки — пункты `railActions` и профиль; `railFoot=false` убирает его для вида с
63
+ вкладками. Логотип — слот `[rtRailLogo]`, содержимое строки телефона — `[rtRailPage]`.
64
+
65
+ **На ширине 768 и меньше рейка становится строкой 50.** В ней бургер, содержимое `[rtRailPage]` и
66
+ кнопки подвала. Бургер открывает столбец `rt-page-phone-menu` шириной 240 поверх затемнённой
67
+ страницы: строки 48, логотипа нет, раздел с панелью открывает свои пункты на месте списка, «Назад»
68
+ возвращает к разделам. `rt-side-menu` здесь не участвует. Нажатие мимо столбца, Escape и выбор пункта
69
+ его закрывают, как и расширение экрана за порог узкого. Столбец — окно (`role="dialog"`): открытый
70
+ берёт фокус на первую строку, закрытый возвращает его бургеру. Цвета темы те же, что на широком экране: список разделов как рейка, открытый раздел
71
+ как панель. Порог задан запросом по ширине окна.
72
+
73
+ **`rt-page-actions` — кнопки ассистента, уведомлений и профиля.** Одна часть стоит в подвале рейки
74
+ (`placement="rail"`) и в ряду с вкладками, куда её ставит потребитель через `rtTabsControl`. Меню
75
+ профиля приходит тем же `userMenu`.
76
+
77
+ **`rt-page-bar` — компактная шапка страницы.** Вход `pageTitle`, действия `actions`, признак
78
+ `filtersActive`, выходы `actionClick` и `filtersApply`; поиск и отборы приходят шаблонами `rtPageBarSearch` и
79
+ `rtPageBarFilter`. Решает собственная ширина шапки, а не окна: страница, суженная ассистентом,
80
+ перестраивает её сама. Одна строка 56, две строки 104, лишние отборы уходят под «Ещё отборы · N»
81
+ (ключ `uiMoreFilters`). Кнопки действий и «Ещё отборы» высотой 32. Поиск и отборы — шаблоны
82
+ приложения, поэтому размер им задаёт оно: в строке `size="sm"`. При ширине до 768 отборы
83
+ открываются в `rt-bottom-sheet`, а действия в `rt-menu`; отключённое действие отключено и там.
84
+ Смена вида закрывает шторку, и при возврате в узкий она сама не открывается. Расчёт — чистая
85
+ функция `pageBarFit`; ширины отборов и «Ещё отборы» в ней и в стилях одни, это держит тест. Без
86
+ поиска и отборов шапка остаётся в одну строку, длинный заголовок обрезается. Заголовок меряется в
87
+ широком виде по тексту, заново — после смены текста, догрузки шрифтов и возврата из узкого вида.
54
88
 
55
89
  ## Края
56
90
 
@@ -0,0 +1,161 @@
1
+ @layer rt-kit.components {
2
+ .rt-page-bar {
3
+ --rt-page-bar-control-border-width: var(--rt-border-width-thin);
4
+ --rt-page-bar-dot-radius: var(--rt-radius-full);
5
+
6
+ position: relative;
7
+ display: flex;
8
+ min-width: 0;
9
+ box-sizing: border-box;
10
+ flex-direction: column;
11
+ padding: var(--rt-space-2) var(--rt-space-5);
12
+ gap: var(--rt-space-2);
13
+
14
+ /* Линия лежит поверх и высоты не отнимает. У строки телефона линия своя, у рейки. */
15
+ &:not(&--narrow):after {
16
+ position: absolute;
17
+ height: var(--rt-page-bar-control-border-width);
18
+ background-color: var(--rt-color-border-default);
19
+ content: '';
20
+ inset: auto 0 0;
21
+ pointer-events: none;
22
+ }
23
+
24
+ &__row {
25
+ display: flex;
26
+ min-width: 0;
27
+ height: 40px;
28
+ align-items: center;
29
+ gap: calc(var(--rt-space-2) + var(--rt-space-1));
30
+ }
31
+
32
+ &__title {
33
+ overflow: hidden;
34
+ min-width: 0;
35
+ flex: 0 1 auto;
36
+ margin: 0;
37
+ color: var(--rt-color-text-primary);
38
+ font-size: var(--rt-text-xl);
39
+ font-weight: var(--rt-font-weight-semibold);
40
+ line-height: 24px;
41
+ text-overflow: ellipsis;
42
+ white-space: nowrap;
43
+ }
44
+
45
+ &__spacer {
46
+ flex: 1 1 0;
47
+ }
48
+
49
+ &__search {
50
+ min-width: 0;
51
+ max-width: 540px;
52
+ flex: 1 1 0;
53
+ }
54
+
55
+ &__filter {
56
+ width: 150px;
57
+ flex: none;
58
+
59
+ &--wide {
60
+ width: 170px;
61
+ }
62
+ }
63
+
64
+ &__actions {
65
+ display: flex;
66
+ flex: none;
67
+ gap: var(--rt-space-2);
68
+ margin-inline-start: auto;
69
+ }
70
+
71
+ &__more {
72
+ width: 185px;
73
+ flex: none;
74
+ }
75
+
76
+ &__filters-trigger {
77
+ position: relative;
78
+ display: inline-flex;
79
+ flex: none;
80
+ }
81
+
82
+ /* Кнопка действий на телефоне, пока её меню открыто. */
83
+ .rt-menu--open .rt-icon-button {
84
+ background-color: var(--rt-nav-item-color-bg-active);
85
+ }
86
+
87
+ &__dot {
88
+ position: absolute;
89
+ top: calc(var(--rt-space-1) + var(--rt-space-0-5));
90
+ right: var(--rt-space-1);
91
+ width: 4px;
92
+ height: 4px;
93
+ border-radius: var(--rt-page-bar-dot-radius);
94
+ background-color: var(--rt-nav-marker-color);
95
+ pointer-events: none;
96
+ }
97
+
98
+ &__sheet {
99
+ display: flex;
100
+ flex-direction: column;
101
+ gap: calc(var(--rt-space-2) + var(--rt-space-1));
102
+ padding-block-end: var(--rt-space-4);
103
+ padding-inline: var(--rt-space-5);
104
+ }
105
+
106
+ &__apply {
107
+ flex: 1 1 auto;
108
+ }
109
+
110
+ /* Узкий вид: заголовок забирает остаток и усекается, кнопки с экрана не уходят. */
111
+ &--narrow &__row {
112
+ height: 32px;
113
+ gap: var(--rt-space-1);
114
+ }
115
+
116
+ &--narrow &__title {
117
+ flex: 1 1 0;
118
+ font-size: var(--rt-text-md);
119
+ line-height: 20px;
120
+ }
121
+
122
+ &--narrow &__spacer {
123
+ display: none;
124
+ }
125
+
126
+ @media (width <= 768px) {
127
+ min-width: 0;
128
+ flex: 1 1 0;
129
+ padding: 0;
130
+ }
131
+ }
132
+
133
+ /* Меню действий узкого вида открывается под строкой шапки 50, а не под кнопкой 32. */
134
+ .rt-page-bar-menu {
135
+ margin-block-start: calc((50px - 32px) / 2);
136
+
137
+ .rt-menu__panel {
138
+ min-width: 220px;
139
+ box-sizing: border-box;
140
+ }
141
+ }
142
+
143
+ /* Панель «Ещё отборы» рисуется в перекрытии, вне поддерева шапки, и подложку несёт сама: у панели
144
+ поповера своего фона нет, и без неё таблица под панелью просвечивала. Поверхность — как у меню кита. */
145
+ .rt-page-bar-more {
146
+ --rt-page-bar-more-radius: var(--rt-overlay-menu-radius);
147
+ --rt-page-bar-more-border-width: var(--rt-border-width-thin);
148
+ --rt-page-bar-more-shadow: var(--rt-overlay-menu-shadow);
149
+
150
+ display: flex;
151
+ width: 240px;
152
+ box-sizing: border-box;
153
+ flex-direction: column;
154
+ padding: var(--rt-space-2);
155
+ border: var(--rt-page-bar-more-border-width) solid var(--rt-color-border-subtle);
156
+ border-radius: var(--rt-page-bar-more-radius);
157
+ background-color: var(--rt-overlay-menu-bg);
158
+ box-shadow: var(--rt-page-bar-more-shadow);
159
+ gap: var(--rt-space-2);
160
+ }
161
+ }
@@ -0,0 +1,115 @@
1
+ @layer rt-kit.components {
2
+ /* Ряд вкладок и шапка телефона: кнопки 32, точка в потоке за иконкой. */
3
+ .rt-page-actions {
4
+ --rt-page-actions-plate-radius: var(--rt-radius-md);
5
+ --rt-page-actions-plate-border-width: var(--rt-border-width-thin);
6
+ --rt-page-actions-marker-radius: var(--rt-radius-full);
7
+
8
+ display: flex;
9
+ flex: none;
10
+ align-items: center;
11
+ gap: var(--rt-space-2);
12
+ padding-inline: var(--rt-space-2);
13
+
14
+ &__item {
15
+ display: inline-flex;
16
+ height: 32px;
17
+ flex: none;
18
+ align-items: center;
19
+ padding: 0 var(--rt-space-2);
20
+ border: 0;
21
+ background: transparent;
22
+ color: var(--rt-nav-item-color);
23
+ cursor: pointer;
24
+
25
+ &:hover {
26
+ color: var(--rt-nav-item-color-hover);
27
+ }
28
+
29
+ &:focus-visible {
30
+ outline: 1px dashed var(--rt-nav-color-focus);
31
+ outline-offset: -1px;
32
+ }
33
+
34
+ &--disabled {
35
+ color: var(--rt-nav-color-disabled);
36
+ cursor: default;
37
+ }
38
+ }
39
+
40
+ &__plate {
41
+ display: inline-flex;
42
+ align-items: center;
43
+ gap: var(--rt-space-2);
44
+ }
45
+
46
+ &__marker {
47
+ width: var(--rt-nav-marker-size);
48
+ height: var(--rt-nav-marker-size);
49
+ flex: none;
50
+ border-radius: var(--rt-page-actions-marker-radius);
51
+ background-color: var(--rt-nav-marker-color);
52
+ }
53
+
54
+ /* Подвал рейки на широком экране: столбец ячеек 50, те же плашки 36, что у разделов.
55
+ Ряд вкладок: кнопки стоят над линией полосы, а не по центру с ней. */
56
+ @media (width > 768px) {
57
+ /* Линия полосы идёт и под кнопками, вместе с отступом ряда вкладок перед ними. */
58
+ &:not(&--rail) {
59
+ border-block-end: var(--rt-page-actions-plate-border-width) solid var(--rt-color-border-default);
60
+ margin-inline-start: calc(-1 * var(--rt-space-md));
61
+ }
62
+
63
+ &--rail {
64
+ flex-direction: column;
65
+ align-items: stretch;
66
+ gap: 0;
67
+ padding-inline: 0;
68
+ }
69
+
70
+ &--rail &__item {
71
+ width: 50px;
72
+ height: 50px;
73
+ justify-content: center;
74
+ padding: 0;
75
+ }
76
+
77
+ &--rail &__plate {
78
+ position: relative;
79
+ width: 36px;
80
+ height: 36px;
81
+ box-sizing: border-box;
82
+ justify-content: center;
83
+ border: var(--rt-page-actions-plate-border-width) solid transparent;
84
+ border-radius: var(--rt-page-actions-plate-radius);
85
+ }
86
+
87
+ &--rail &__item:hover &__plate {
88
+ background-color: var(--rt-nav-item-color-bg-active);
89
+ }
90
+
91
+ /* Включённая кнопка: в рейке как выбранный раздел, в ряду вкладок заливка на всю кнопку. */
92
+ &--rail &__item--active &__plate {
93
+ border-color: var(--rt-color-border-default);
94
+ background-color: var(--rt-nav-item-color-bg-active);
95
+ }
96
+
97
+ &:not(&--rail) &__item--active {
98
+ background-color: var(--rt-nav-item-color-bg-active);
99
+ color: var(--rt-nav-item-color-hover);
100
+ }
101
+
102
+ &--rail &__marker {
103
+ position: absolute;
104
+ top: calc(var(--rt-space-1) - var(--rt-page-actions-plate-border-width));
105
+ right: calc(var(--rt-space-1) - var(--rt-page-actions-plate-border-width));
106
+ }
107
+ }
108
+
109
+ /* Телефон: кнопки примыкают друг к другу через 4. */
110
+ @media (width <= 768px) {
111
+ gap: var(--rt-space-1);
112
+ padding-inline: 0;
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,129 @@
1
+ @layer rt-kit.components {
2
+ .rt-page-phone-menu {
3
+ --rt-page-phone-menu-row-radius: var(--rt-radius-md);
4
+ --rt-page-phone-menu-marker-radius: var(--rt-radius-full);
5
+ --rt-page-phone-menu-border-width: var(--rt-border-width-thin);
6
+
7
+ display: flex;
8
+ overflow: hidden auto;
9
+ width: 100%;
10
+ height: 100%;
11
+ box-sizing: border-box;
12
+ flex-direction: column;
13
+
14
+ /* Список разделов красится как рейка, открытый раздел как панель раздела. */
15
+ &__list {
16
+ display: flex;
17
+ box-sizing: border-box;
18
+ flex: 1 0 auto;
19
+ flex-direction: column;
20
+ padding: var(--rt-space-2);
21
+ background-color: var(--rt-nav-header-color-bg);
22
+ gap: var(--rt-space-1);
23
+
24
+ &--panel {
25
+ background-color: var(--rt-nav-panel-color-bg);
26
+ }
27
+ }
28
+
29
+ &__group-title {
30
+ display: flex;
31
+ height: 32px;
32
+ flex: none;
33
+ align-items: center;
34
+ color: var(--rt-nav-panel-group-color);
35
+ font-size: var(--rt-nav-panel-group-font-size);
36
+ font-weight: var(--rt-nav-panel-group-font-weight);
37
+ padding-inline: var(--rt-space-4);
38
+ }
39
+
40
+ &__row {
41
+ display: flex;
42
+ width: 100%;
43
+ height: 48px;
44
+ box-sizing: border-box;
45
+ flex: none;
46
+ align-items: center;
47
+ padding: 0 var(--rt-space-4);
48
+ border: var(--rt-page-phone-menu-border-width) solid transparent;
49
+ border-radius: var(--rt-page-phone-menu-row-radius);
50
+ background: transparent;
51
+ color: var(--rt-nav-item-color);
52
+ cursor: pointer;
53
+ font-family: inherit;
54
+ font-size: var(--rt-text-sm);
55
+ font-weight: var(--rt-font-weight-medium);
56
+ gap: calc(var(--rt-space-2) + var(--rt-space-1));
57
+ text-align: start;
58
+ text-decoration: none;
59
+
60
+ &:hover {
61
+ background-color: var(--rt-nav-item-color-bg-active);
62
+ color: var(--rt-nav-item-color-hover);
63
+ }
64
+
65
+ &--active {
66
+ border-color: var(--rt-color-border-default);
67
+ background-color: var(--rt-nav-item-color-bg-active);
68
+ font-weight: var(--rt-font-weight-semibold);
69
+ }
70
+
71
+ &--disabled,
72
+ &--disabled:hover {
73
+ background: transparent;
74
+ color: var(--rt-nav-color-disabled);
75
+ cursor: default;
76
+ }
77
+ }
78
+
79
+ &__list--panel &__row {
80
+ color: var(--rt-nav-panel-item-color);
81
+
82
+ &:hover {
83
+ background-color: var(--rt-nav-panel-item-color-bg-hover);
84
+ }
85
+
86
+ &--active,
87
+ &--active:hover {
88
+ border-color: transparent;
89
+ background-color: var(--rt-nav-panel-item-color-bg-active);
90
+ color: var(--rt-nav-panel-item-color-active);
91
+ }
92
+
93
+ &--disabled,
94
+ &--disabled:hover {
95
+ background: transparent;
96
+ color: var(--rt-nav-color-disabled);
97
+ }
98
+ }
99
+
100
+ &__icon {
101
+ position: relative;
102
+ display: flex;
103
+ flex: none;
104
+ }
105
+
106
+ &__marker {
107
+ position: absolute;
108
+ top: 0;
109
+ right: 0;
110
+ width: var(--rt-nav-marker-size);
111
+ height: var(--rt-nav-marker-size);
112
+ border-radius: var(--rt-page-phone-menu-marker-radius);
113
+ background-color: var(--rt-nav-marker-color);
114
+ }
115
+
116
+ &__label {
117
+ overflow: hidden;
118
+ min-width: 0;
119
+ flex: 1 1 auto;
120
+ text-overflow: ellipsis;
121
+ white-space: nowrap;
122
+ }
123
+
124
+ &__arrow {
125
+ display: flex;
126
+ flex: none;
127
+ }
128
+ }
129
+ }