@rt-tools/ui-kit-v2 0.34.2 → 0.34.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/rt-tools-ui-kit-v2-action-bar.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-action-bar.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-aside.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-aside.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-copy-value.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-copy-value.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-counter.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-counter.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs +4 -0
- package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs +4 -0
- package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs +4 -0
- package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-dialog.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-dialog.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-header.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-header.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs +103 -6
- package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-input.mjs +6 -1
- package/fesm2022/rt-tools-ui-kit-v2-input.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-menu.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-menu.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-message.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-message.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-pdf-viewer.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-pdf-viewer.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-photo-viewer.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-photo-viewer.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +10 -0
- package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-select.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-select.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +6 -0
- package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-table.mjs +8 -0
- package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-toast.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-toast.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs +14 -2
- package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/components/icon-button/CONTEXT.md +32 -16
- package/src/lib/components/icon-button/rt-icon-button.component.scss +17 -9
- package/src/lib/components/input/CONTEXT.md +6 -0
- package/src/lib/components/tooltip/CONTEXT.md +3 -0
- package/src/styles/_form.scss +14 -1
- package/styles/tokens.css +13 -1
- package/types/rt-tools-ui-kit-v2-icon-button.d.ts +38 -2
- package/types/rt-tools-ui-kit-v2-input.d.ts +2 -0
- package/types/rt-tools-ui-kit-v2-tooltip.d.ts +6 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-tooltip.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/tooltip/rt-tooltip.component.ts","../../../projects/ui-kit-v2/src/lib/components/tooltip/rt-tooltip.logic.ts","../../../projects/ui-kit-v2/src/lib/components/tooltip/rt-tooltip.directive.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, signal, ViewEncapsulation, WritableSignal } from '@angular/core';\n\nconst BEM_BLOCK: string = 'rt-tooltip';\n\n/**\n * Презентационная панель tooltip'а. Рендерится директивой `[rtTooltip]` через\n * CDK `ComponentPortal` в overlay; текст выставляется императивно\n * (`ref.instance.text.set(...)`) — отдельного `input()` нет, т.к. компонент\n * создаётся вручную, а не в шаблоне.\n *\n * `ViewEncapsulation.None` — стили префиксованы `.rt-tooltip` (единообразно с\n * остальным common/ui). `role=\"tooltip\"` — вспомогательный ярлык для AT.\n */\n@Component({\n selector: 'rt-tooltip',\n template: '{{ text() }}',\n styleUrl: './rt-tooltip.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: BEM_BLOCK,\n role: 'tooltip',\n },\n})\nexport class RtTooltipComponent {\n public readonly text: WritableSignal<string> = signal<string>('');\n}\n","import { ConnectedPosition } from '@angular/cdk/overlay';\n\nimport { IRtTooltip } from './rt-tooltip.model';\n\n/** Зазор между подсказкой и host'ом. */\nconst TOOLTIP_GAP_PX: number = 6;\n\nconst POSITION_BY_PLACEMENT: Readonly<Record<IRtTooltip.Placement, ConnectedPosition>> = {\n top: { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -TOOLTIP_GAP_PX },\n bottom: { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: TOOLTIP_GAP_PX },\n left: { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -TOOLTIP_GAP_PX },\n right: { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: TOOLTIP_GAP_PX },\n};\n\nconst FALLBACKS: Readonly<Record<IRtTooltip.Placement, readonly IRtTooltip.Placement[]>> = {\n top: ['top', 'bottom'],\n bottom: ['bottom', 'top'],\n left: ['left', 'right', 'top', 'bottom'],\n right: ['right', 'left', 'top', 'bottom'],\n};\n\n/**\n * Позиции подсказки по порядку попыток: заданная сторона, противоположная, а у боковой ещё\n * верх и низ — на узком экране сбоку не помещается ни одна сторона, и подсказка, придвинутая\n * к краю, легла бы на сам host. Бока заданы логическими `start`/`end`: в письме справа налево\n * `left` встаёт справа — как и вся раскладка кита.\n */\n/**\n * Сторона подсказки: своя на элементе, иначе из настроек кита, иначе сверху, а под материальным\n * набором снизу, как у первого кита.\n */\nexport function tooltipPlacement(\n own: IRtTooltip.Placement | null,\n configured: IRtTooltip.Placement | null,\n materialPreset: boolean\n): IRtTooltip.Placement {\n return own ?? configured ?? (materialPreset ? 'bottom' : 'top');\n}\n\nexport function tooltipPositions(placement: IRtTooltip.Placement): ConnectedPosition[] {\n return FALLBACKS[placement].map((side: IRtTooltip.Placement): ConnectedPosition => ({ ...POSITION_BY_PLACEMENT[side] }));\n}\n\n/** Размеры узла, по которым судят об обрезке: видимая ширина и ширина содержимого. */\nexport interface IRtTooltipBox {\n readonly clientWidth: number;\n readonly scrollWidth: number;\n}\n\n/**\n * Текст узла обрезан: содержимое шире видимой коробки. Высота не судится — узел с видимым\n * переполнением по высоте показывает всё, и его подсказка только повторяла бы текст.\n */\nexport function isTooltipTextCut(box: IRtTooltipBox): boolean {\n return box.scrollWidth > box.clientWidth;\n}\n","import { FocusMonitor, FocusOrigin } from '@angular/cdk/a11y';\nimport { NumberInput } from '@angular/cdk/coercion';\nimport {\n ConnectedPosition,\n FlexibleConnectedPositionStrategy,\n Overlay,\n OverlayConfig,\n OverlayRef,\n ScrollStrategyOptions,\n} from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport {\n booleanAttribute,\n ComponentRef,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n numberAttribute,\n OnDestroy,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nimport { carryThemeScope, IRtKitConfig, materialPresetClassesOf, rtKitDefault } from '@rt-tools/ui-kit-v2/core';\nimport { RtTooltipComponent } from './rt-tooltip.component';\nimport { isTooltipTextCut, tooltipPlacement, tooltipPositions } from './rt-tooltip.logic';\nimport { IRtTooltip } from './rt-tooltip.model';\n\nconst SHOW_DELAY_MS: number = 300;\nconst VIEWPORT_MARGIN: number = 8;\n\n/**\n * Tooltip-директива поверх CDK Overlay. Показывает короткую подсказку\n * (`rtTooltip` = строка) на hover/focus host'а. Движок — CDK `flexibleConnectedTo`\n * (авто-flip у края viewport, reposition при скролле), так что подсказка не\n * режется `overflow: hidden` предками (таблицы, aside, карточки).\n *\n * Триггеры: `mouseenter` и фокус с клавиатуры показывают (с задержкой `SHOW_DELAY_MS`),\n * `mouseleave`/`focusout`/`click` прячут. Фокус, поставленный мышью или кодом, подсказку не\n * показывает, как у Material: меню возвращает фокус кнопке после выбора пункта мышью, и\n * подсказка кнопки всплывала поверх того, что пункт открыл. Пустой текст → no-op (директива\n * выключена), поэтому её можно безусловно вешать на icon-кнопки и включать\n * выставлением строки.\n *\n * @example\n * ```html\n * <rt-icon-button icon=\"ico-trash\" ariaLabel=\"Удалить\" tooltip=\"Удалить\" />\n * <button rtButton [rtTooltip]=\"'Подсказка'\">…</button>\n * ```\n */\n@Directive({\n selector: '[rtTooltip]',\n exportAs: 'rtTooltip',\n host: {\n '(mouseenter)': 'show()',\n '(mouseleave)': 'hide()',\n '(focusout)': 'hide()',\n '(click)': 'onClick()',\n },\n})\nexport class RtTooltipDirective implements OnDestroy {\n readonly #overlay: Overlay = inject(Overlay);\n readonly #elementRef: ElementRef<HTMLElement> = inject<ElementRef<HTMLElement>>(ElementRef);\n readonly #scrollStrategies: ScrollStrategyOptions = inject(ScrollStrategyOptions);\n readonly #focusMonitor: FocusMonitor = inject(FocusMonitor);\n\n #overlayRef: OverlayRef | null = null;\n #tooltipRef: ComponentRef<RtTooltipComponent> | null = null;\n #showTimer: ReturnType<typeof setTimeout> | null = null;\n /**\n * Сторона из настроек кита. Не умолчание входа: обёртка кита, передающая свой `null`, перебила\n * бы настройку приложения.\n */\n readonly #placementDefault: IRtTooltip.Placement | null = rtKitDefault(\n 'tooltip',\n (it: IRtKitConfig.Tooltip): IRtTooltip.Placement | undefined => it.placement,\n null\n );\n /**\n * Задержка показа по умолчанию: из настроек кита `components.tooltip.showDelay`, без них —\n * `SHOW_DELAY_MS`. Не умолчание входа — по той же причине, что и сторона.\n */\n readonly #showDelayDefault: number = rtKitDefault(\n 'tooltip',\n (it: IRtKitConfig.Tooltip): number | undefined => it.showDelay,\n SHOW_DELAY_MS\n );\n\n /**\n * Текст подсказки. Принимает `null`/`undefined` (частый результат date-пайпа\n * или nullable-полей модели) и нормализует их в пустую строку — иначе\n * биндинги вида `value | date` ломали бы строгую типизацию шаблона. Пустая\n * строка → no-op (директива выключена).\n */\n public readonly text: InputSignalWithTransform<string, string | null | undefined> = input<string, string | null | undefined>('', {\n alias: 'rtTooltip',\n transform: (value: string | null | undefined): string => value ?? '',\n });\n\n /**\n * Сторона подсказки. `null` — сторона из настроек кита `components.tooltip.placement`, без них\n * сверху, а под материальным набором снизу, как у первого кита.\n */\n public readonly placement: InputSignal<IRtTooltip.Placement | null> = input<IRtTooltip.Placement | null>(null, {\n alias: 'rtTooltipPlacement',\n });\n\n /**\n * Задержка показа этой подсказки в миллисекундах. `null` — общая задержка из настроек кита, без\n * них 300.\n */\n public readonly showDelay: InputSignalWithTransform<number | null, NumberInput> = input<number | null, NumberInput>(null, {\n alias: 'rtTooltipShowDelay',\n transform: (value: NumberInput): number | null => {\n const delay: number = value === null || value === undefined || value === '' ? Number.NaN : numberAttribute(value, Number.NaN);\n return delay >= 0 ? delay : null;\n },\n });\n\n /**\n * Подсказка только у обрезанного текста: хост меряется в момент показа, и подсказка не\n * появляется, пока его содержимое помещается целиком. Мерить заранее не нужно — показ идёт\n * только отсюда, и признак в эту минуту всегда свежий.\n */\n public readonly whenTruncated: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n alias: 'rtTooltipWhenTruncated',\n transform: booleanAttribute,\n });\n\n /**\n * Клик прячет открытую подсказку — по умолчанию, как раньше; умолчание на всё приложение —\n * `components.tooltip.hideOnClick` в настройках кита. `false` оставляет её открытой:\n * кнопка-переключатель показывает в ней новое состояние сразу после нажатия. Отложенный показ\n * клик снимает при любом значении — касание на тач-экране (mouseenter + click) подсказку не\n * показывает.\n */\n public readonly hideOnClick: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(\n rtKitDefault('tooltip', (it: IRtKitConfig.Tooltip): boolean | undefined => it.hideOnClick, true),\n {\n alias: 'rtTooltipHideOnClick',\n transform: booleanAttribute,\n }\n );\n\n constructor() {\n // Новый текст доходит до открытой панели на месте, без повторного наведения.\n effect((): void => this.#syncText(this.text()));\n this.#focusMonitor\n .monitor(this.#elementRef, true)\n .pipe(takeUntilDestroyed())\n .subscribe((origin: FocusOrigin): void => {\n if (origin === 'keyboard') {\n this.show();\n }\n });\n }\n\n public ngOnDestroy(): void {\n this.#focusMonitor.stopMonitoring(this.#elementRef);\n this.#clearTimer();\n this.#disposeOverlay();\n }\n\n protected show(): void {\n if (this.text().trim() === '' || this.#tooltipRef !== null) {\n return;\n }\n this.#clearTimer();\n this.#showTimer = setTimeout((): void => this.#attach(), this.showDelay() ?? this.#showDelayDefault);\n }\n\n protected hide(): void {\n this.#clearTimer();\n this.#overlayRef?.detach();\n this.#tooltipRef = null;\n }\n\n protected onClick(): void {\n if (this.hideOnClick() || this.#tooltipRef === null) {\n this.hide();\n }\n }\n\n #syncText(text: string): void {\n if (this.#tooltipRef === null) {\n return;\n }\n if (text.trim() === '') {\n this.hide();\n return;\n }\n this.#tooltipRef.instance.text.set(text);\n this.#tooltipRef.changeDetectorRef.markForCheck();\n this.#overlayRef?.updatePosition();\n }\n\n #attach(): void {\n if (this.text().trim() === '' || (this.whenTruncated() && !isTooltipTextCut(this.#elementRef.nativeElement))) {\n return;\n }\n const overlayRef: OverlayRef = this.#ensureOverlay();\n // Коробка переживает закрытие, а кусок темы вокруг host'а мог смениться — переносим на каждом показе.\n carryThemeScope(overlayRef.overlayElement, this.#elementRef.nativeElement);\n const portal: ComponentPortal<RtTooltipComponent> = new ComponentPortal(RtTooltipComponent);\n this.#tooltipRef = overlayRef.attach(portal);\n this.#tooltipRef.instance.text.set(this.text());\n this.#tooltipRef.changeDetectorRef.markForCheck();\n }\n\n #ensureOverlay(): OverlayRef {\n if (this.#overlayRef !== null) {\n return this.#overlayRef;\n }\n const presetClasses: string[] = materialPresetClassesOf(this.#elementRef.nativeElement);\n const placement: IRtTooltip.Placement = tooltipPlacement(this.placement(), this.#placementDefault, presetClasses.length > 0);\n const positions: ConnectedPosition[] = tooltipPositions(placement);\n\n const positionStrategy: FlexibleConnectedPositionStrategy = this.#overlay\n .position()\n .flexibleConnectedTo(this.#elementRef)\n .withPush(true)\n .withViewportMargin(VIEWPORT_MARGIN)\n .withFlexibleDimensions(false)\n .withPositions(positions);\n\n const config: OverlayConfig = new OverlayConfig({\n positionStrategy,\n scrollStrategy: this.#scrollStrategies.reposition(),\n hasBackdrop: false,\n panelClass: ['rt-tooltip-panel', ...presetClasses],\n });\n this.#overlayRef = this.#overlay.create(config);\n return this.#overlayRef;\n }\n\n #clearTimer(): void {\n if (this.#showTimer !== null) {\n clearTimeout(this.#showTimer);\n this.#showTimer = null;\n }\n }\n\n #disposeOverlay(): void {\n this.#overlayRef?.dispose();\n this.#overlayRef = null;\n this.#tooltipRef = null;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-tooltip.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/tooltip/rt-tooltip.component.ts","../../../projects/ui-kit-v2/src/lib/components/tooltip/rt-tooltip.logic.ts","../../../projects/ui-kit-v2/src/lib/components/tooltip/rt-tooltip.directive.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, signal, ViewEncapsulation, WritableSignal } from '@angular/core';\n\nconst BEM_BLOCK: string = 'rt-tooltip';\n\n/**\n * Презентационная панель tooltip'а. Рендерится директивой `[rtTooltip]` через\n * CDK `ComponentPortal` в overlay; текст выставляется императивно\n * (`ref.instance.text.set(...)`) — отдельного `input()` нет, т.к. компонент\n * создаётся вручную, а не в шаблоне.\n *\n * `ViewEncapsulation.None` — стили префиксованы `.rt-tooltip` (единообразно с\n * остальным common/ui). `role=\"tooltip\"` — вспомогательный ярлык для AT.\n */\n@Component({\n selector: 'rt-tooltip',\n template: '{{ text() }}',\n styleUrl: './rt-tooltip.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: BEM_BLOCK,\n role: 'tooltip',\n },\n})\nexport class RtTooltipComponent {\n public readonly text: WritableSignal<string> = signal<string>('');\n}\n","import { ConnectedPosition } from '@angular/cdk/overlay';\n\nimport { IRtTooltip } from './rt-tooltip.model';\n\n/** Зазор между подсказкой и host'ом. */\nconst TOOLTIP_GAP_PX: number = 6;\n\nconst POSITION_BY_PLACEMENT: Readonly<Record<IRtTooltip.Placement, ConnectedPosition>> = {\n top: { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -TOOLTIP_GAP_PX },\n bottom: { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: TOOLTIP_GAP_PX },\n left: { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -TOOLTIP_GAP_PX },\n right: { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: TOOLTIP_GAP_PX },\n};\n\nconst FALLBACKS: Readonly<Record<IRtTooltip.Placement, readonly IRtTooltip.Placement[]>> = {\n top: ['top', 'bottom'],\n bottom: ['bottom', 'top'],\n left: ['left', 'right', 'top', 'bottom'],\n right: ['right', 'left', 'top', 'bottom'],\n};\n\n/**\n * Позиции подсказки по порядку попыток: заданная сторона, противоположная, а у боковой ещё\n * верх и низ — на узком экране сбоку не помещается ни одна сторона, и подсказка, придвинутая\n * к краю, легла бы на сам host. Бока заданы логическими `start`/`end`: в письме справа налево\n * `left` встаёт справа — как и вся раскладка кита.\n */\n/**\n * Сторона подсказки: своя на элементе, иначе из настроек кита, иначе сверху, а под материальным\n * набором снизу, как у первого кита.\n */\nexport function tooltipPlacement(\n own: IRtTooltip.Placement | null,\n configured: IRtTooltip.Placement | null,\n materialPreset: boolean\n): IRtTooltip.Placement {\n return own ?? configured ?? (materialPreset ? 'bottom' : 'top');\n}\n\nexport function tooltipPositions(placement: IRtTooltip.Placement): ConnectedPosition[] {\n return FALLBACKS[placement].map((side: IRtTooltip.Placement): ConnectedPosition => ({ ...POSITION_BY_PLACEMENT[side] }));\n}\n\n/** Размеры узла, по которым судят об обрезке: видимая ширина и ширина содержимого. */\nexport interface IRtTooltipBox {\n readonly clientWidth: number;\n readonly scrollWidth: number;\n}\n\n/**\n * Текст узла обрезан: содержимое шире видимой коробки. Высота не судится — узел с видимым\n * переполнением по высоте показывает всё, и его подсказка только повторяла бы текст.\n */\nexport function isTooltipTextCut(box: IRtTooltipBox): boolean {\n return box.scrollWidth > box.clientWidth;\n}\n","import { FocusMonitor, FocusOrigin } from '@angular/cdk/a11y';\nimport { NumberInput } from '@angular/cdk/coercion';\nimport { hasModifierKey } from '@angular/cdk/keycodes';\nimport {\n ConnectedPosition,\n FlexibleConnectedPositionStrategy,\n Overlay,\n OverlayConfig,\n OverlayRef,\n ScrollStrategyOptions,\n} from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport {\n booleanAttribute,\n ComponentRef,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n numberAttribute,\n OnDestroy,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\n\nimport { carryThemeScope, IRtKitConfig, materialPresetClassesOf, rtKitDefault } from '@rt-tools/ui-kit-v2/core';\nimport { RtTooltipComponent } from './rt-tooltip.component';\nimport { isTooltipTextCut, tooltipPlacement, tooltipPositions } from './rt-tooltip.logic';\nimport { IRtTooltip } from './rt-tooltip.model';\n\nconst SHOW_DELAY_MS: number = 300;\nconst VIEWPORT_MARGIN: number = 8;\n\n/**\n * Tooltip-директива поверх CDK Overlay. Показывает короткую подсказку\n * (`rtTooltip` = строка) на hover/focus host'а. Движок — CDK `flexibleConnectedTo`\n * (авто-flip у края viewport, reposition при скролле), так что подсказка не\n * режется `overflow: hidden` предками (таблицы, aside, карточки).\n *\n * Триггеры: `mouseenter` и фокус с клавиатуры показывают (с задержкой `SHOW_DELAY_MS`),\n * `mouseleave`/`focusout`/`click`/Escape прячут. Фокус, поставленный мышью или кодом, подсказку не\n * показывает, как у Material: меню возвращает фокус кнопке после выбора пункта мышью, и\n * подсказка кнопки всплывала поверх того, что пункт открыл. Пустой текст → no-op (директива\n * выключена), поэтому её можно безусловно вешать на icon-кнопки и включать\n * выставлением строки.\n *\n * @example\n * ```html\n * <rt-icon-button icon=\"ico-trash\" ariaLabel=\"Удалить\" tooltip=\"Удалить\" />\n * <button rtButton [rtTooltip]=\"'Подсказка'\">…</button>\n * ```\n */\n@Directive({\n selector: '[rtTooltip]',\n exportAs: 'rtTooltip',\n host: {\n '(mouseenter)': 'show()',\n '(mouseleave)': 'hide()',\n '(focusout)': 'hide()',\n '(click)': 'onClick()',\n '(keydown)': 'onKeydown($event)',\n },\n})\nexport class RtTooltipDirective implements OnDestroy {\n readonly #overlay: Overlay = inject(Overlay);\n readonly #elementRef: ElementRef<HTMLElement> = inject<ElementRef<HTMLElement>>(ElementRef);\n readonly #scrollStrategies: ScrollStrategyOptions = inject(ScrollStrategyOptions);\n readonly #focusMonitor: FocusMonitor = inject(FocusMonitor);\n\n #overlayRef: OverlayRef | null = null;\n #tooltipRef: ComponentRef<RtTooltipComponent> | null = null;\n #showTimer: ReturnType<typeof setTimeout> | null = null;\n /**\n * Сторона из настроек кита. Не умолчание входа: обёртка кита, передающая свой `null`, перебила\n * бы настройку приложения.\n */\n readonly #placementDefault: IRtTooltip.Placement | null = rtKitDefault(\n 'tooltip',\n (it: IRtKitConfig.Tooltip): IRtTooltip.Placement | undefined => it.placement,\n null\n );\n /**\n * Задержка показа по умолчанию: из настроек кита `components.tooltip.showDelay`, без них —\n * `SHOW_DELAY_MS`. Не умолчание входа — по той же причине, что и сторона.\n */\n readonly #showDelayDefault: number = rtKitDefault(\n 'tooltip',\n (it: IRtKitConfig.Tooltip): number | undefined => it.showDelay,\n SHOW_DELAY_MS\n );\n\n /**\n * Текст подсказки. Принимает `null`/`undefined` (частый результат date-пайпа\n * или nullable-полей модели) и нормализует их в пустую строку — иначе\n * биндинги вида `value | date` ломали бы строгую типизацию шаблона. Пустая\n * строка → no-op (директива выключена).\n */\n public readonly text: InputSignalWithTransform<string, string | null | undefined> = input<string, string | null | undefined>('', {\n alias: 'rtTooltip',\n transform: (value: string | null | undefined): string => value ?? '',\n });\n\n /**\n * Сторона подсказки. `null` — сторона из настроек кита `components.tooltip.placement`, без них\n * сверху, а под материальным набором снизу, как у первого кита.\n */\n public readonly placement: InputSignal<IRtTooltip.Placement | null> = input<IRtTooltip.Placement | null>(null, {\n alias: 'rtTooltipPlacement',\n });\n\n /**\n * Задержка показа этой подсказки в миллисекундах. `null` — общая задержка из настроек кита, без\n * них 300.\n */\n public readonly showDelay: InputSignalWithTransform<number | null, NumberInput> = input<number | null, NumberInput>(null, {\n alias: 'rtTooltipShowDelay',\n transform: (value: NumberInput): number | null => {\n const delay: number = value === null || value === undefined || value === '' ? Number.NaN : numberAttribute(value, Number.NaN);\n return delay >= 0 ? delay : null;\n },\n });\n\n /**\n * Подсказка только у обрезанного текста: хост меряется в момент показа, и подсказка не\n * появляется, пока его содержимое помещается целиком. Мерить заранее не нужно — показ идёт\n * только отсюда, и признак в эту минуту всегда свежий.\n */\n public readonly whenTruncated: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(false, {\n alias: 'rtTooltipWhenTruncated',\n transform: booleanAttribute,\n });\n\n /**\n * Клик прячет открытую подсказку — по умолчанию, как раньше; умолчание на всё приложение —\n * `components.tooltip.hideOnClick` в настройках кита. `false` оставляет её открытой:\n * кнопка-переключатель показывает в ней новое состояние сразу после нажатия. Отложенный показ\n * клик снимает при любом значении — касание на тач-экране (mouseenter + click) подсказку не\n * показывает.\n */\n public readonly hideOnClick: InputSignalWithTransform<boolean, unknown> = input<boolean, unknown>(\n rtKitDefault('tooltip', (it: IRtKitConfig.Tooltip): boolean | undefined => it.hideOnClick, true),\n {\n alias: 'rtTooltipHideOnClick',\n transform: booleanAttribute,\n }\n );\n\n constructor() {\n // Новый текст доходит до открытой панели на месте, без повторного наведения.\n effect((): void => this.#syncText(this.text()));\n this.#focusMonitor\n .monitor(this.#elementRef, true)\n .pipe(takeUntilDestroyed())\n .subscribe((origin: FocusOrigin): void => {\n if (origin === 'keyboard') {\n this.show();\n }\n });\n }\n\n public ngOnDestroy(): void {\n this.#focusMonitor.stopMonitoring(this.#elementRef);\n this.#clearTimer();\n this.#disposeOverlay();\n }\n\n protected show(): void {\n if (this.text().trim() === '' || this.#tooltipRef !== null) {\n return;\n }\n this.#clearTimer();\n this.#showTimer = setTimeout((): void => this.#attach(), this.showDelay() ?? this.#showDelayDefault);\n }\n\n protected hide(): void {\n this.#clearTimer();\n this.#overlayRef?.detach();\n this.#tooltipRef = null;\n }\n\n protected onClick(): void {\n if (this.hideOnClick() || this.#tooltipRef === null) {\n this.hide();\n }\n }\n\n /**\n * Escape прячет подсказку и снимает отложенный показ, фокус остаётся на хосте. Событие гасится,\n * только когда панель была открыта: при закрытой Escape доходит до диалога или панели выше.\n */\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key !== 'Escape' || hasModifierKey(event)) {\n return;\n }\n const wasOpen: boolean = this.#tooltipRef !== null;\n this.hide();\n if (wasOpen) {\n event.preventDefault();\n event.stopPropagation();\n }\n }\n\n #syncText(text: string): void {\n if (this.#tooltipRef === null) {\n return;\n }\n if (text.trim() === '') {\n this.hide();\n return;\n }\n this.#tooltipRef.instance.text.set(text);\n this.#tooltipRef.changeDetectorRef.markForCheck();\n this.#overlayRef?.updatePosition();\n }\n\n #attach(): void {\n if (this.text().trim() === '' || (this.whenTruncated() && !isTooltipTextCut(this.#elementRef.nativeElement))) {\n return;\n }\n const overlayRef: OverlayRef = this.#ensureOverlay();\n // Коробка переживает закрытие, а кусок темы вокруг host'а мог смениться — переносим на каждом показе.\n carryThemeScope(overlayRef.overlayElement, this.#elementRef.nativeElement);\n const portal: ComponentPortal<RtTooltipComponent> = new ComponentPortal(RtTooltipComponent);\n this.#tooltipRef = overlayRef.attach(portal);\n this.#tooltipRef.instance.text.set(this.text());\n this.#tooltipRef.changeDetectorRef.markForCheck();\n }\n\n #ensureOverlay(): OverlayRef {\n if (this.#overlayRef !== null) {\n return this.#overlayRef;\n }\n const presetClasses: string[] = materialPresetClassesOf(this.#elementRef.nativeElement);\n const placement: IRtTooltip.Placement = tooltipPlacement(this.placement(), this.#placementDefault, presetClasses.length > 0);\n const positions: ConnectedPosition[] = tooltipPositions(placement);\n\n const positionStrategy: FlexibleConnectedPositionStrategy = this.#overlay\n .position()\n .flexibleConnectedTo(this.#elementRef)\n .withPush(true)\n .withViewportMargin(VIEWPORT_MARGIN)\n .withFlexibleDimensions(false)\n .withPositions(positions);\n\n const config: OverlayConfig = new OverlayConfig({\n positionStrategy,\n scrollStrategy: this.#scrollStrategies.reposition(),\n hasBackdrop: false,\n panelClass: ['rt-tooltip-panel', ...presetClasses],\n });\n this.#overlayRef = this.#overlay.create(config);\n return this.#overlayRef;\n }\n\n #clearTimer(): void {\n if (this.#showTimer !== null) {\n clearTimeout(this.#showTimer);\n this.#showTimer = null;\n }\n }\n\n #disposeOverlay(): void {\n this.#overlayRef?.dispose();\n this.#overlayRef = null;\n this.#tooltipRef = null;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-workspace-details.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/workspace-details/rt-workspace-details.component.ts","../../../projects/ui-kit-v2/src/lib/components/workspace-details/rt-workspace-details.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport { DecimalPipe, NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n output,\n OutputEmitterRef,\n signal,\n Signal,\n untracked,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\nimport { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';\n\nimport { BlockDirective, ElemDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { NotificationBus } from '@rt-tools/ui-kit-v2/core';\n\nimport { RtAsideSectionComponent } from '@rt-tools/ui-kit-v2/aside-section';\nimport { RtButtonDirective } from '@rt-tools/ui-kit-v2/button';\nimport { RtConfirmDirective } from '@rt-tools/ui-kit-v2/confirm-popover';\nimport { RtDetailListComponent } from '@rt-tools/ui-kit-v2/detail-list';\nimport { RtDetailRowComponent } from '@rt-tools/ui-kit-v2/detail-list';\nimport { RtEmptyStateComponent } from '@rt-tools/ui-kit-v2/empty-state';\nimport { RtFieldComponent } from '@rt-tools/ui-kit-v2/field';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtMoneyListComponent } from '@rt-tools/ui-kit-v2/money-list';\nimport { RtMoneyRowComponent } from '@rt-tools/ui-kit-v2/money-list';\nimport { RtNoteComponent } from '@rt-tools/ui-kit-v2/note';\nimport { RtSelectComponent } from '@rt-tools/ui-kit-v2/select';\nimport { RtSpinnerComponent } from '@rt-tools/ui-kit-v2/spinner';\nimport { RtTabDirective } from '@rt-tools/ui-kit-v2/tabs';\nimport { RtTabsComponent } from '@rt-tools/ui-kit-v2/tabs';\nimport { RtTextareaComponent } from '@rt-tools/ui-kit-v2/textarea';\nimport { RtTimelineComponent } from '@rt-tools/ui-kit-v2/timeline';\nimport { RtToggleSwitchComponent } from '@rt-tools/ui-kit-v2/toggle-switch';\nimport { IRtWorkspaceDetails } from './rt-workspace-details.model';\n\nconst BEM_BLOCK: string = 'rt-workspace-details';\n\ninterface ITransitionFormShape {\n to_key: FormControl<string | null>;\n note: FormControl<string | null>;\n}\n\n@Component({\n selector: 'rt-workspace-details',\n templateUrl: './rt-workspace-details.component.html',\n styleUrls: ['./rt-workspace-details.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n DecimalPipe,\n FormsModule,\n NgTemplateOutlet,\n ReactiveFormsModule,\n\n // standalone components / directives\n RtAsideSectionComponent,\n RtButtonDirective,\n RtConfirmDirective,\n RtDetailListComponent,\n RtDetailRowComponent,\n RtEmptyStateComponent,\n RtFieldComponent,\n RtIconButtonComponent,\n RtMoneyListComponent,\n RtMoneyRowComponent,\n RtNoteComponent,\n RtSelectComponent,\n RtSpinnerComponent,\n RtTabDirective,\n RtTabsComponent,\n RtTextareaComponent,\n RtTimelineComponent,\n RtToggleSwitchComponent,\n BlockDirective,\n ElemDirective,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtWorkspaceDetailsComponent {\n readonly #notificationBus: NotificationBus = inject(NotificationBus);\n\n readonly #lastEntityId: WritableSignal<number | null | undefined> = signal<number | null | undefined>(undefined);\n\n readonly #lastAgentId: WritableSignal<number | null | undefined> = signal<number | null | undefined>(undefined);\n\n #lastTransitionSuccess: string | null = null;\n\n #lastTransitionError: string | null = null;\n\n #lastTransitionSubmitError: string | null = null;\n\n #lastAuditError: string | null = null;\n\n #lastPanelError: string | null = null;\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly editingAgent: WritableSignal<boolean> = signal<boolean>(false);\n\n protected readonly selectedAgentId: WritableSignal<number | null> = signal<number | null>(null);\n\n protected readonly transitionForm: FormGroup<ITransitionFormShape> = new FormGroup<ITransitionFormShape>({\n to_key: new FormControl<string | null>(null, {\n validators: [Validators.required],\n }),\n note: new FormControl<string | null>(null),\n });\n\n protected readonly hasTabs: Signal<boolean> = computed((): boolean => this.transition() !== null || this.audit() !== null);\n\n protected readonly noTransitions: Signal<boolean> = computed((): boolean => {\n const transition: IRtWorkspaceDetails.Transition | null = this.transition();\n return transition !== null && !transition.loading && transition.error === null && transition.options.length === 0;\n });\n\n protected readonly canSaveReassign: Signal<boolean> = computed((): boolean => {\n const edit: IRtWorkspaceDetails.AgentEdit | null = this.agentEdit();\n const selected: number | null = this.selectedAgentId();\n return edit !== null && selected !== null && selected !== edit.currentAgentId;\n });\n\n public readonly title: InputSignal<string | null> = input<string | null>(null);\n\n public readonly entityId: InputSignal<number | null> = input<number | null>(null);\n\n public readonly loading: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly busy: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly rows: InputSignal<readonly IRtWorkspaceDetails.Row[]> = input<readonly IRtWorkspaceDetails.Row[]>([]);\n\n public readonly agentEdit: InputSignal<IRtWorkspaceDetails.AgentEdit | null> = input<IRtWorkspaceDetails.AgentEdit | null>(null);\n\n public readonly money: InputSignal<readonly IRtWorkspaceDetails.MoneyRow[]> = input<readonly IRtWorkspaceDetails.MoneyRow[]>([]);\n\n public readonly toggles: InputSignal<readonly IRtWorkspaceDetails.Toggle[]> = input<readonly IRtWorkspaceDetails.Toggle[]>([]);\n\n public readonly toggleHint: InputSignal<string | null> = input<string | null>(null);\n\n public readonly transition: InputSignal<IRtWorkspaceDetails.Transition | null> = input<IRtWorkspaceDetails.Transition | null>(null);\n\n public readonly audit: InputSignal<IRtWorkspaceDetails.Audit | null> = input<IRtWorkspaceDetails.Audit | null>(null);\n\n public readonly actions: InputSignal<readonly IRtWorkspaceDetails.Action[]> = input<readonly IRtWorkspaceDetails.Action[]>([]);\n\n public readonly error: InputSignal<string | null> = input<string | null>(null);\n\n public readonly toggleChange: OutputEmitterRef<IRtWorkspaceDetails.ToggleChange> = output<IRtWorkspaceDetails.ToggleChange>();\n\n public readonly agentReassign: OutputEmitterRef<number> = output<number>();\n\n public readonly transitionSubmit: OutputEmitterRef<IRtWorkspaceDetails.TransitionSubmit> =\n output<IRtWorkspaceDetails.TransitionSubmit>();\n\n public readonly transitionSuccessClose: OutputEmitterRef<void> = output<void>();\n\n public readonly transitionErrorClose: OutputEmitterRef<void> = output<void>();\n\n public readonly auditLoadMore: OutputEmitterRef<void> = output<void>();\n\n public readonly actionClicked: OutputEmitterRef<string> = output<string>();\n\n constructor() {\n effect((): void => {\n const id: number | null = this.entityId();\n if (id === untracked((): number | null | undefined => this.#lastEntityId())) {\n return;\n }\n this.#lastEntityId.set(id);\n this.editingAgent.set(false);\n this.selectedAgentId.set(untracked((): IRtWorkspaceDetails.AgentEdit | null => this.agentEdit())?.currentAgentId ?? null);\n this.transitionForm.reset();\n });\n\n effect((): void => {\n const currentAgentId: number | null = this.agentEdit()?.currentAgentId ?? null;\n if (currentAgentId === untracked((): number | null | undefined => this.#lastAgentId())) {\n return;\n }\n this.#lastAgentId.set(currentAgentId);\n this.editingAgent.set(false);\n this.selectedAgentId.set(currentAgentId);\n });\n\n effect((): void => {\n if (this.transition()?.success != null) {\n this.transitionForm.reset();\n }\n });\n\n effect((): void => {\n const successText: string | null = this.transition()?.success ?? null;\n if (successText !== null && successText !== this.#lastTransitionSuccess) {\n this.transitionSuccessClose.emit();\n }\n this.#lastTransitionSuccess = successText;\n });\n\n effect((): void => {\n const submitError: string | null = this.transition()?.submitError ?? null;\n if (submitError !== null && submitError !== this.#lastTransitionSubmitError) {\n this.#notificationBus.error(submitError);\n this.transitionErrorClose.emit();\n }\n this.#lastTransitionSubmitError = submitError;\n });\n\n effect((): void => {\n const transitionError: string | null = this.transition()?.error ?? null;\n if (transitionError !== null && transitionError !== this.#lastTransitionError) {\n this.#notificationBus.error(transitionError);\n }\n this.#lastTransitionError = transitionError;\n });\n\n effect((): void => {\n const auditError: string | null = this.audit()?.error ?? null;\n if (auditError !== null && auditError !== this.#lastAuditError) {\n this.#notificationBus.error(auditError);\n }\n this.#lastAuditError = auditError;\n });\n\n effect((): void => {\n const panelError: string | null = this.error();\n if (panelError !== null && panelError !== this.#lastPanelError) {\n this.#notificationBus.error(panelError);\n }\n this.#lastPanelError = panelError;\n });\n }\n\n protected startEditAgent(): void {\n const edit: IRtWorkspaceDetails.AgentEdit | null = this.agentEdit();\n if (edit === null || !edit.canEdit || this.busy()) {\n return;\n }\n this.selectedAgentId.set(edit.currentAgentId);\n this.editingAgent.set(true);\n }\n\n protected cancelEditAgent(): void {\n const edit: IRtWorkspaceDetails.AgentEdit | null = this.agentEdit();\n if (edit !== null && edit.loading) {\n return;\n }\n this.selectedAgentId.set(edit?.currentAgentId ?? null);\n this.editingAgent.set(false);\n }\n\n protected onReassign(): void {\n const agentId: number | null = this.selectedAgentId();\n if (agentId === null || !this.canSaveReassign() || this.busy()) {\n return;\n }\n this.agentReassign.emit(agentId);\n }\n\n protected onSelectedAgentChange(agentId: number | null): void {\n this.selectedAgentId.set(agentId);\n }\n\n protected onToggleChange(toggle: IRtWorkspaceDetails.Toggle, value: boolean): void {\n if (toggle.value === value) {\n return;\n }\n this.toggleChange.emit({ id: toggle.id, value });\n }\n\n protected onTransitionSubmit(): void {\n const transition: IRtWorkspaceDetails.Transition | null = this.transition();\n if (transition === null || transition.submitting) {\n return;\n }\n if (!this.transitionForm.valid) {\n this.transitionForm.markAllAsTouched();\n return;\n }\n\n const value: ReturnType<typeof this.transitionForm.getRawValue> = this.transitionForm.getRawValue();\n this.transitionSubmit.emit({\n stageKey: value.to_key ?? '',\n comment: value.note?.trim() ?? '',\n });\n }\n\n protected onAuditLoadMore(): void {\n this.auditLoadMore.emit();\n }\n\n protected onAction(action: IRtWorkspaceDetails.Action): void {\n if ((action.disabled ?? false) || this.busy()) {\n return;\n }\n this.actionClicked.emit(action.id);\n }\n}\n","<ng-container rtBlock=\"rt-workspace-details\">\n @if (title(); as headTitle) {\n <header rtElem=\"head\">\n <span rtElem=\"head-title\" qa-dataid=\"workspace-details-title\">{{ headTitle }}</span>\n </header>\n }\n\n @if (hasTabs()) {\n <rt-tabs rtElem=\"tabs\" qa-dataid=\"workspace-details-tabs\">\n <ng-template rtTab=\"details\" [label]=\"t().uiDetails\">\n <ng-container [ngTemplateOutlet]=\"detailsTpl\" />\n </ng-template>\n\n <ng-template rtTab=\"transition\" [label]=\"t().uiStageTransition\" [hidden]=\"transition() === null\">\n @if (transition(); as stageTransition) {\n @if (stageTransition.currentStageLabel; as stageLabel) {\n <rt-detail-list>\n <rt-detail-row qa-dataid=\"workspace-details-current-stage\" [label]=\"t().uiCurrentStage\">\n {{ stageLabel }}\n </rt-detail-row>\n </rt-detail-list>\n }\n\n @if (noTransitions()) {\n <rt-note qa-dataid=\"workspace-details-no-transitions\">{{ stageTransition.noTransitionsText }}</rt-note>\n } @else {\n <form\n rtElem=\"transition-form\"\n qa-dataid=\"workspace-details-transition-form\"\n [formGroup]=\"transitionForm\"\n (ngSubmit)=\"onTransitionSubmit()\">\n <rt-field\n [label]=\"t().uiTargetStage\"\n [loading]=\"stageTransition.loading\"\n [errors]=\"{ required: t().uiTargetStageRequired }\">\n <rt-select\n formControlName=\"to_key\"\n qa-dataid=\"workspace-details-transition-stage\"\n [placeholder]=\"t().uiPickTransition\"\n [options]=\"stageTransition.options\" />\n </rt-field>\n\n <rt-field [label]=\"t().uiCommentOptional\" [hint]=\"t().uiStageNoteHint\" [loading]=\"stageTransition.loading\">\n <rt-textarea formControlName=\"note\" qa-dataid=\"workspace-details-transition-note\" rows=\"3\" />\n </rt-field>\n\n <button\n rtButton\n rtElem=\"transition-submit\"\n qa-dataid=\"workspace-details-transition-submit\"\n type=\"submit\"\n [label]=\"t().uiMoveStage\"\n [attr.aria-label]=\"t().uiMoveStageAria\"\n [loading]=\"stageTransition.submitting\"\n [disabled]=\"stageTransition.loading || busy()\"></button>\n </form>\n }\n }\n </ng-template>\n\n <ng-template rtTab=\"audit\" [label]=\"t().uiHistory\" [hidden]=\"audit() === null\">\n @if (audit(); as auditFeed) {\n <div rtElem=\"audit\" qa-dataid=\"workspace-details-audit\">\n @if (auditFeed.loading) {\n <rt-spinner rtElem=\"audit-loading\" qa-dataid=\"workspace-details-audit-loading\" />\n } @else if (auditFeed.steps.length === 0) {\n <rt-empty-state\n qa-dataid=\"workspace-details-audit-empty\"\n icon=\"history\"\n [description]=\"t().uiAuditEmptyHint\"\n [title]=\"auditFeed.emptyText\" />\n } @else {\n <rt-timeline qa-dataid=\"workspace-details-audit-timeline\" [steps]=\"auditFeed.steps\" />\n }\n\n @if (auditFeed.hasMore) {\n <button\n rtButton\n rtElem=\"audit-more\"\n qa-dataid=\"workspace-details-audit-more\"\n type=\"button\"\n appearance=\"text\"\n [label]=\"t().uiLoadMore\"\n [attr.aria-label]=\"t().uiLoadMore\"\n [loading]=\"auditFeed.loadingMore\"\n [disabled]=\"auditFeed.loadingMore\"\n (click)=\"onAuditLoadMore()\"></button>\n }\n </div>\n }\n </ng-template>\n </rt-tabs>\n } @else {\n <div rtElem=\"body\">\n <ng-container [ngTemplateOutlet]=\"detailsTpl\" />\n </div>\n }\n\n <ng-template #detailsTpl>\n @if (rows().length > 0) {\n <rt-detail-list>\n @for (row of rows(); track row.label) {\n <rt-detail-row qa-dataid=\"workspace-details-row\" [label]=\"row.label\" [loading]=\"loading()\">\n @if (row.agent && agentEdit(); as edit) {\n @if (!editingAgent()) {\n <div rtElem=\"agent-view\">\n <span rtElem=\"agent-name\" qa-dataid=\"workspace-details-agent-name\">{{ edit.currentLabel }}</span>\n <rt-icon-button\n qa-dataid=\"workspace-details-agent-edit\"\n icon=\"pencil\"\n size=\"sm\"\n [ariaLabel]=\"t().uiChangeAgent\"\n [tooltip]=\"edit.canEdit ? edit.editTooltip : edit.cannotEditTooltip\"\n [disabled]=\"!edit.canEdit || busy()\"\n (clicked)=\"startEditAgent()\" />\n </div>\n } @else {\n <div rtElem=\"agent-edit\">\n <rt-select\n qa-dataid=\"workspace-details-agent-select\"\n [placeholder]=\"t().uiPickAgent\"\n [ngModel]=\"selectedAgentId()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"edit.options\"\n [clearable]=\"false\"\n (ngModelChange)=\"onSelectedAgentChange($event)\" />\n <rt-icon-button\n qa-dataid=\"workspace-details-agent-save\"\n icon=\"check\"\n size=\"sm\"\n rtConfirmTone=\"primary\"\n [ariaLabel]=\"t().uiSaveNewAgent\"\n [rtConfirmTitle]=\"t().uiReplaceAgentTitle\"\n [rtConfirmLabel]=\"t().uiReplace\"\n [tooltip]=\"canSaveReassign() ? t().uiSaveNewAgent : t().uiPickAnotherAgent\"\n [loading]=\"edit.loading\"\n [disabled]=\"!canSaveReassign() || busy()\"\n [rtConfirm]=\"edit.confirmText\"\n [rtConfirmDisabled]=\"!canSaveReassign() || busy()\"\n (confirmed)=\"onReassign()\" />\n <rt-icon-button\n qa-dataid=\"workspace-details-agent-cancel\"\n icon=\"ico-close\"\n size=\"sm\"\n [ariaLabel]=\"t().uiRevert\"\n [tooltip]=\"t().uiRevert\"\n [disabled]=\"edit.loading\"\n (clicked)=\"cancelEditAgent()\" />\n </div>\n }\n } @else {\n {{ row.value }}\n }\n </rt-detail-row>\n }\n </rt-detail-list>\n }\n\n @if (money().length > 0) {\n <rt-money-list>\n @for (moneyRow of money(); track moneyRow.label) {\n <rt-money-row\n qa-dataid=\"workspace-details-money-row\"\n [label]=\"moneyRow.label\"\n [total]=\"moneyRow.total ?? false\"\n [loading]=\"loading()\">\n {{ moneyRow.amount | number: moneyRow.format ?? '1.0-0' }} ₽\n </rt-money-row>\n }\n </rt-money-list>\n }\n\n @if (toggles().length > 0 || toggleHint()) {\n <rt-aside-section>\n @for (toggle of toggles(); track toggle.id) {\n <div rtElem=\"toggle-row\" qa-dataid=\"workspace-details-toggle-row\" [attr.data-id]=\"toggle.id\">\n <span rtElem=\"toggle-label\" qa-dataid=\"workspace-details-toggle-label\">{{ toggle.label }}</span>\n <rt-toggle-switch\n qa-dataid=\"workspace-details-toggle\"\n [inputId]=\"toggle.id\"\n [ariaLabel]=\"toggle.label\"\n [ngModel]=\"toggle.value\"\n [ngModelOptions]=\"{ standalone: true }\"\n [disabled]=\"(toggle.disabled ?? false) || busy()\"\n (ngModelChange)=\"onToggleChange(toggle, $event)\" />\n </div>\n }\n @if (toggleHint(); as hint) {\n <p rtElem=\"toggle-hint\" qa-dataid=\"workspace-details-toggle-hint\">{{ hint }}</p>\n }\n </rt-aside-section>\n }\n </ng-template>\n\n <footer rtElem=\"footer\">\n @for (panelAction of actions(); track panelAction.id) {\n @if (panelAction.confirm; as confirm) {\n <button\n rtButton\n rtElem=\"footer-action\"\n qa-dataid=\"workspace-details-action\"\n type=\"button\"\n [attr.data-id]=\"panelAction.id\"\n [theme]=\"panelAction.theme ?? 'primary'\"\n [appearance]=\"panelAction.appearance ?? 'filled'\"\n [label]=\"panelAction.label\"\n [icon]=\"panelAction.icon\"\n [attr.aria-label]=\"panelAction.label\"\n [rtConfirmTitle]=\"confirm.title\"\n [rtConfirmLabel]=\"confirm.label\"\n [rtConfirmTone]=\"confirm.tone\"\n [loading]=\"panelAction.loading ?? false\"\n [disabled]=\"(panelAction.disabled ?? false) || busy()\"\n [rtConfirm]=\"confirm.text\"\n [rtConfirmDisabled]=\"(panelAction.disabled ?? false) || busy()\"\n (confirmed)=\"onAction(panelAction)\"></button>\n } @else {\n <button\n rtButton\n rtElem=\"footer-action\"\n qa-dataid=\"workspace-details-action\"\n type=\"button\"\n [attr.data-id]=\"panelAction.id\"\n [theme]=\"panelAction.theme ?? 'primary'\"\n [appearance]=\"panelAction.appearance ?? 'filled'\"\n [label]=\"panelAction.label\"\n [icon]=\"panelAction.icon\"\n [attr.aria-label]=\"panelAction.label\"\n [loading]=\"panelAction.loading ?? false\"\n [disabled]=\"(panelAction.disabled ?? false) || busy()\"\n (click)=\"onAction(panelAction)\"></button>\n }\n }\n </footer>\n</ng-container>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-workspace-details.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/workspace-details/rt-workspace-details.component.ts","../../../projects/ui-kit-v2/src/lib/components/workspace-details/rt-workspace-details.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport { DecimalPipe, NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n output,\n OutputEmitterRef,\n signal,\n Signal,\n untracked,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\nimport { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';\n\nimport { BlockDirective, ElemDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { NotificationBus } from '@rt-tools/ui-kit-v2/core';\n\nimport { RtAsideSectionComponent } from '@rt-tools/ui-kit-v2/aside-section';\nimport { RtButtonDirective } from '@rt-tools/ui-kit-v2/button';\nimport { RtConfirmDirective } from '@rt-tools/ui-kit-v2/confirm-popover';\nimport { RtDetailListComponent } from '@rt-tools/ui-kit-v2/detail-list';\nimport { RtDetailRowComponent } from '@rt-tools/ui-kit-v2/detail-list';\nimport { RtEmptyStateComponent } from '@rt-tools/ui-kit-v2/empty-state';\nimport { RtFieldComponent } from '@rt-tools/ui-kit-v2/field';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtMoneyListComponent } from '@rt-tools/ui-kit-v2/money-list';\nimport { RtMoneyRowComponent } from '@rt-tools/ui-kit-v2/money-list';\nimport { RtNoteComponent } from '@rt-tools/ui-kit-v2/note';\nimport { RtSelectComponent } from '@rt-tools/ui-kit-v2/select';\nimport { RtSpinnerComponent } from '@rt-tools/ui-kit-v2/spinner';\nimport { RtTabDirective } from '@rt-tools/ui-kit-v2/tabs';\nimport { RtTabsComponent } from '@rt-tools/ui-kit-v2/tabs';\nimport { RtTextareaComponent } from '@rt-tools/ui-kit-v2/textarea';\nimport { RtTimelineComponent } from '@rt-tools/ui-kit-v2/timeline';\nimport { RtToggleSwitchComponent } from '@rt-tools/ui-kit-v2/toggle-switch';\nimport { IRtWorkspaceDetails } from './rt-workspace-details.model';\n\nconst BEM_BLOCK: string = 'rt-workspace-details';\n\ninterface ITransitionFormShape {\n to_key: FormControl<string | null>;\n note: FormControl<string | null>;\n}\n\n@Component({\n selector: 'rt-workspace-details',\n templateUrl: './rt-workspace-details.component.html',\n styleUrls: ['./rt-workspace-details.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n DecimalPipe,\n FormsModule,\n NgTemplateOutlet,\n ReactiveFormsModule,\n\n // standalone components / directives\n RtAsideSectionComponent,\n RtButtonDirective,\n RtConfirmDirective,\n RtDetailListComponent,\n RtDetailRowComponent,\n RtEmptyStateComponent,\n RtFieldComponent,\n RtIconButtonComponent,\n RtMoneyListComponent,\n RtMoneyRowComponent,\n RtNoteComponent,\n RtSelectComponent,\n RtSpinnerComponent,\n RtTabDirective,\n RtTabsComponent,\n RtTextareaComponent,\n RtTimelineComponent,\n RtToggleSwitchComponent,\n BlockDirective,\n ElemDirective,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtWorkspaceDetailsComponent {\n readonly #notificationBus: NotificationBus = inject(NotificationBus);\n\n readonly #lastEntityId: WritableSignal<number | null | undefined> = signal<number | null | undefined>(undefined);\n\n readonly #lastAgentId: WritableSignal<number | null | undefined> = signal<number | null | undefined>(undefined);\n\n #lastTransitionSuccess: string | null = null;\n\n #lastTransitionError: string | null = null;\n\n #lastTransitionSubmitError: string | null = null;\n\n #lastAuditError: string | null = null;\n\n #lastPanelError: string | null = null;\n\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly editingAgent: WritableSignal<boolean> = signal<boolean>(false);\n\n protected readonly selectedAgentId: WritableSignal<number | null> = signal<number | null>(null);\n\n protected readonly transitionForm: FormGroup<ITransitionFormShape> = new FormGroup<ITransitionFormShape>({\n to_key: new FormControl<string | null>(null, {\n validators: [Validators.required],\n }),\n note: new FormControl<string | null>(null),\n });\n\n protected readonly hasTabs: Signal<boolean> = computed((): boolean => this.transition() !== null || this.audit() !== null);\n\n protected readonly noTransitions: Signal<boolean> = computed((): boolean => {\n const transition: IRtWorkspaceDetails.Transition | null = this.transition();\n return transition !== null && !transition.loading && transition.error === null && transition.options.length === 0;\n });\n\n protected readonly canSaveReassign: Signal<boolean> = computed((): boolean => {\n const edit: IRtWorkspaceDetails.AgentEdit | null = this.agentEdit();\n const selected: number | null = this.selectedAgentId();\n return edit !== null && selected !== null && selected !== edit.currentAgentId;\n });\n\n public readonly title: InputSignal<string | null> = input<string | null>(null);\n\n public readonly entityId: InputSignal<number | null> = input<number | null>(null);\n\n public readonly loading: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly busy: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly rows: InputSignal<readonly IRtWorkspaceDetails.Row[]> = input<readonly IRtWorkspaceDetails.Row[]>([]);\n\n public readonly agentEdit: InputSignal<IRtWorkspaceDetails.AgentEdit | null> = input<IRtWorkspaceDetails.AgentEdit | null>(null);\n\n public readonly money: InputSignal<readonly IRtWorkspaceDetails.MoneyRow[]> = input<readonly IRtWorkspaceDetails.MoneyRow[]>([]);\n\n public readonly toggles: InputSignal<readonly IRtWorkspaceDetails.Toggle[]> = input<readonly IRtWorkspaceDetails.Toggle[]>([]);\n\n public readonly toggleHint: InputSignal<string | null> = input<string | null>(null);\n\n public readonly transition: InputSignal<IRtWorkspaceDetails.Transition | null> = input<IRtWorkspaceDetails.Transition | null>(null);\n\n public readonly audit: InputSignal<IRtWorkspaceDetails.Audit | null> = input<IRtWorkspaceDetails.Audit | null>(null);\n\n public readonly actions: InputSignal<readonly IRtWorkspaceDetails.Action[]> = input<readonly IRtWorkspaceDetails.Action[]>([]);\n\n public readonly error: InputSignal<string | null> = input<string | null>(null);\n\n public readonly toggleChange: OutputEmitterRef<IRtWorkspaceDetails.ToggleChange> = output<IRtWorkspaceDetails.ToggleChange>();\n\n public readonly agentReassign: OutputEmitterRef<number> = output<number>();\n\n public readonly transitionSubmit: OutputEmitterRef<IRtWorkspaceDetails.TransitionSubmit> =\n output<IRtWorkspaceDetails.TransitionSubmit>();\n\n public readonly transitionSuccessClose: OutputEmitterRef<void> = output<void>();\n\n public readonly transitionErrorClose: OutputEmitterRef<void> = output<void>();\n\n public readonly auditLoadMore: OutputEmitterRef<void> = output<void>();\n\n public readonly actionClicked: OutputEmitterRef<string> = output<string>();\n\n constructor() {\n effect((): void => {\n const id: number | null = this.entityId();\n if (id === untracked((): number | null | undefined => this.#lastEntityId())) {\n return;\n }\n this.#lastEntityId.set(id);\n this.editingAgent.set(false);\n this.selectedAgentId.set(untracked((): IRtWorkspaceDetails.AgentEdit | null => this.agentEdit())?.currentAgentId ?? null);\n this.transitionForm.reset();\n });\n\n effect((): void => {\n const currentAgentId: number | null = this.agentEdit()?.currentAgentId ?? null;\n if (currentAgentId === untracked((): number | null | undefined => this.#lastAgentId())) {\n return;\n }\n this.#lastAgentId.set(currentAgentId);\n this.editingAgent.set(false);\n this.selectedAgentId.set(currentAgentId);\n });\n\n effect((): void => {\n if (this.transition()?.success != null) {\n this.transitionForm.reset();\n }\n });\n\n effect((): void => {\n const successText: string | null = this.transition()?.success ?? null;\n if (successText !== null && successText !== this.#lastTransitionSuccess) {\n this.transitionSuccessClose.emit();\n }\n this.#lastTransitionSuccess = successText;\n });\n\n effect((): void => {\n const submitError: string | null = this.transition()?.submitError ?? null;\n if (submitError !== null && submitError !== this.#lastTransitionSubmitError) {\n this.#notificationBus.error(submitError);\n this.transitionErrorClose.emit();\n }\n this.#lastTransitionSubmitError = submitError;\n });\n\n effect((): void => {\n const transitionError: string | null = this.transition()?.error ?? null;\n if (transitionError !== null && transitionError !== this.#lastTransitionError) {\n this.#notificationBus.error(transitionError);\n }\n this.#lastTransitionError = transitionError;\n });\n\n effect((): void => {\n const auditError: string | null = this.audit()?.error ?? null;\n if (auditError !== null && auditError !== this.#lastAuditError) {\n this.#notificationBus.error(auditError);\n }\n this.#lastAuditError = auditError;\n });\n\n effect((): void => {\n const panelError: string | null = this.error();\n if (panelError !== null && panelError !== this.#lastPanelError) {\n this.#notificationBus.error(panelError);\n }\n this.#lastPanelError = panelError;\n });\n }\n\n protected startEditAgent(): void {\n const edit: IRtWorkspaceDetails.AgentEdit | null = this.agentEdit();\n if (edit === null || !edit.canEdit || this.busy()) {\n return;\n }\n this.selectedAgentId.set(edit.currentAgentId);\n this.editingAgent.set(true);\n }\n\n protected cancelEditAgent(): void {\n const edit: IRtWorkspaceDetails.AgentEdit | null = this.agentEdit();\n if (edit !== null && edit.loading) {\n return;\n }\n this.selectedAgentId.set(edit?.currentAgentId ?? null);\n this.editingAgent.set(false);\n }\n\n protected onReassign(): void {\n const agentId: number | null = this.selectedAgentId();\n if (agentId === null || !this.canSaveReassign() || this.busy()) {\n return;\n }\n this.agentReassign.emit(agentId);\n }\n\n protected onSelectedAgentChange(agentId: number | null): void {\n this.selectedAgentId.set(agentId);\n }\n\n protected onToggleChange(toggle: IRtWorkspaceDetails.Toggle, value: boolean): void {\n if (toggle.value === value) {\n return;\n }\n this.toggleChange.emit({ id: toggle.id, value });\n }\n\n protected onTransitionSubmit(): void {\n const transition: IRtWorkspaceDetails.Transition | null = this.transition();\n if (transition === null || transition.submitting) {\n return;\n }\n if (!this.transitionForm.valid) {\n this.transitionForm.markAllAsTouched();\n return;\n }\n\n const value: ReturnType<typeof this.transitionForm.getRawValue> = this.transitionForm.getRawValue();\n this.transitionSubmit.emit({\n stageKey: value.to_key ?? '',\n comment: value.note?.trim() ?? '',\n });\n }\n\n protected onAuditLoadMore(): void {\n this.auditLoadMore.emit();\n }\n\n protected onAction(action: IRtWorkspaceDetails.Action): void {\n if ((action.disabled ?? false) || this.busy()) {\n return;\n }\n this.actionClicked.emit(action.id);\n }\n}\n","<ng-container rtBlock=\"rt-workspace-details\">\n @if (title(); as headTitle) {\n <header rtElem=\"head\">\n <span rtElem=\"head-title\" qa-dataid=\"workspace-details-title\">{{ headTitle }}</span>\n </header>\n }\n\n @if (hasTabs()) {\n <rt-tabs rtElem=\"tabs\" qa-dataid=\"workspace-details-tabs\">\n <ng-template rtTab=\"details\" [label]=\"t().uiDetails\">\n <ng-container [ngTemplateOutlet]=\"detailsTpl\" />\n </ng-template>\n\n <ng-template rtTab=\"transition\" [label]=\"t().uiStageTransition\" [hidden]=\"transition() === null\">\n @if (transition(); as stageTransition) {\n @if (stageTransition.currentStageLabel; as stageLabel) {\n <rt-detail-list>\n <rt-detail-row qa-dataid=\"workspace-details-current-stage\" [label]=\"t().uiCurrentStage\">\n {{ stageLabel }}\n </rt-detail-row>\n </rt-detail-list>\n }\n\n @if (noTransitions()) {\n <rt-note qa-dataid=\"workspace-details-no-transitions\">{{ stageTransition.noTransitionsText }}</rt-note>\n } @else {\n <form\n rtElem=\"transition-form\"\n qa-dataid=\"workspace-details-transition-form\"\n [formGroup]=\"transitionForm\"\n (ngSubmit)=\"onTransitionSubmit()\">\n <rt-field\n [label]=\"t().uiTargetStage\"\n [loading]=\"stageTransition.loading\"\n [errors]=\"{ required: t().uiTargetStageRequired }\">\n <rt-select\n formControlName=\"to_key\"\n qa-dataid=\"workspace-details-transition-stage\"\n [placeholder]=\"t().uiPickTransition\"\n [options]=\"stageTransition.options\" />\n </rt-field>\n\n <rt-field [label]=\"t().uiCommentOptional\" [hint]=\"t().uiStageNoteHint\" [loading]=\"stageTransition.loading\">\n <rt-textarea formControlName=\"note\" qa-dataid=\"workspace-details-transition-note\" rows=\"3\" />\n </rt-field>\n\n <button\n rtButton\n rtElem=\"transition-submit\"\n qa-dataid=\"workspace-details-transition-submit\"\n type=\"submit\"\n [label]=\"t().uiMoveStage\"\n [attr.aria-label]=\"t().uiMoveStageAria\"\n [loading]=\"stageTransition.submitting\"\n [disabled]=\"stageTransition.loading || busy()\"></button>\n </form>\n }\n }\n </ng-template>\n\n <ng-template rtTab=\"audit\" [label]=\"t().uiHistory\" [hidden]=\"audit() === null\">\n @if (audit(); as auditFeed) {\n <div rtElem=\"audit\" qa-dataid=\"workspace-details-audit\">\n @if (auditFeed.loading) {\n <rt-spinner rtElem=\"audit-loading\" qa-dataid=\"workspace-details-audit-loading\" />\n } @else if (auditFeed.steps.length === 0) {\n <rt-empty-state\n qa-dataid=\"workspace-details-audit-empty\"\n icon=\"history\"\n [description]=\"t().uiAuditEmptyHint\"\n [title]=\"auditFeed.emptyText\" />\n } @else {\n <rt-timeline qa-dataid=\"workspace-details-audit-timeline\" [steps]=\"auditFeed.steps\" />\n }\n\n @if (auditFeed.hasMore) {\n <button\n rtButton\n rtElem=\"audit-more\"\n qa-dataid=\"workspace-details-audit-more\"\n type=\"button\"\n appearance=\"text\"\n [label]=\"t().uiLoadMore\"\n [attr.aria-label]=\"t().uiLoadMore\"\n [loading]=\"auditFeed.loadingMore\"\n [disabled]=\"auditFeed.loadingMore\"\n (click)=\"onAuditLoadMore()\"></button>\n }\n </div>\n }\n </ng-template>\n </rt-tabs>\n } @else {\n <div rtElem=\"body\">\n <ng-container [ngTemplateOutlet]=\"detailsTpl\" />\n </div>\n }\n\n <ng-template #detailsTpl>\n @if (rows().length > 0) {\n <rt-detail-list>\n @for (row of rows(); track row.label) {\n <rt-detail-row qa-dataid=\"workspace-details-row\" [label]=\"row.label\" [loading]=\"loading()\">\n @if (row.agent && agentEdit(); as edit) {\n @if (!editingAgent()) {\n <div rtElem=\"agent-view\">\n <span rtElem=\"agent-name\" qa-dataid=\"workspace-details-agent-name\">{{ edit.currentLabel }}</span>\n <rt-icon-button\n qa-dataid=\"workspace-details-agent-edit\"\n icon=\"pencil\"\n size=\"sm\"\n [ariaLabel]=\"t().uiChangeAgent\"\n [tooltip]=\"edit.canEdit ? edit.editTooltip : edit.cannotEditTooltip\"\n [disabled]=\"!edit.canEdit || busy()\"\n (clicked)=\"startEditAgent()\" />\n </div>\n } @else {\n <div rtElem=\"agent-edit\">\n <rt-select\n qa-dataid=\"workspace-details-agent-select\"\n [placeholder]=\"t().uiPickAgent\"\n [ngModel]=\"selectedAgentId()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"edit.options\"\n [clearable]=\"false\"\n (ngModelChange)=\"onSelectedAgentChange($event)\" />\n <rt-icon-button\n qa-dataid=\"workspace-details-agent-save\"\n icon=\"check\"\n size=\"sm\"\n rtConfirmTone=\"primary\"\n [ariaLabel]=\"t().uiSaveNewAgent\"\n [rtConfirmTitle]=\"t().uiReplaceAgentTitle\"\n [rtConfirmLabel]=\"t().uiReplace\"\n [tooltip]=\"canSaveReassign() ? t().uiSaveNewAgent : t().uiPickAnotherAgent\"\n [loading]=\"edit.loading\"\n [disabled]=\"!canSaveReassign() || busy()\"\n [rtConfirm]=\"edit.confirmText\"\n [rtConfirmDisabled]=\"!canSaveReassign() || busy()\"\n (confirmed)=\"onReassign()\" />\n <rt-icon-button\n qa-dataid=\"workspace-details-agent-cancel\"\n icon=\"ico-close\"\n size=\"sm\"\n [ariaLabel]=\"t().uiRevert\"\n [tooltip]=\"t().uiRevert\"\n [disabled]=\"edit.loading\"\n (clicked)=\"cancelEditAgent()\" />\n </div>\n }\n } @else {\n {{ row.value }}\n }\n </rt-detail-row>\n }\n </rt-detail-list>\n }\n\n @if (money().length > 0) {\n <rt-money-list>\n @for (moneyRow of money(); track moneyRow.label) {\n <rt-money-row\n qa-dataid=\"workspace-details-money-row\"\n [label]=\"moneyRow.label\"\n [total]=\"moneyRow.total ?? false\"\n [loading]=\"loading()\">\n {{ moneyRow.amount | number: moneyRow.format ?? '1.0-0' }} ₽\n </rt-money-row>\n }\n </rt-money-list>\n }\n\n @if (toggles().length > 0 || toggleHint()) {\n <rt-aside-section>\n @for (toggle of toggles(); track toggle.id) {\n <div rtElem=\"toggle-row\" qa-dataid=\"workspace-details-toggle-row\" [attr.data-id]=\"toggle.id\">\n <span rtElem=\"toggle-label\" qa-dataid=\"workspace-details-toggle-label\">{{ toggle.label }}</span>\n <rt-toggle-switch\n qa-dataid=\"workspace-details-toggle\"\n [inputId]=\"toggle.id\"\n [ariaLabel]=\"toggle.label\"\n [ngModel]=\"toggle.value\"\n [ngModelOptions]=\"{ standalone: true }\"\n [disabled]=\"(toggle.disabled ?? false) || busy()\"\n (ngModelChange)=\"onToggleChange(toggle, $event)\" />\n </div>\n }\n @if (toggleHint(); as hint) {\n <p rtElem=\"toggle-hint\" qa-dataid=\"workspace-details-toggle-hint\">{{ hint }}</p>\n }\n </rt-aside-section>\n }\n </ng-template>\n\n <footer rtElem=\"footer\">\n @for (panelAction of actions(); track panelAction.id) {\n @if (panelAction.confirm; as confirm) {\n <button\n rtButton\n rtElem=\"footer-action\"\n qa-dataid=\"workspace-details-action\"\n type=\"button\"\n [attr.data-id]=\"panelAction.id\"\n [theme]=\"panelAction.theme ?? 'primary'\"\n [appearance]=\"panelAction.appearance ?? 'filled'\"\n [label]=\"panelAction.label\"\n [icon]=\"panelAction.icon\"\n [attr.aria-label]=\"panelAction.label\"\n [rtConfirmTitle]=\"confirm.title\"\n [rtConfirmLabel]=\"confirm.label\"\n [rtConfirmTone]=\"confirm.tone\"\n [loading]=\"panelAction.loading ?? false\"\n [disabled]=\"(panelAction.disabled ?? false) || busy()\"\n [rtConfirm]=\"confirm.text\"\n [rtConfirmDisabled]=\"(panelAction.disabled ?? false) || busy()\"\n (confirmed)=\"onAction(panelAction)\"></button>\n } @else {\n <button\n rtButton\n rtElem=\"footer-action\"\n qa-dataid=\"workspace-details-action\"\n type=\"button\"\n [attr.data-id]=\"panelAction.id\"\n [theme]=\"panelAction.theme ?? 'primary'\"\n [appearance]=\"panelAction.appearance ?? 'filled'\"\n [label]=\"panelAction.label\"\n [icon]=\"panelAction.icon\"\n [attr.aria-label]=\"panelAction.label\"\n [loading]=\"panelAction.loading ?? false\"\n [disabled]=\"(panelAction.disabled ?? false) || busy()\"\n (click)=\"onAction(panelAction)\"></button>\n }\n }\n </footer>\n</ng-container>\n"],"mappings":"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"}
|
|
@@ -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":"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"}
|
package/package.json
CHANGED
|
@@ -4,26 +4,33 @@
|
|
|
4
4
|
<rt-icon-button icon="ico-trash" ariaLabel="Удалить" variant="danger" size="md" (clicked)="remove()" />
|
|
5
5
|
```
|
|
6
6
|
|
|
7
|
-
| вход | тип
|
|
8
|
-
| ----------------------------------------------- |
|
|
9
|
-
| `icon` | `IRtIcon.Name \| null` — нужен он или `glyph`; без обоих показывает вложенное
|
|
10
|
-
| `glyph` | `string \| null` — имя Material, как `glyph` у `rt-icon`
|
|
11
|
-
| `ariaLabel` | `string`
|
|
12
|
-
| `variant` | `'primary' \| 'secondary' \| 'ghost' \| 'danger' \| 'success' \| 'warning'`
|
|
13
|
-
| `size` | `'2xs' \| 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl'`
|
|
14
|
-
| `iconSize` | `IRtIcon.Size \| null`
|
|
15
|
-
| `iconColor` | `IRtIcon.Color`
|
|
16
|
-
| `radius` | `TRtRadius \| null` — шаг общей шкалы
|
|
17
|
-
| `type` | `'button' \| 'submit'`
|
|
18
|
-
| `tooltip` | `string`
|
|
19
|
-
| `tooltipHideOnClick` | `boolean` — `false` у переключателя: подсказка остаётся после клика
|
|
20
|
-
| `tabIndex` | `number`
|
|
21
|
-
| `
|
|
7
|
+
| вход | тип | умолчание |
|
|
8
|
+
| ----------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------------------- |
|
|
9
|
+
| `icon` | `IRtIcon.Name \| null` — нужен он или `glyph`; без обоих показывает вложенное | `null` |
|
|
10
|
+
| `glyph` | `string \| null` — имя Material, как `glyph` у `rt-icon` | `null` |
|
|
11
|
+
| `ariaLabel` | `string` | **обязателен** |
|
|
12
|
+
| `variant` | `'primary' \| 'secondary' \| 'ghost' \| 'danger' \| 'success' \| 'warning'` | `'ghost'` |
|
|
13
|
+
| `size` | `'2xs' \| 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl'` | `'md'` |
|
|
14
|
+
| `iconSize` | `IRtIcon.Size \| null` | `null` → от размера кнопки |
|
|
15
|
+
| `iconColor` | `IRtIcon.Color` | `'current'` |
|
|
16
|
+
| `radius` | `TRtRadius \| null` — шаг общей шкалы | `null` → `md` |
|
|
17
|
+
| `type` | `'button' \| 'submit'` | `'button'` |
|
|
18
|
+
| `tooltip` | `string` | `''` (пусто → подсказки нет) |
|
|
19
|
+
| `tooltipHideOnClick` | `boolean` — `false` у переключателя: подсказка остаётся после клика | из `provideRtKit`, без него `true` |
|
|
20
|
+
| `tabIndex` | `number` | `0` |
|
|
21
|
+
| `link` | `RouterLink['routerLink']` — маршрут: компонент рисует ссылку `<a>` | `null` → кнопка |
|
|
22
|
+
| `expanded` | `boolean \| null` → `aria-expanded` | `null` (атрибута нет) |
|
|
23
|
+
| `ariaHaspopup` | `'menu' \| 'listbox' \| 'tree' \| 'grid' \| 'dialog' \| null` → `aria-haspopup` | `null` (атрибута нет) |
|
|
24
|
+
| `loading` / `disabled` / `active` / `indicator` | `boolean` | `false` |
|
|
22
25
|
|
|
23
26
|
| выход | тип |
|
|
24
27
|
| --------- | ------------ |
|
|
25
28
|
| `clicked` | `MouseEvent` |
|
|
26
29
|
|
|
30
|
+
| метод | что делает |
|
|
31
|
+
| ----------------- | ----------------------------------- |
|
|
32
|
+
| `focus(options?)` | фокусирует кнопку или ссылку внутри |
|
|
33
|
+
|
|
27
34
|
## Главное, что нужно знать
|
|
28
35
|
|
|
29
36
|
**`ariaLabel` обязателен.** У кнопки нет текста, и без подписи она для скринридера безымянна.
|
|
@@ -48,7 +55,16 @@
|
|
|
48
55
|
- `loading` = `disabled` плюс кольцо вместо иконки. Клик в этом состоянии наружу не уходит.
|
|
49
56
|
- `active` превращается в `aria-pressed="true"` — для кнопок-переключателей.
|
|
50
57
|
- `expanded` пишет `aria-expanded` кнопке, которая открывает панель, — так делает `rt-speed-menu`.
|
|
51
|
-
Без входа атрибута нет вовсе.
|
|
58
|
+
Без входа атрибута нет вовсе. `ariaHaspopup` называет вид панели: `'menu'` у кнопки «Ещё».
|
|
59
|
+
- `link` превращает кнопку в ссылку `<a href>` с тем же видом, рябью и подсказкой: браузер
|
|
60
|
+
открывает её в новой вкладке из контекстного меню, а скринридер называет ссылкой. `clicked`
|
|
61
|
+
приходит и от ссылки. Недоступная или загружающаяся ссылка теряет адрес, получает
|
|
62
|
+
`aria-disabled` и никуда не ведёт. `type` и `active` у ссылки не действуют. Нужен
|
|
63
|
+
`provideRouter` в приложении. Кнопка у ссылки остаётся в разметке пустой и спрятанной: в шаблоне
|
|
64
|
+
она без условия, чтобы появляться с первым проходом — родитель, который меряет соседей на первой
|
|
65
|
+
проверке (автовысота поля), иначе считал бы ряд без неё.
|
|
66
|
+
- `focus()` возвращает фокус на кнопку из кода — например, когда закрылось меню, которое она
|
|
67
|
+
открыла. Искать `button` внутри компонента не нужно.
|
|
52
68
|
- `tabIndex="-1"` оставляет клик мышью, но убирает кнопку из таб-порядка: так сделаны
|
|
53
69
|
вспомогательные крестики внутри полей.
|
|
54
70
|
- `iconSize` нужен, когда крупная кнопка должна остаться крупной (в неё целятся пальцем), а
|