@rt-tools/ui-kit-v2 0.34.3 → 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-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/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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-input.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/input/rt-input.component.ts","../../../projects/ui-kit-v2/src/lib/components/input/rt-input.component.html"],"sourcesContent":["import { BooleanInput, NumberInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n computed,\n forwardRef,\n inject,\n input,\n output,\n signal,\n viewChild,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { rtMaxlength, rtNotchWidth, RtFormControlBase } from '@rt-tools/ui-kit-v2/form-control';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { IRtInput } from '@rt-tools/ui-kit-v2/core';\n\nconst BEM_BLOCK: string = 'rt-input';\n\nlet floatingLabelSeed: number = 0;\n\nfunction nextFloatingLabelId(): string {\n floatingLabelSeed += 1;\n return `rt-input-label-${floatingLabelSeed}`;\n}\n\n/**\n * Шеренный input common/ui. Поддерживает:\n * - интеграцию с Reactive Forms через общий `RtFormControlBase` (CVA-ядро,\n * авто-подсветка invalid, `clearable`);\n * - левую и правую иконочные «слоты» (`iconLeft`, `iconRight`); по `iconLeftAction` /\n * `iconRightAction` иконка становится кнопкой с подсказкой и своим выходом;\n * - подпись на рамке (`floatingLabel`): у пустого поля в покое лежит на месте подсказки, при\n * значении или фокусе поднимается на верхнюю рамку, высоту поля не меняет;\n * - встроенный password-toggle (`passwordToggle=true` + `type=\"password\"`);\n * - кнопку очистки (крестик) при наличии значения; на password-полях крестик\n * не показывается (postfix занят toggle'ом).\n *\n * Все размеры/цвета — через `--rt-input-*` semantic-токены.\n */\n@Component({\n selector: 'rt-input',\n templateUrl: './rt-input.component.html',\n styleUrls: ['./rt-input.component.scss', './rt-input-floating-label.scss', './rt-input-icons.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtIconButtonComponent,\n RtIconComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n providers: [\n // Алиас базового токена — чтобы rt-field мог найти контрол через\n // contentChild(RtFormControlBase) (query по абстрактному классу).\n { provide: RtFormControlBase, useExisting: forwardRef(() => RtInputComponent) },\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n '[class.rt-input--disabled]': 'isDisabled()',\n '[class.rt-input--invalid]': 'isInvalid()',\n '[class.rt-input--readonly]': 'isReadonly()',\n '[class.rt-input--borderless]': '!bordered()',\n '[class.rt-input--appearance--fill]': \"appearance() === 'fill'\",\n '[class.rt-input--appearance--pill]': \"appearance() === 'pill'\",\n '[class.rt-input--size--sm]': \"size() === 'sm'\",\n '[class.rt-input--size--lg]': \"size() === 'lg'\",\n '[class.rt-input--with-icon-left]': '!!iconLeft()',\n '[class.rt-input--with-icon-right]': 'hasIconRight()',\n '[class.rt-input--floating]': '!!floatingLabel()',\n '[class.rt-input--clearable]': 'clearable()',\n '[style.--rt-input-notch-width]': \"notchWidth() + 'px'\",\n '[class.rt-input--filled]': 'hasValue()',\n '(mousedown)': 'onHostMousedown($event)',\n },\n})\nexport class RtInputComponent extends RtFormControlBase<string> {\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly fieldEl: Signal<ElementRef<HTMLInputElement> | undefined> = viewChild<ElementRef<HTMLInputElement>>('fieldEl');\n\n /** Подпись на рамке: по её ширине материальный набор вырезает разрыв в рамке. `#`-поле `viewChild` не принимает. */\n protected readonly floatingLabelEl: Signal<ElementRef<HTMLElement> | undefined> = viewChild<ElementRef<HTMLElement>>('floatingLabelEl');\n\n /** Ширина подписи на рамке, px. */\n protected readonly notchWidth: Signal<number> = rtNotchWidth(this.floatingLabelEl);\n\n protected readonly isPasswordVisible: WritableSignal<boolean> = signal<boolean>(false);\n\n protected readonly hasValue: Signal<boolean> = computed((): boolean => this.value() !== '');\n\n /** Id подписи на рамке: на него ссылается `aria-labelledby` поля. */\n protected readonly floatingLabelId: string = nextFloatingLabelId();\n\n /** Подпись на рамке называет поле, только когда явного `ariaLabel` нет. */\n protected readonly labelledBy: Signal<string | null> = computed((): string | null =>\n this.floatingLabel() && !this.ariaLabel() ? this.floatingLabelId : null\n );\n\n protected readonly effectiveType: Signal<string> = computed((): string => {\n const t: IRtInput.Type = this.type();\n if (t === 'password' && this.passwordToggle() && this.isPasswordVisible()) {\n return 'text';\n }\n return t;\n });\n\n protected readonly showPasswordToggle: Signal<boolean> = computed((): boolean => this.passwordToggle() && this.type() === 'password');\n\n protected readonly hasIconRight: Signal<boolean> = computed((): boolean => !!this.iconRight() || this.showPasswordToggle());\n\n /** Иконка-кнопка отключена вместе с полем или своим входом. */\n protected readonly isIconLeftDisabled: Signal<boolean> = computed((): boolean => this.isDisabled() || this.iconLeftDisabled());\n protected readonly isIconRightDisabled: Signal<boolean> = computed((): boolean => this.isDisabled() || this.iconRightDisabled());\n\n protected readonly passwordToggleIcon: Signal<IRtIcon.Name> = computed((): IRtIcon.Name =>\n this.isPasswordVisible() ? 'ico-eyeClose' : 'ico-eye'\n );\n\n /** Вид рамки: `outline` — рамка со всех сторон, `fill` — залитое поле с чертой снизу. */\n public override readonly fieldLabelInside: boolean = true;\n public readonly appearance: InputSignal<IRtInput.Appearance> = input<IRtInput.Appearance>('outline');\n\n public readonly displayText: Signal<string> = computed((): string => this.value());\n\n public readonly type: InputSignal<IRtInput.Type> = input<IRtInput.Type>('text');\n public readonly placeholder: InputSignal<string> = input<string>('');\n public readonly iconLeft: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n public readonly iconRight: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n public readonly passwordToggle: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n public readonly autocomplete: InputSignal<string | null> = input<string | null>(null);\n\n /**\n * Предел длины значения: уходит атрибутом `maxlength` на поле, и браузер не даёт набрать лишний\n * знак. `null` — предела нет. Проверку формы вход не заменяет: значение, записанное кодом,\n * браузер не режет.\n */\n public readonly maxlength: InputSignalWithTransform<number | null, NumberInput> = input<number | null, NumberInput>(null, {\n transform: rtMaxlength,\n });\n\n /** Видимая подпись на рамке поля. `null` — подписи нет, поле как прежде. */\n public readonly floatingLabel: InputSignal<string | null> = input<string | null>(null);\n\n /** Левая иконка — кнопка: Tab, Enter, Space, нажатие уходит в `iconLeftClick`. */\n public readonly iconLeftAction: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Правая иконка — кнопка, нажатие уходит в `iconRightClick`. На поле пароля с переключателем\n * показа не действует: место занято переключателем.\n */\n public readonly iconRightAction: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Левая иконка-кнопка отключена, хотя поле доступно: например, поиск, который не ищет, пока\n * введено меньше трёх знаков. Подсказка у отключённой кнопки остаётся и объясняет почему.\n */\n public readonly iconLeftDisabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Правая иконка-кнопка отключена, хотя поле доступно. */\n public readonly iconRightDisabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Подсказка левой иконки-кнопки; она же её доступное имя. Без неё имя — имя иконки. */\n public readonly iconLeftTooltip: InputSignal<string | null> = input<string | null>(null);\n\n /** Подсказка правой иконки-кнопки; она же её доступное имя. */\n public readonly iconRightTooltip: InputSignal<string | null> = input<string | null>(null);\n\n /** Нажатие левой иконки-кнопки — мышью или клавишей (браузер шлёт click и на Enter/Space). */\n public readonly iconLeftClick: OutputEmitterRef<MouseEvent> = output<MouseEvent>();\n\n /** Нажатие правой иконки-кнопки. */\n public readonly iconRightClick: OutputEmitterRef<MouseEvent> = output<MouseEvent>();\n\n /**\n * Форма может вернуть полю прежнее значение в том же стеке, что и ввод: сигнал тогда равен\n * последнему отрисованному, привязка `[value]` не срабатывает, и поле остаётся с набранным.\n * Поэтому расхождение с полем пишется в него сразу.\n */\n public override writeValue(value: string | null): void {\n super.writeValue(value);\n const field: HTMLInputElement | undefined = this.fieldEl()?.nativeElement;\n if (field && field.value !== this.value()) {\n field.value = this.value();\n }\n }\n\n protected getEmptyValue(): string {\n return '';\n }\n\n protected focusAfterClear(): void {\n this.fieldEl()?.nativeElement.focus();\n }\n\n /**\n * Падинг/гэп рамки принадлежат host-контейнеру, а не `<input>`, поэтому клик\n * по этой зоне сам по себе не фокусирует поле. Перехватываем mousedown и\n * переводим фокус в input — но только если клик не пришёлся на само поле\n * (там нужно нативное позиционирование курсора) и не на интерактивный\n * постфикс (крестик/таггл со своими обработчиками).\n */\n protected onHostMousedown(event: MouseEvent): void {\n if (this.isDisabled()) {\n return;\n }\n const field: HTMLInputElement | undefined = this.fieldEl()?.nativeElement;\n const target: HTMLElement = event.target as HTMLElement;\n if (!field || target === field || target.closest('button, rt-icon-button')) {\n return;\n }\n event.preventDefault();\n field.focus();\n }\n\n protected onInput(event: Event): void {\n const target: HTMLInputElement = event.target as HTMLInputElement;\n const next: string = target.value;\n this.value.set(next);\n this.emitChange(next);\n }\n\n protected onBlur(): void {\n this.markTouched();\n }\n\n protected togglePassword(): void {\n this.isPasswordVisible.update((v: boolean): boolean => !v);\n }\n}\n","<ng-container rtBlock=\"rt-input\">\n @if (isReadonly()) {\n <span rtElem=\"readonly\" qa-dataid=\"input-readonly\" [rtMod]=\"{ empty: !displayText() }\">{{ displayText() || '—' }}</span>\n } @else {\n @if (iconLeft(); as left) {\n @if (iconLeftAction()) {\n <rt-icon-button\n rtElem=\"icon-left\"\n qa-dataid=\"input-icon-left-action\"\n size=\"sm\"\n variant=\"ghost\"\n iconColor=\"muted\"\n [icon]=\"left\"\n [ariaLabel]=\"iconLeftTooltip() || left\"\n [tooltip]=\"iconLeftTooltip() ?? ''\"\n [disabled]=\"isIconLeftDisabled()\"\n (clicked)=\"iconLeftClick.emit($event)\" />\n } @else {\n <rt-icon rtElem=\"icon-left\" size=\"sm\" color=\"muted\" [name]=\"left\" />\n }\n }\n @if (floatingLabel(); as label) {\n <!-- Подпись — картинка поверх поля: клик проходит сквозь неё в поле, имя полю она даёт по aria-labelledby. -->\n <span #floatingLabelEl rtElem=\"floating-label\" qa-dataid=\"input-floating-label\" aria-hidden=\"true\" [id]=\"floatingLabelId\">\n {{ label }}\n </span>\n }\n <input\n #fieldEl\n rtElem=\"field\"\n qa-dataid=\"input-control\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [value]=\"value()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.maxlength]=\"maxlength()\"\n [attr.id]=\"effectiveControlId()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-invalid]=\"isInvalid() || null\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\" />\n @if (showClearButton() && !showPasswordToggle()) {\n <rt-icon-button\n rtElem=\"clear\"\n qa-dataid=\"input-clear\"\n icon=\"ico-close\"\n size=\"sm\"\n variant=\"ghost\"\n iconColor=\"muted\"\n [ariaLabel]=\"t().uiClear\"\n [tabIndex]=\"clearTabIndex()\"\n (clicked)=\"clear($event)\" />\n }\n @if (showPasswordToggle()) {\n <button\n rtElem=\"toggle\"\n qa-dataid=\"input-password-toggle\"\n type=\"button\"\n [attr.aria-label]=\"isPasswordVisible() ? t().uiHidePassword : t().uiShowPassword\"\n [tabIndex]=\"-1\"\n (click)=\"togglePassword()\">\n <rt-icon size=\"sm\" color=\"muted\" [name]=\"passwordToggleIcon()\" />\n </button>\n } @else if (iconRight(); as right) {\n @if (iconRightAction()) {\n <rt-icon-button\n rtElem=\"icon-right\"\n qa-dataid=\"input-icon-right-action\"\n size=\"sm\"\n variant=\"ghost\"\n iconColor=\"muted\"\n [icon]=\"right\"\n [ariaLabel]=\"iconRightTooltip() || right\"\n [tooltip]=\"iconRightTooltip() ?? ''\"\n [disabled]=\"isIconRightDisabled()\"\n (clicked)=\"iconRightClick.emit($event)\" />\n } @else {\n <rt-icon rtElem=\"icon-right\" size=\"sm\" color=\"muted\" [name]=\"right\" />\n }\n }\n }\n</ng-container>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-input.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/input/rt-input.component.ts","../../../projects/ui-kit-v2/src/lib/components/input/rt-input.component.html"],"sourcesContent":["import { BooleanInput, NumberInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n computed,\n forwardRef,\n inject,\n input,\n output,\n signal,\n viewChild,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { rtMaxlength, rtNotchWidth, RtFormControlBase } from '@rt-tools/ui-kit-v2/form-control';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { IRtInput } from '@rt-tools/ui-kit-v2/core';\n\nconst BEM_BLOCK: string = 'rt-input';\n\nlet floatingLabelSeed: number = 0;\n\nfunction nextFloatingLabelId(): string {\n floatingLabelSeed += 1;\n return `rt-input-label-${floatingLabelSeed}`;\n}\n\n/**\n * Шеренный input common/ui. Поддерживает:\n * - интеграцию с Reactive Forms через общий `RtFormControlBase` (CVA-ядро,\n * авто-подсветка invalid, `clearable`);\n * - левую и правую иконочные «слоты» (`iconLeft`, `iconRight`); по `iconLeftAction` /\n * `iconRightAction` иконка становится кнопкой с подсказкой и своим выходом;\n * - подпись на рамке (`floatingLabel`): у пустого поля в покое лежит на месте подсказки, при\n * значении или фокусе поднимается на верхнюю рамку, высоту поля не меняет;\n * - встроенный password-toggle (`passwordToggle=true` + `type=\"password\"`);\n * - кнопку очистки (крестик) при наличии значения; на password-полях крестик\n * не показывается (postfix занят toggle'ом).\n *\n * Все размеры/цвета — через `--rt-input-*` semantic-токены.\n */\n@Component({\n selector: 'rt-input',\n templateUrl: './rt-input.component.html',\n styleUrls: ['./rt-input.component.scss', './rt-input-floating-label.scss', './rt-input-icons.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtIconButtonComponent,\n RtIconComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n providers: [\n // Алиас базового токена — чтобы rt-field мог найти контрол через\n // contentChild(RtFormControlBase) (query по абстрактному классу).\n { provide: RtFormControlBase, useExisting: forwardRef(() => RtInputComponent) },\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n '[class.rt-input--disabled]': 'isDisabled()',\n '[class.rt-input--invalid]': 'isInvalid()',\n '[class.rt-input--readonly]': 'isReadonly()',\n '[class.rt-input--borderless]': '!bordered()',\n '[class.rt-input--appearance--fill]': \"appearance() === 'fill'\",\n '[class.rt-input--appearance--pill]': \"appearance() === 'pill'\",\n '[class.rt-input--size--sm]': \"size() === 'sm'\",\n '[class.rt-input--size--lg]': \"size() === 'lg'\",\n '[class.rt-input--with-icon-left]': '!!iconLeft()',\n '[class.rt-input--with-icon-right]': 'hasIconRight()',\n '[class.rt-input--floating]': '!!floatingLabel()',\n '[class.rt-input--clearable]': 'clearable()',\n '[style.--rt-input-notch-width]': \"notchWidth() + 'px'\",\n '[class.rt-input--filled]': 'hasValue()',\n '(mousedown)': 'onHostMousedown($event)',\n },\n})\nexport class RtInputComponent extends RtFormControlBase<string> {\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly fieldEl: Signal<ElementRef<HTMLInputElement> | undefined> = viewChild<ElementRef<HTMLInputElement>>('fieldEl');\n\n /** Подпись на рамке: по её ширине материальный набор вырезает разрыв в рамке. `#`-поле `viewChild` не принимает. */\n protected readonly floatingLabelEl: Signal<ElementRef<HTMLElement> | undefined> = viewChild<ElementRef<HTMLElement>>('floatingLabelEl');\n\n /** Ширина подписи на рамке, px. */\n protected readonly notchWidth: Signal<number> = rtNotchWidth(this.floatingLabelEl);\n\n protected readonly isPasswordVisible: WritableSignal<boolean> = signal<boolean>(false);\n\n protected readonly hasValue: Signal<boolean> = computed((): boolean => this.value() !== '');\n\n /** Id подписи на рамке: на него ссылается `aria-labelledby` поля. */\n protected readonly floatingLabelId: string = nextFloatingLabelId();\n\n /** Подпись на рамке называет поле, только когда явного `ariaLabel` нет. */\n protected readonly labelledBy: Signal<string | null> = computed((): string | null =>\n this.floatingLabel() && !this.ariaLabel() ? this.floatingLabelId : null\n );\n\n protected readonly effectiveType: Signal<string> = computed((): string => {\n const t: IRtInput.Type = this.type();\n if (t === 'password' && this.passwordToggle() && this.isPasswordVisible()) {\n return 'text';\n }\n return t;\n });\n\n protected readonly showPasswordToggle: Signal<boolean> = computed((): boolean => this.passwordToggle() && this.type() === 'password');\n\n protected readonly hasIconRight: Signal<boolean> = computed((): boolean => !!this.iconRight() || this.showPasswordToggle());\n\n /** Иконка-кнопка отключена вместе с полем или своим входом. */\n protected readonly isIconLeftDisabled: Signal<boolean> = computed((): boolean => this.isDisabled() || this.iconLeftDisabled());\n protected readonly isIconRightDisabled: Signal<boolean> = computed((): boolean => this.isDisabled() || this.iconRightDisabled());\n\n protected readonly passwordToggleIcon: Signal<IRtIcon.Name> = computed((): IRtIcon.Name =>\n this.isPasswordVisible() ? 'ico-eyeClose' : 'ico-eye'\n );\n\n /** Вид рамки: `outline` — рамка со всех сторон, `fill` — залитое поле с чертой снизу. */\n public override readonly fieldLabelInside: boolean = true;\n public readonly appearance: InputSignal<IRtInput.Appearance> = input<IRtInput.Appearance>('outline');\n\n public readonly displayText: Signal<string> = computed((): string => this.value());\n\n public readonly type: InputSignal<IRtInput.Type> = input<IRtInput.Type>('text');\n public readonly placeholder: InputSignal<string> = input<string>('');\n public readonly iconLeft: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n public readonly iconRight: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n public readonly passwordToggle: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n public readonly autocomplete: InputSignal<string | null> = input<string | null>(null);\n\n /**\n * Предел длины значения: уходит атрибутом `maxlength` на поле, и браузер не даёт набрать лишний\n * знак. `null` — предела нет. Проверку формы вход не заменяет: значение, записанное кодом,\n * браузер не режет.\n */\n public readonly maxlength: InputSignalWithTransform<number | null, NumberInput> = input<number | null, NumberInput>(null, {\n transform: rtMaxlength,\n });\n\n /** Видимая подпись на рамке поля. `null` — подписи нет, поле как прежде. */\n public readonly floatingLabel: InputSignal<string | null> = input<string | null>(null);\n\n /** Левая иконка — кнопка: Tab, Enter, Space, нажатие уходит в `iconLeftClick`. */\n public readonly iconLeftAction: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Правая иконка — кнопка, нажатие уходит в `iconRightClick`. На поле пароля с переключателем\n * показа не действует: место занято переключателем.\n */\n public readonly iconRightAction: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Левая иконка-кнопка отключена, хотя поле доступно: например, поиск, который не ищет, пока\n * введено меньше трёх знаков. Подсказка у отключённой кнопки остаётся и объясняет почему.\n */\n public readonly iconLeftDisabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Правая иконка-кнопка отключена, хотя поле доступно. */\n public readonly iconRightDisabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Подсказка левой иконки-кнопки; она же её доступное имя. Без неё имя — имя иконки. */\n public readonly iconLeftTooltip: InputSignal<string | null> = input<string | null>(null);\n\n /** Подсказка правой иконки-кнопки; она же её доступное имя. */\n public readonly iconRightTooltip: InputSignal<string | null> = input<string | null>(null);\n\n /** Нажатие левой иконки-кнопки — мышью или клавишей (браузер шлёт click и на Enter/Space). */\n public readonly iconLeftClick: OutputEmitterRef<MouseEvent> = output<MouseEvent>();\n\n /** Нажатие правой иконки-кнопки. */\n public readonly iconRightClick: OutputEmitterRef<MouseEvent> = output<MouseEvent>();\n\n /**\n * Форма может вернуть полю прежнее значение в том же стеке, что и ввод: сигнал тогда равен\n * последнему отрисованному, привязка `[value]` не срабатывает, и поле остаётся с набранным.\n * Поэтому расхождение с полем пишется в него сразу.\n */\n public override writeValue(value: string | null): void {\n super.writeValue(value);\n const field: HTMLInputElement | undefined = this.fieldEl()?.nativeElement;\n if (field && field.value !== this.value()) {\n field.value = this.value();\n }\n }\n\n /** Фокусирует поле ввода внутри — например, поиск, когда открылась его панель. */\n public focus(options?: FocusOptions): void {\n this.fieldEl()?.nativeElement.focus(options);\n }\n\n protected getEmptyValue(): string {\n return '';\n }\n\n protected focusAfterClear(): void {\n this.focus();\n }\n\n /**\n * Падинг/гэп рамки принадлежат host-контейнеру, а не `<input>`, поэтому клик\n * по этой зоне сам по себе не фокусирует поле. Перехватываем mousedown и\n * переводим фокус в input — но только если клик не пришёлся на само поле\n * (там нужно нативное позиционирование курсора) и не на интерактивный\n * постфикс (крестик/таггл со своими обработчиками).\n */\n protected onHostMousedown(event: MouseEvent): void {\n if (this.isDisabled()) {\n return;\n }\n const field: HTMLInputElement | undefined = this.fieldEl()?.nativeElement;\n const target: HTMLElement = event.target as HTMLElement;\n if (!field || target === field || target.closest('button, rt-icon-button')) {\n return;\n }\n event.preventDefault();\n field.focus();\n }\n\n protected onInput(event: Event): void {\n const target: HTMLInputElement = event.target as HTMLInputElement;\n const next: string = target.value;\n this.value.set(next);\n this.emitChange(next);\n }\n\n protected onBlur(): void {\n this.markTouched();\n }\n\n protected togglePassword(): void {\n this.isPasswordVisible.update((v: boolean): boolean => !v);\n }\n}\n","<ng-container rtBlock=\"rt-input\">\n @if (isReadonly()) {\n <span rtElem=\"readonly\" qa-dataid=\"input-readonly\" [rtMod]=\"{ empty: !displayText() }\">{{ displayText() || '—' }}</span>\n } @else {\n @if (iconLeft(); as left) {\n @if (iconLeftAction()) {\n <rt-icon-button\n rtElem=\"icon-left\"\n qa-dataid=\"input-icon-left-action\"\n size=\"sm\"\n variant=\"ghost\"\n iconColor=\"muted\"\n [icon]=\"left\"\n [ariaLabel]=\"iconLeftTooltip() || left\"\n [tooltip]=\"iconLeftTooltip() ?? ''\"\n [disabled]=\"isIconLeftDisabled()\"\n (clicked)=\"iconLeftClick.emit($event)\" />\n } @else {\n <rt-icon rtElem=\"icon-left\" size=\"sm\" color=\"muted\" [name]=\"left\" />\n }\n }\n @if (floatingLabel(); as label) {\n <!-- Подпись — картинка поверх поля: клик проходит сквозь неё в поле, имя полю она даёт по aria-labelledby. -->\n <span #floatingLabelEl rtElem=\"floating-label\" qa-dataid=\"input-floating-label\" aria-hidden=\"true\" [id]=\"floatingLabelId\">\n {{ label }}\n </span>\n }\n <input\n #fieldEl\n rtElem=\"field\"\n qa-dataid=\"input-control\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [value]=\"value()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.maxlength]=\"maxlength()\"\n [attr.id]=\"effectiveControlId()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-invalid]=\"isInvalid() || null\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\" />\n @if (showClearButton() && !showPasswordToggle()) {\n <rt-icon-button\n rtElem=\"clear\"\n qa-dataid=\"input-clear\"\n icon=\"ico-close\"\n size=\"sm\"\n variant=\"ghost\"\n iconColor=\"muted\"\n [ariaLabel]=\"t().uiClear\"\n [tabIndex]=\"clearTabIndex()\"\n (clicked)=\"clear($event)\" />\n }\n @if (showPasswordToggle()) {\n <button\n rtElem=\"toggle\"\n qa-dataid=\"input-password-toggle\"\n type=\"button\"\n [attr.aria-label]=\"isPasswordVisible() ? t().uiHidePassword : t().uiShowPassword\"\n [tabIndex]=\"-1\"\n (click)=\"togglePassword()\">\n <rt-icon size=\"sm\" color=\"muted\" [name]=\"passwordToggleIcon()\" />\n </button>\n } @else if (iconRight(); as right) {\n @if (iconRightAction()) {\n <rt-icon-button\n rtElem=\"icon-right\"\n qa-dataid=\"input-icon-right-action\"\n size=\"sm\"\n variant=\"ghost\"\n iconColor=\"muted\"\n [icon]=\"right\"\n [ariaLabel]=\"iconRightTooltip() || right\"\n [tooltip]=\"iconRightTooltip() ?? ''\"\n [disabled]=\"isIconRightDisabled()\"\n (clicked)=\"iconRightClick.emit($event)\" />\n } @else {\n <rt-icon rtElem=\"icon-right\" size=\"sm\" color=\"muted\" [name]=\"right\" />\n }\n }\n }\n</ng-container>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-menu.mjs","names":["BEM_BLOCK","BEM_BLOCK","i1"],"sources":["../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-item-icon.directive.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-confirm-dialog.component.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-confirm-dialog.component.html","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-item.logic.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu.model.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-item.component.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-item.component.html","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu.component.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu.component.html"],"sourcesContent":["import { Directive, inject, TemplateRef } from '@angular/core';\n\n/**\n * Помечает `<ng-template>` своего значка пункта меню. Кит ставит содержимое на место значка\n * `rt-menu-item__icon` его размером и цветом тона пункта — так приложение рисует значок, которого\n * нет ни в наборе кита, ни в перечне имён Material. Свой значок сильнее `icon` и `glyph`.\n *\n * ```html\n * <rt-menu-item label=\"Сделать активным\">\n * <ng-template rtMenuItemIcon><svg viewBox=\"0 0 24 24\">…</svg></ng-template>\n * </rt-menu-item>\n * ```\n */\n@Directive({\n selector: 'ng-template[rtMenuItemIcon]',\n})\nexport class RtMenuItemIconDirective {\n public readonly templateRef: TemplateRef<unknown> = inject<TemplateRef<unknown>>(TemplateRef);\n}\n","import { inject, ChangeDetectionStrategy, Component, Signal, ViewEncapsulation } from '@angular/core';\n\nimport { BlockDirective, ElemDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { RtButtonDirective } from '@rt-tools/ui-kit-v2/button';\nimport { RtDialogRef } from '@rt-tools/ui-kit-v2/dialog';\nimport { RtDialogComponent } from '@rt-tools/ui-kit-v2/dialog';\nimport { RT_DIALOG_DATA } from '@rt-tools/ui-kit-v2/dialog';\nimport { IRtMenu } from './rt-menu.model';\n\nconst BEM_BLOCK: string = 'rt-menu-confirm-dialog';\n\n/**\n * Confirm-модалка деструктивного пункта `rt-menu-item`. Открывается через\n * `RtDialogService` (центрированный overlay поверх меню), возвращает `true`\n * при подтверждении и `false`/`undefined` при отмене.\n *\n * Модалка (а не popover-под-пунктом) нужна потому, что панель `rt-menu` сама\n * живёт в CDK Overlay: вложенный popover-overlay конфликтовал бы с её\n * backdrop/закрытием. Внутренний компонент — не экспортируется из `components`, это\n * деталь реализации confirm-флоу пункта меню.\n */\n@Component({\n selector: 'rt-menu-confirm-dialog',\n templateUrl: './rt-menu-confirm-dialog.component.html',\n styleUrl: './rt-menu-confirm-dialog.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtButtonDirective,\n RtDialogComponent,\n BlockDirective,\n ElemDirective,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtMenuConfirmDialogComponent {\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly data: IRtMenu.ConfirmData = inject(RT_DIALOG_DATA) as IRtMenu.ConfirmData;\n\n readonly #dialogRef: RtDialogRef<boolean> = inject(RtDialogRef);\n\n protected onConfirm(): void {\n this.#dialogRef.close(true);\n }\n\n protected onCancel(): void {\n this.#dialogRef.close(false);\n }\n}\n","<rt-dialog width=\"360px\" [ariaLabel]=\"t().uiConfirmAction\">\n <div rtBlock=\"rt-menu-confirm-dialog\">\n <div rtElem=\"text\">\n @if (data.title; as title) {\n <h2 rtElem=\"title\" qa-dataid=\"menu-confirm-title\">{{ title }}</h2>\n }\n <p rtElem=\"message\" qa-dataid=\"menu-confirm-message\">{{ data.message }}</p>\n </div>\n <div rtElem=\"footer\">\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content -->\n <button\n rtButton\n qa-dataid=\"menu-confirm-cancel\"\n type=\"button\"\n appearance=\"text\"\n theme=\"secondary\"\n [label]=\"data.cancelLabel\"\n (click)=\"onCancel()\"></button>\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content -->\n <button\n rtButton\n qa-dataid=\"menu-confirm-accept\"\n type=\"button\"\n appearance=\"filled\"\n [label]=\"data.confirmLabel\"\n [theme]=\"data.tone\"\n (click)=\"onConfirm()\"></button>\n </div>\n </div>\n</rt-dialog>\n","import { materialPairOf } from '@rt-tools/ui-kit-v2/icon';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\n\n/** Значок пункта: свой `icon`, а без него — пара имени Material из перечня кита. */\nexport function menuItemIconName(icon: IRtIcon.Name | null, glyph: string | null): IRtIcon.Name | null {\n if (icon !== null) {\n return icon;\n }\n return materialPairOf(glyph);\n}\n\n/**\n * Имя Material, о котором пункт должен предупредить: у него нет пары в перечне кита, а ни `icon`,\n * ни своего значка нет. Тогда пункт рисуется без значка, и без предупреждения пропуск не заметен.\n * `null` — предупреждать не о чем.\n */\nexport function unpairedGlyph(icon: IRtIcon.Name | null, glyph: string | null, hasOwnIcon: boolean): string | null {\n if (!glyph || hasOwnIcon || menuItemIconName(icon, glyph) !== null) {\n return null;\n }\n return glyph;\n}\n","/**\n * Контракты `rt-menu` — dropdown-меню действий (триггер «…» + плавающая панель\n * с пунктами `rt-menu-item`). Один корневой неймспейс с префиксом `I`.\n */\nexport namespace IRtMenu {\n /** Горизонтальное выравнивание панели относительно триггера. */\n export type Align = 'start' | 'end';\n\n /**\n * Размер панели: `md` — обычный, `sm` — компактный, как меню действий строки в первом ките. Под\n * материальным набором у компактного пункт ниже и значок мельче; свой вид их не различает.\n */\n export type Size = 'md' | 'sm';\n\n /** Тон подтверждающей кнопки в confirm-модалке пункта меню. */\n export type ConfirmTone = 'danger' | 'warning' | 'primary';\n\n /**\n * Данные для confirm-модалки, которую `rt-menu-item` открывает перед\n * деструктивным действием. Прокидываются в `rt-menu-confirm-dialog` через\n * `RT_DIALOG_DATA`; модалка возвращает `true` при подтверждении.\n */\n export interface ConfirmData {\n readonly message: string;\n readonly title: string | null;\n readonly confirmLabel: string;\n readonly cancelLabel: string;\n readonly tone: ConfirmTone;\n }\n\n /** Пункт панели для хода стрелками: его узел и признак, что его пропускают. */\n export interface Focusable {\n readonly disabled: boolean;\n focus(): void;\n }\n}\n\n/**\n * Имя DOM-события, которое `rt-menu-item` всплывающе диспатчит при выборе пункта.\n * `rt-menu` слушает его на панели и закрывается. DOM-событие (а не DI/output)\n * нужно потому, что пункты проецируются в overlay-панель — всплытие через DOM\n * переживает границы content-projection и overlay-контейнера.\n */\nexport const RT_MENU_SELECT_EVENT: string = 'rtMenuSelect';\n","import { BooleanInput } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n computed,\n Component,\n contentChild,\n DestroyRef,\n effect,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n isDevMode,\n output,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { RouterLink } from '@angular/router';\n\nimport { mergeMap, Observable, Subject } from 'rxjs';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { RtDialogService } from '@rt-tools/ui-kit-v2/dialog';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\nimport { RtMenuConfirmDialogComponent } from './rt-menu-confirm-dialog.component';\nimport { RtMenuItemIconDirective } from './rt-menu-item-icon.directive';\nimport { menuItemIconName, unpairedGlyph } from './rt-menu-item.logic';\nimport { RT_MENU_SELECT_EVENT, IRtMenu } from './rt-menu.model';\n\nconst BEM_BLOCK: string = 'rt-menu-item';\n\n/**\n * Пункт меню `rt-menu`: иконка (опц.) + лейбл. Кликабелен и активируется с\n * клавиатуры (Enter/Space). Выбор пункта эмитит `(selected)` для потребителя\n * и всплывающе диспатчит DOM-событие `rtMenuSelect`, по которому `rt-menu`\n * закрывается. `disabled` блокирует и `(selected)`, и закрытие.\n *\n * Tooltip — через host-директиву `RtTooltipDirective` (`tooltip` маппится в\n * `rtTooltip`): полезно показать причину недоступности на `disabled`-пункте.\n *\n * Деструктивный пункт может требовать подтверждения: задайте `confirmMessage`\n * (опц. `confirmTitle` / `confirmLabel` / `confirmTone`) — тогда по выбору\n * сперва открывается центрированная confirm-модалка, и `(selected)` эмитится\n * только после подтверждения. Модалка (а не popover) нужна потому, что панель\n * `rt-menu` сама в CDK Overlay; меню остаётся открытым под backdrop'ом, пока\n * пользователь решает.\n *\n * `ViewEncapsulation.None`; стили префиксованы `.rt-menu-item`. Host несёт\n * BEM-класс блока (template-`<ng-container rtBlock>` даёт контекст для `rtElem`,\n * но класс на comment-node не вешает — см. host-class паттерн rt-icon-button).\n */\n@Component({\n selector: 'rt-menu-item',\n templateUrl: './rt-menu-item.component.html',\n styleUrl: './rt-menu-item.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtIconComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n NgTemplateOutlet,\n RouterLink,\n ],\n hostDirectives: [\n {\n directive: RtTooltipDirective,\n inputs: ['rtTooltip: tooltip'],\n },\n { directive: RtRadiusDirective, inputs: ['radius'] },\n ],\n host: {\n class: BEM_BLOCK,\n '[attr.role]': \"isLink() ? 'none' : 'menuitem'\",\n '[class.rt-menu-item--danger]': 'danger()',\n '[class.rt-menu-item--success]': 'success()',\n '[class.rt-menu-item--disabled]': 'disabled()',\n '[class.rt-menu-item--current]': 'current()',\n '[class.rt-menu-item--link]': 'isLink()',\n '[attr.aria-current]': \"current() && !isLink() ? 'true' : null\",\n '[attr.aria-disabled]': \"disabled() && !isLink() ? 'true' : null\",\n '[attr.tabindex]': 'disabled() || isLink() ? null : 0',\n '(click)': 'onActivate($event)',\n '(auxclick)': 'onAuxClick($event)',\n '(keydown.enter)': 'onKey($event)',\n '(keydown.space)': 'onKey($event)',\n },\n})\nexport class RtMenuItemComponent {\n readonly #elementRef: ElementRef<HTMLElement> = inject<ElementRef<HTMLElement>>(ElementRef);\n readonly #dialogService: RtDialogService = inject(RtDialogService);\n readonly #destroyRef: DestroyRef = inject(DestroyRef);\n\n readonly #confirmRequestSource: Subject<IRtMenu.ConfirmData> = new Subject<IRtMenu.ConfirmData>();\n\n readonly #t_uiConfirm: Signal<string> = rtKitLabel('uiConfirm');\n readonly #t_uiCancel: Signal<string> = rtKitLabel('uiCancel');\n\n /** Свой значок приложения — `<ng-template rtMenuItemIcon>` внутри пункта. */\n protected readonly ownIcon: Signal<RtMenuItemIconDirective | undefined> = contentChild(RtMenuItemIconDirective);\n\n /** Значок пункта: свой `icon`, а без него — пара имени Material из перечня кита. */\n protected readonly iconName: Signal<IRtIcon.Name | null> = computed((): IRtIcon.Name | null =>\n menuItemIconName(this.icon(), this.glyph())\n );\n\n /** Пункт — ссылка: задан `link`. Роль пункта меню и фокус тогда несёт ссылка внутри. */\n protected readonly isLink: Signal<boolean> = computed((): boolean => this.link() !== null);\n\n /** Адрес для ссылки: у недоступного пункта его нет, и ссылка не переходит. */\n protected readonly linkTarget: Signal<RouterLink['routerLink']> = computed((): RouterLink['routerLink'] =>\n this.disabled() ? null : this.link()\n );\n\n /** Иконка слева от лейбла. `null` — без иконки. */\n public readonly icon: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /** Текст пункта. */\n public readonly label: InputSignal<string> = input<string>('');\n\n /** Деструктивный пункт (например «Удалить») — красный текст/иконка. */\n public readonly danger: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Пункт-согласие (например «Принять») — зелёный текст и иконка, как тон `success` пунктов первого кита. */\n public readonly success: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Имя значка Material, как его пишет пункт меню первого кита (`check_circle`). Рисует его набор\n * кита через перечень соответствий; `icon` сильнее, а имя без пары рисует пункт без значка.\n */\n public readonly glyph: InputSignal<string | null> = input<string | null>(null);\n\n /**\n * Залитый значок вместо контурного — как значки пунктов меню первого кита. Уходит в `fill`\n * значка: действует в материальном наборе, свой набор рисует значок одним рисунком. Свой\n * значок `rtMenuItemIcon` приложение рисует само, и заливка его не касается.\n */\n public readonly fill: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Пункт — нынешнее значение выбора, который открыл меню: подсвечен фоном и объявлен скринридеру. */\n public readonly current: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Недоступный пункт — приглушён, не эмитит `(selected)` и не закрывает меню. */\n public readonly disabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Текст confirm-модалки. Непустое значение включает подтверждение: по выбору\n * пункта открывается модалка, и `(selected)` эмитится только после согласия.\n */\n public readonly confirmMessage: InputSignal<string> = input<string>('');\n\n /** Заголовок confirm-модалки (опц.). */\n public readonly confirmTitle: InputSignal<string | null> = input<string | null>(null);\n\n /** Лейбл подтверждающей кнопки в модалке. */\n /** Пусто — берётся переведённая подпись по умолчанию */\n public readonly confirmLabel: InputSignal<string> = input<string>('');\n\n /** Лейбл кнопки отмены в модалке. */\n public readonly confirmCancelLabel: InputSignal<string> = input<string>('');\n\n /** Тон подтверждающей кнопки в модалке. */\n public readonly confirmTone: InputSignal<IRtMenu.ConfirmTone> = input<IRtMenu.ConfirmTone>('danger');\n\n /**\n * Команды маршрута приложения, как у `routerLink`. Задан — пункт рисует ссылку с `href`: Enter и\n * клик переходят по ней, а Ctrl/Cmd-click, Shift-click и средняя кнопка открывают новую вкладку\n * или окно силами браузера. Меню закрывается во всех этих случаях; подтверждение не спрашивается.\n */\n public readonly link: InputSignal<RouterLink['routerLink']> = input<RouterLink['routerLink']>(null);\n\n /** Пункт выбран (клик/Enter/Space и не `disabled`; после подтверждения, если задано). */\n public readonly selected: OutputEmitterRef<void> = output<void>();\n\n constructor() {\n // Имя Material без пары рисует пункт без значка, и пропуск без предупреждения не заметен.\n if (isDevMode()) {\n effect((): void => {\n const glyph: string | null = unpairedGlyph(this.icon(), this.glyph(), this.ownIcon() !== undefined);\n if (glyph !== null) {\n // eslint-disable-next-line no-console -- предупреждение разработчику приложения: другого канала у кита нет\n console.warn(\n `rt-menu-item «${this.label()}»: у значка Material «${glyph}» нет пары в перечне кита. ` +\n 'Задайте icon или свой значок через <ng-template rtMenuItemIcon>.'\n );\n }\n });\n }\n\n // Подписка на результат confirm-модалки объявлена один раз: #openConfirm\n // эмитит данные модалки, mergeMap открывает её и ждёт afterClosed()\n // (одноразовый стрим — комплитится при закрытии модалки).\n this.#confirmRequestSource\n .pipe(\n mergeMap((data: IRtMenu.ConfirmData): Observable<boolean | undefined> =>\n this.#dialogService\n .open<RtMenuConfirmDialogComponent, IRtMenu.ConfirmData, boolean>(RtMenuConfirmDialogComponent, { data })\n .afterClosed()\n ),\n takeUntilDestroyed(this.#destroyRef)\n )\n .subscribe((confirmed: boolean | undefined = false): void => {\n if (confirmed === true) {\n this.#commitSelection();\n }\n });\n }\n\n protected onActivate(event: Event): void {\n if (this.disabled()) {\n // Гасим, чтобы клик по disabled-пункту не «протёк» наружу.\n event.stopPropagation();\n event.preventDefault();\n return;\n }\n const message: string = this.confirmMessage().trim();\n if (message !== '' && !this.isLink()) {\n // Не закрываем меню сразу: оно остаётся открытым под backdrop'ом\n // модалки, чтобы пункт пережил решение пользователя (отмена → меню\n // снова видно). Подтверждение коммитит выбор.\n this.#openConfirm(message);\n return;\n }\n this.#commitSelection();\n }\n\n protected onKey(event: Event): void {\n if (this.isLink()) {\n this.#onLinkKey(event);\n return;\n }\n // Space иначе проскроллит страницу — гасим дефолт перед активацией.\n event.preventDefault();\n this.onActivate(event);\n }\n\n /** Средняя кнопка не даёт `click`: вкладку открывает браузер, а меню закрываем сами. */\n protected onAuxClick(event: MouseEvent): void {\n if (this.isLink() && event.button === 1 && !this.disabled()) {\n this.#commitSelection();\n }\n }\n\n /**\n * Enter на ссылке браузер сам превращает в `click`, и переход делает `routerLink`. Пробел ссылка\n * не нажимает — его переводим в тот же `click`, погасив прокрутку страницы.\n */\n #onLinkKey(event: Event): void {\n if (event instanceof KeyboardEvent && event.key === ' ') {\n event.preventDefault();\n this.#elementRef.nativeElement.querySelector<HTMLElement>('a')?.click();\n }\n }\n\n #openConfirm(message: string): void {\n const data: IRtMenu.ConfirmData = {\n message,\n title: this.confirmTitle(),\n confirmLabel: this.confirmLabel() || this.#t_uiConfirm(),\n cancelLabel: this.confirmCancelLabel() || this.#t_uiCancel(),\n tone: this.confirmTone(),\n };\n // Открытие модалки и подписка на результат — в конструкторном стриме\n // (см. #confirmRequestSource); здесь только эмит данных модалки.\n this.#confirmRequestSource.next(data);\n }\n\n #commitSelection(): void {\n this.selected.emit();\n // Закрыть родительское меню: событие всплывает к панели rt-menu в overlay.\n this.#elementRef.nativeElement.dispatchEvent(new CustomEvent(RT_MENU_SELECT_EVENT, { bubbles: true }));\n }\n}\n","<ng-container rtBlock=\"rt-menu-item\">\n @if (isLink()) {\n <a\n rtElem=\"link\"\n role=\"menuitem\"\n qa-dataid=\"menu-item-link\"\n [routerLink]=\"linkTarget()\"\n [attr.aria-current]=\"current() ? 'true' : null\"\n [attr.aria-disabled]=\"disabled() ? 'true' : null\"\n [attr.tabindex]=\"disabled() ? null : 0\">\n <ng-container [ngTemplateOutlet]=\"content\" />\n </a>\n } @else {\n <ng-container [ngTemplateOutlet]=\"content\" />\n }\n\n <ng-template #content>\n @if (ownIcon(); as own) {\n <span rtElem=\"icon\" qa-dataid=\"menu-item-own-icon\" aria-hidden=\"true\" [rtMod]=\"{ own: true }\">\n <ng-container [ngTemplateOutlet]=\"own.templateRef\" />\n </span>\n } @else if (iconName(); as name) {\n <rt-icon rtElem=\"icon\" size=\"sm\" [name]=\"name\" [fill]=\"fill()\" />\n }\n\n <span rtElem=\"label\" qa-dataid=\"menu-item-label\">{{ label() }}</span>\n </ng-template>\n</ng-container>\n","import { FocusKeyManager } from '@angular/cdk/a11y';\nimport { BooleanInput } from '@angular/cdk/coercion';\nimport { CdkConnectedOverlay, CdkOverlayOrigin, ConnectedPosition, OverlayModule } from '@angular/cdk/overlay';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n output,\n OutputEmitterRef,\n Signal,\n signal,\n viewChild,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { carryThemeScope, materialPresetClassesOf } from '@rt-tools/ui-kit-v2/core';\nimport { IRtIconButton, RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { IRtMenu } from './rt-menu.model';\n\nconst BEM_BLOCK: string = 'rt-menu';\n\nconst POSITION_BELOW_END: ConnectedPosition = {\n originX: 'end',\n originY: 'bottom',\n overlayX: 'end',\n overlayY: 'top',\n offsetY: 4,\n};\nconst POSITION_ABOVE_END: ConnectedPosition = {\n originX: 'end',\n originY: 'top',\n overlayX: 'end',\n overlayY: 'bottom',\n offsetY: -4,\n};\nconst POSITION_BELOW_START: ConnectedPosition = {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n offsetY: 4,\n};\nconst POSITION_ABOVE_START: ConnectedPosition = {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'bottom',\n offsetY: -4,\n};\n\n/**\n * Dropdown-меню действий: icon-only триггер «…» + плавающая панель с пунктами\n * `rt-menu-item`, спроецированными через `<ng-content>`. Типовое применение —\n * per-row действия в конце строки `rt-table` (см. `[showRowActions]`).\n *\n * Движок — CDK `cdkConnectedOverlay` с прозрачным backdrop: авто-flip у края\n * viewport (4 fallback-позиции), backdrop-click и `(detach)` закрывают, Escape\n * закрывает через `(overlayKeydown)`. Панель не режется `overflow: hidden`\n * предками (таблицы, карточки), т.к. рендерится в overlay-контейнере.\n *\n * Выбор пункта закрывает меню: `rt-menu-item` всплывающе диспатчит DOM-событие\n * `rtMenuSelect`, которое панель ловит, — это переживает content-projection.\n *\n * @example\n * ```html\n * <rt-menu ariaLabel=\"Действия\">\n * <rt-menu-item icon=\"ico-edit\" label=\"Редактировать\" (selected)=\"edit()\" />\n * <rt-menu-item icon=\"ico-trash\" label=\"Удалить\" danger (selected)=\"remove()\" />\n * </rt-menu>\n * ```\n */\n@Component({\n selector: 'rt-menu',\n templateUrl: './rt-menu.component.html',\n styleUrl: './rt-menu.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // @angular/cdk\n OverlayModule,\n\n // standalone components / directives\n RtIconButtonComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n host: {\n class: BEM_BLOCK,\n '[class.rt-menu--open]': 'isOpen()',\n },\n})\nexport class RtMenuComponent {\n readonly #host: ElementRef<HTMLElement> = inject<ElementRef<HTMLElement>>(ElementRef);\n readonly #t_uiActions: Signal<string> = rtKitLabel('uiActions');\n\n /** Ход стрелками по пунктам открытой панели; у закрытой его нет. */\n #keyManager: FocusKeyManager<IRtMenu.Focusable> | null = null;\n\n protected readonly overlay: Signal<CdkConnectedOverlay> = viewChild.required(CdkConnectedOverlay);\n protected readonly trigger: Signal<CdkOverlayOrigin> = viewChild.required(CdkOverlayOrigin);\n\n protected readonly isOpen: WritableSignal<boolean> = signal<boolean>(false);\n\n /** Класс набора, найденный над меню при открытии: панель лежит вне контейнера с признаком. */\n protected readonly presetClasses: WritableSignal<string[]> = signal<string[]>([]);\n\n /** Классы панели: заданные входом и класс набора. */\n protected readonly panelClasses: Signal<string[]> = computed((): string[] => {\n const own: string | string[] = this.panelClass();\n return [...(Array.isArray(own) ? own : own.split(/\\s+/).filter(Boolean)), ...this.presetClasses()];\n });\n\n protected readonly ariaText: Signal<string> = computed((): string => this.ariaLabel() || this.#t_uiActions());\n\n /** Fallback-цепочка позиций панели: первой идёт сторона по `align`. */\n protected readonly overlayPositions: Signal<ConnectedPosition[]> = computed((): ConnectedPosition[] =>\n this.align() === 'end'\n ? [POSITION_BELOW_END, POSITION_ABOVE_END, POSITION_BELOW_START, POSITION_ABOVE_START]\n : [POSITION_BELOW_START, POSITION_ABOVE_START, POSITION_BELOW_END, POSITION_ABOVE_END]\n );\n\n /** Иконка триггера. Default `ellipsis-h` («…» — три точки в конце строки). */\n public readonly icon: InputSignal<IRtIcon.Name> = input<IRtIcon.Name>('ellipsis-h');\n\n /** ARIA-метка триггера (icon-only кнопка) + текст tooltip'а. */\n /** Пусто — берётся переведённая подпись по умолчанию */\n public readonly ariaLabel: InputSignal<string> = input<string>('');\n\n /** Сторона раскрытия панели относительно триггера. */\n public readonly align: InputSignal<IRtMenu.Align> = input<IRtMenu.Align>('end');\n\n /**\n * Классы панели. Панель живёт поверх страницы, вне хоста меню, и признаки вида над хостом до неё\n * не доходят: семья, нарисованная своим набором, отдаёт его панели этим входом.\n */\n public readonly panelClass: InputSignal<string | string[]> = input<string | string[]>([]);\n\n /** Размер кнопки-триггера: мельче `md` — в плотной строке рядом с другими действиями строки. */\n public readonly triggerSize: InputSignal<IRtIconButton.Size> = input<IRtIconButton.Size>('md');\n\n /** Размер панели: компактная — у меню действий строки таблицы. */\n public readonly size: InputSignal<IRtMenu.Size> = input<IRtMenu.Size>('md');\n\n /** Триггер отключён — меню не открыть. */\n public readonly disabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Панель открылась (`true`) или закрылась (`false`); повтор того же состояния не приходит. */\n public readonly openedChange: OutputEmitterRef<boolean> = output<boolean>();\n\n protected toggle(event: MouseEvent): void {\n // Клик по триггеру не должен активировать строку таблицы под ним.\n event.stopPropagation();\n this.#setOpen(!this.isOpen());\n }\n\n protected close(): void {\n this.#setOpen(false);\n }\n\n /**\n * Панель легла на страницу — фокус уходит на первый пункт, как у меню Material. Пункты берутся\n * из разметки панели, а не запросом компонентов: таблица кладёт их шаблоном приложения, и\n * запрос содержимого меню их не видит.\n */\n protected onAttach(): void {\n const pane: HTMLElement = this.overlay().overlayRef.overlayElement;\n\n // Тема куска `rtTheme` вокруг меню едет на коробку панели, как у поповера и подсказки:\n // панель лежит в конце страницы, и без этого меню из тёмной карточки рисовалось темой\n // страницы. Зовётся на каждом открытии — кусок вокруг кнопки мог смениться.\n carryThemeScope(pane, this.trigger().elementRef.nativeElement);\n\n const nodes: HTMLElement[] = Array.from(pane.querySelectorAll<HTMLElement>('[role=\"menuitem\"]'));\n const focusables: IRtMenu.Focusable[] = nodes.map((node: HTMLElement): IRtMenu.Focusable => ({\n disabled: node.getAttribute('aria-disabled') === 'true',\n focus: (): void => node.focus(),\n }));\n\n this.#keyManager = new FocusKeyManager<IRtMenu.Focusable>(focusables).withWrap().withHomeAndEnd();\n this.#keyManager.setFirstItemActive();\n }\n\n /** Выбранный пункт закрывает панель и возвращает фокус кнопке, откуда меню открыли. */\n protected onSelect(): void {\n this.close();\n this.#focusTrigger();\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape') {\n // Escape закрывает один слой: меню, а не боковую панель или окно под ним.\n event.stopPropagation();\n this.close();\n this.#focusTrigger();\n return;\n }\n\n if (event.key === 'Tab') {\n // Tab уводит фокус дальше по порядку — панель за ним не остаётся. Панель лежит в конце\n // страницы, и без возврата Tab ушёл бы с неё в никуда: фокус ставится на кнопку, а\n // умолчание клавиши не отменяется — браузер ведёт его от кнопки к следующему, как у\n // меню Material.\n this.close();\n this.#focusTrigger();\n return;\n }\n\n this.#keyManager?.onKeydown(event);\n }\n\n #focusTrigger(): void {\n this.trigger().elementRef.nativeElement.querySelector('button')?.focus();\n }\n\n #setOpen(open: boolean): void {\n if (open !== this.isOpen()) {\n if (!open) {\n this.#keyManager?.destroy();\n this.#keyManager = null;\n }\n if (open) {\n this.presetClasses.set(materialPresetClassesOf(this.#host.nativeElement));\n }\n this.isOpen.set(open);\n this.openedChange.emit(open);\n }\n }\n}\n","<rt-icon-button\n cdkOverlayOrigin\n qa-dataid=\"menu-trigger\"\n #trigger=\"cdkOverlayOrigin\"\n variant=\"ghost\"\n [size]=\"triggerSize()\"\n [icon]=\"icon()\"\n [ariaLabel]=\"ariaText()\"\n [tooltip]=\"ariaText()\"\n [disabled]=\"disabled()\"\n (clicked)=\"toggle($event)\" />\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPositions]=\"overlayPositions()\"\n [cdkConnectedOverlayPanelClass]=\"panelClasses()\"\n (backdropClick)=\"close()\"\n (attach)=\"onAttach()\"\n (detach)=\"close()\"\n (overlayKeydown)=\"onKeydown($event)\">\n <ng-container rtBlock=\"rt-menu\">\n <div rtElem=\"panel\" qa-dataid=\"menu-panel\" role=\"menu\" [rtMod]=\"{ size: size() }\" (rtMenuSelect)=\"onSelect()\">\n <ng-content />\n </div>\n </ng-container>\n</ng-template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-menu.mjs","names":["BEM_BLOCK","BEM_BLOCK","i1"],"sources":["../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-item-icon.directive.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-confirm-dialog.component.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-confirm-dialog.component.html","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-item.logic.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu.model.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-item.component.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu-item.component.html","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu.component.ts","../../../projects/ui-kit-v2/src/lib/components/menu/rt-menu.component.html"],"sourcesContent":["import { Directive, inject, TemplateRef } from '@angular/core';\n\n/**\n * Помечает `<ng-template>` своего значка пункта меню. Кит ставит содержимое на место значка\n * `rt-menu-item__icon` его размером и цветом тона пункта — так приложение рисует значок, которого\n * нет ни в наборе кита, ни в перечне имён Material. Свой значок сильнее `icon` и `glyph`.\n *\n * ```html\n * <rt-menu-item label=\"Сделать активным\">\n * <ng-template rtMenuItemIcon><svg viewBox=\"0 0 24 24\">…</svg></ng-template>\n * </rt-menu-item>\n * ```\n */\n@Directive({\n selector: 'ng-template[rtMenuItemIcon]',\n})\nexport class RtMenuItemIconDirective {\n public readonly templateRef: TemplateRef<unknown> = inject<TemplateRef<unknown>>(TemplateRef);\n}\n","import { inject, ChangeDetectionStrategy, Component, Signal, ViewEncapsulation } from '@angular/core';\n\nimport { BlockDirective, ElemDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { RtButtonDirective } from '@rt-tools/ui-kit-v2/button';\nimport { RtDialogRef } from '@rt-tools/ui-kit-v2/dialog';\nimport { RtDialogComponent } from '@rt-tools/ui-kit-v2/dialog';\nimport { RT_DIALOG_DATA } from '@rt-tools/ui-kit-v2/dialog';\nimport { IRtMenu } from './rt-menu.model';\n\nconst BEM_BLOCK: string = 'rt-menu-confirm-dialog';\n\n/**\n * Confirm-модалка деструктивного пункта `rt-menu-item`. Открывается через\n * `RtDialogService` (центрированный overlay поверх меню), возвращает `true`\n * при подтверждении и `false`/`undefined` при отмене.\n *\n * Модалка (а не popover-под-пунктом) нужна потому, что панель `rt-menu` сама\n * живёт в CDK Overlay: вложенный popover-overlay конфликтовал бы с её\n * backdrop/закрытием. Внутренний компонент — не экспортируется из `components`, это\n * деталь реализации confirm-флоу пункта меню.\n */\n@Component({\n selector: 'rt-menu-confirm-dialog',\n templateUrl: './rt-menu-confirm-dialog.component.html',\n styleUrl: './rt-menu-confirm-dialog.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtButtonDirective,\n RtDialogComponent,\n BlockDirective,\n ElemDirective,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtMenuConfirmDialogComponent {\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly data: IRtMenu.ConfirmData = inject(RT_DIALOG_DATA) as IRtMenu.ConfirmData;\n\n readonly #dialogRef: RtDialogRef<boolean> = inject(RtDialogRef);\n\n protected onConfirm(): void {\n this.#dialogRef.close(true);\n }\n\n protected onCancel(): void {\n this.#dialogRef.close(false);\n }\n}\n","<rt-dialog width=\"360px\" [ariaLabel]=\"t().uiConfirmAction\">\n <div rtBlock=\"rt-menu-confirm-dialog\">\n <div rtElem=\"text\">\n @if (data.title; as title) {\n <h2 rtElem=\"title\" qa-dataid=\"menu-confirm-title\">{{ title }}</h2>\n }\n <p rtElem=\"message\" qa-dataid=\"menu-confirm-message\">{{ data.message }}</p>\n </div>\n <div rtElem=\"footer\">\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content -->\n <button\n rtButton\n qa-dataid=\"menu-confirm-cancel\"\n type=\"button\"\n appearance=\"text\"\n theme=\"secondary\"\n [label]=\"data.cancelLabel\"\n (click)=\"onCancel()\"></button>\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content -->\n <button\n rtButton\n qa-dataid=\"menu-confirm-accept\"\n type=\"button\"\n appearance=\"filled\"\n [label]=\"data.confirmLabel\"\n [theme]=\"data.tone\"\n (click)=\"onConfirm()\"></button>\n </div>\n </div>\n</rt-dialog>\n","import { materialPairOf } from '@rt-tools/ui-kit-v2/icon';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\n\n/** Значок пункта: свой `icon`, а без него — пара имени Material из перечня кита. */\nexport function menuItemIconName(icon: IRtIcon.Name | null, glyph: string | null): IRtIcon.Name | null {\n if (icon !== null) {\n return icon;\n }\n return materialPairOf(glyph);\n}\n\n/**\n * Имя Material, о котором пункт должен предупредить: у него нет пары в перечне кита, а ни `icon`,\n * ни своего значка нет. Тогда пункт рисуется без значка, и без предупреждения пропуск не заметен.\n * `null` — предупреждать не о чем.\n */\nexport function unpairedGlyph(icon: IRtIcon.Name | null, glyph: string | null, hasOwnIcon: boolean): string | null {\n if (!glyph || hasOwnIcon || menuItemIconName(icon, glyph) !== null) {\n return null;\n }\n return glyph;\n}\n","/**\n * Контракты `rt-menu` — dropdown-меню действий (триггер «…» + плавающая панель\n * с пунктами `rt-menu-item`). Один корневой неймспейс с префиксом `I`.\n */\nexport namespace IRtMenu {\n /** Горизонтальное выравнивание панели относительно триггера. */\n export type Align = 'start' | 'end';\n\n /**\n * Размер панели: `md` — обычный, `sm` — компактный, как меню действий строки в первом ките. Под\n * материальным набором у компактного пункт ниже и значок мельче; свой вид их не различает.\n */\n export type Size = 'md' | 'sm';\n\n /** Тон подтверждающей кнопки в confirm-модалке пункта меню. */\n export type ConfirmTone = 'danger' | 'warning' | 'primary';\n\n /**\n * Данные для confirm-модалки, которую `rt-menu-item` открывает перед\n * деструктивным действием. Прокидываются в `rt-menu-confirm-dialog` через\n * `RT_DIALOG_DATA`; модалка возвращает `true` при подтверждении.\n */\n export interface ConfirmData {\n readonly message: string;\n readonly title: string | null;\n readonly confirmLabel: string;\n readonly cancelLabel: string;\n readonly tone: ConfirmTone;\n }\n\n /** Пункт панели для хода стрелками: его узел и признак, что его пропускают. */\n export interface Focusable {\n readonly disabled: boolean;\n focus(): void;\n }\n}\n\n/**\n * Имя DOM-события, которое `rt-menu-item` всплывающе диспатчит при выборе пункта.\n * `rt-menu` слушает его на панели и закрывается. DOM-событие (а не DI/output)\n * нужно потому, что пункты проецируются в overlay-панель — всплытие через DOM\n * переживает границы content-projection и overlay-контейнера.\n */\nexport const RT_MENU_SELECT_EVENT: string = 'rtMenuSelect';\n","import { BooleanInput } from '@angular/cdk/coercion';\nimport { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n computed,\n Component,\n contentChild,\n DestroyRef,\n effect,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n isDevMode,\n output,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { RouterLink } from '@angular/router';\n\nimport { mergeMap, Observable, Subject } from 'rxjs';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { RtDialogService } from '@rt-tools/ui-kit-v2/dialog';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';\nimport { RtMenuConfirmDialogComponent } from './rt-menu-confirm-dialog.component';\nimport { RtMenuItemIconDirective } from './rt-menu-item-icon.directive';\nimport { menuItemIconName, unpairedGlyph } from './rt-menu-item.logic';\nimport { RT_MENU_SELECT_EVENT, IRtMenu } from './rt-menu.model';\n\nconst BEM_BLOCK: string = 'rt-menu-item';\n\n/**\n * Пункт меню `rt-menu`: иконка (опц.) + лейбл. Кликабелен и активируется с\n * клавиатуры (Enter/Space). Выбор пункта эмитит `(selected)` для потребителя\n * и всплывающе диспатчит DOM-событие `rtMenuSelect`, по которому `rt-menu`\n * закрывается. `disabled` блокирует и `(selected)`, и закрытие.\n *\n * Tooltip — через host-директиву `RtTooltipDirective` (`tooltip` маппится в\n * `rtTooltip`): полезно показать причину недоступности на `disabled`-пункте.\n *\n * Деструктивный пункт может требовать подтверждения: задайте `confirmMessage`\n * (опц. `confirmTitle` / `confirmLabel` / `confirmTone`) — тогда по выбору\n * сперва открывается центрированная confirm-модалка, и `(selected)` эмитится\n * только после подтверждения. Модалка (а не popover) нужна потому, что панель\n * `rt-menu` сама в CDK Overlay; меню остаётся открытым под backdrop'ом, пока\n * пользователь решает.\n *\n * `ViewEncapsulation.None`; стили префиксованы `.rt-menu-item`. Host несёт\n * BEM-класс блока (template-`<ng-container rtBlock>` даёт контекст для `rtElem`,\n * но класс на comment-node не вешает — см. host-class паттерн rt-icon-button).\n */\n@Component({\n selector: 'rt-menu-item',\n templateUrl: './rt-menu-item.component.html',\n styleUrl: './rt-menu-item.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtIconComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n NgTemplateOutlet,\n RouterLink,\n ],\n hostDirectives: [\n {\n directive: RtTooltipDirective,\n inputs: ['rtTooltip: tooltip'],\n },\n { directive: RtRadiusDirective, inputs: ['radius'] },\n ],\n host: {\n class: BEM_BLOCK,\n '[attr.role]': \"isLink() ? 'none' : 'menuitem'\",\n '[class.rt-menu-item--danger]': 'danger()',\n '[class.rt-menu-item--success]': 'success()',\n '[class.rt-menu-item--disabled]': 'disabled()',\n '[class.rt-menu-item--current]': 'current()',\n '[class.rt-menu-item--link]': 'isLink()',\n '[attr.aria-current]': \"current() && !isLink() ? 'true' : null\",\n '[attr.aria-disabled]': \"disabled() && !isLink() ? 'true' : null\",\n '[attr.tabindex]': 'disabled() || isLink() ? null : 0',\n '(click)': 'onActivate($event)',\n '(auxclick)': 'onAuxClick($event)',\n '(keydown.enter)': 'onKey($event)',\n '(keydown.space)': 'onKey($event)',\n },\n})\nexport class RtMenuItemComponent {\n readonly #elementRef: ElementRef<HTMLElement> = inject<ElementRef<HTMLElement>>(ElementRef);\n readonly #dialogService: RtDialogService = inject(RtDialogService);\n readonly #destroyRef: DestroyRef = inject(DestroyRef);\n\n readonly #confirmRequestSource: Subject<IRtMenu.ConfirmData> = new Subject<IRtMenu.ConfirmData>();\n\n readonly #t_uiConfirm: Signal<string> = rtKitLabel('uiConfirm');\n readonly #t_uiCancel: Signal<string> = rtKitLabel('uiCancel');\n\n /** Свой значок приложения — `<ng-template rtMenuItemIcon>` внутри пункта. */\n protected readonly ownIcon: Signal<RtMenuItemIconDirective | undefined> = contentChild(RtMenuItemIconDirective);\n\n /** Значок пункта: свой `icon`, а без него — пара имени Material из перечня кита. */\n protected readonly iconName: Signal<IRtIcon.Name | null> = computed((): IRtIcon.Name | null =>\n menuItemIconName(this.icon(), this.glyph())\n );\n\n /** Пункт — ссылка: задан `link`. Роль пункта меню и фокус тогда несёт ссылка внутри. */\n protected readonly isLink: Signal<boolean> = computed((): boolean => this.link() !== null);\n\n /** Адрес для ссылки: у недоступного пункта его нет, и ссылка не переходит. */\n protected readonly linkTarget: Signal<RouterLink['routerLink']> = computed((): RouterLink['routerLink'] =>\n this.disabled() ? null : this.link()\n );\n\n /** Иконка слева от лейбла. `null` — без иконки. */\n public readonly icon: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /** Текст пункта. */\n public readonly label: InputSignal<string> = input<string>('');\n\n /** Деструктивный пункт (например «Удалить») — красный текст/иконка. */\n public readonly danger: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Пункт-согласие (например «Принять») — зелёный текст и иконка, как тон `success` пунктов первого кита. */\n public readonly success: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Имя значка Material, как его пишет пункт меню первого кита (`check_circle`). Рисует его набор\n * кита через перечень соответствий; `icon` сильнее, а имя без пары рисует пункт без значка.\n */\n public readonly glyph: InputSignal<string | null> = input<string | null>(null);\n\n /**\n * Залитый значок вместо контурного — как значки пунктов меню первого кита. Уходит в `fill`\n * значка: действует в материальном наборе, свой набор рисует значок одним рисунком. Свой\n * значок `rtMenuItemIcon` приложение рисует само, и заливка его не касается.\n */\n public readonly fill: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Пункт — нынешнее значение выбора, который открыл меню: подсвечен фоном и объявлен скринридеру. */\n public readonly current: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Недоступный пункт — приглушён, не эмитит `(selected)` и не закрывает меню. */\n public readonly disabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /**\n * Текст confirm-модалки. Непустое значение включает подтверждение: по выбору\n * пункта открывается модалка, и `(selected)` эмитится только после согласия.\n */\n public readonly confirmMessage: InputSignal<string> = input<string>('');\n\n /** Заголовок confirm-модалки (опц.). */\n public readonly confirmTitle: InputSignal<string | null> = input<string | null>(null);\n\n /** Лейбл подтверждающей кнопки в модалке. */\n /** Пусто — берётся переведённая подпись по умолчанию */\n public readonly confirmLabel: InputSignal<string> = input<string>('');\n\n /** Лейбл кнопки отмены в модалке. */\n public readonly confirmCancelLabel: InputSignal<string> = input<string>('');\n\n /** Тон подтверждающей кнопки в модалке. */\n public readonly confirmTone: InputSignal<IRtMenu.ConfirmTone> = input<IRtMenu.ConfirmTone>('danger');\n\n /**\n * Команды маршрута приложения, как у `routerLink`. Задан — пункт рисует ссылку с `href`: Enter и\n * клик переходят по ней, а Ctrl/Cmd-click, Shift-click и средняя кнопка открывают новую вкладку\n * или окно силами браузера. Меню закрывается во всех этих случаях; подтверждение не спрашивается.\n */\n public readonly link: InputSignal<RouterLink['routerLink']> = input<RouterLink['routerLink']>(null);\n\n /** Пункт выбран (клик/Enter/Space и не `disabled`; после подтверждения, если задано). */\n public readonly selected: OutputEmitterRef<void> = output<void>();\n\n constructor() {\n // Имя Material без пары рисует пункт без значка, и пропуск без предупреждения не заметен.\n if (isDevMode()) {\n effect((): void => {\n const glyph: string | null = unpairedGlyph(this.icon(), this.glyph(), this.ownIcon() !== undefined);\n if (glyph !== null) {\n // eslint-disable-next-line no-console -- предупреждение разработчику приложения: другого канала у кита нет\n console.warn(\n `rt-menu-item «${this.label()}»: у значка Material «${glyph}» нет пары в перечне кита. ` +\n 'Задайте icon или свой значок через <ng-template rtMenuItemIcon>.'\n );\n }\n });\n }\n\n // Подписка на результат confirm-модалки объявлена один раз: #openConfirm\n // эмитит данные модалки, mergeMap открывает её и ждёт afterClosed()\n // (одноразовый стрим — комплитится при закрытии модалки).\n this.#confirmRequestSource\n .pipe(\n mergeMap((data: IRtMenu.ConfirmData): Observable<boolean | undefined> =>\n this.#dialogService\n .open<RtMenuConfirmDialogComponent, IRtMenu.ConfirmData, boolean>(RtMenuConfirmDialogComponent, { data })\n .afterClosed()\n ),\n takeUntilDestroyed(this.#destroyRef)\n )\n .subscribe((confirmed: boolean | undefined = false): void => {\n if (confirmed === true) {\n this.#commitSelection();\n }\n });\n }\n\n protected onActivate(event: Event): void {\n if (this.disabled()) {\n // Гасим, чтобы клик по disabled-пункту не «протёк» наружу.\n event.stopPropagation();\n event.preventDefault();\n return;\n }\n const message: string = this.confirmMessage().trim();\n if (message !== '' && !this.isLink()) {\n // Не закрываем меню сразу: оно остаётся открытым под backdrop'ом\n // модалки, чтобы пункт пережил решение пользователя (отмена → меню\n // снова видно). Подтверждение коммитит выбор.\n this.#openConfirm(message);\n return;\n }\n this.#commitSelection();\n }\n\n protected onKey(event: Event): void {\n if (this.isLink()) {\n this.#onLinkKey(event);\n return;\n }\n // Space иначе проскроллит страницу — гасим дефолт перед активацией.\n event.preventDefault();\n this.onActivate(event);\n }\n\n /** Средняя кнопка не даёт `click`: вкладку открывает браузер, а меню закрываем сами. */\n protected onAuxClick(event: MouseEvent): void {\n if (this.isLink() && event.button === 1 && !this.disabled()) {\n this.#commitSelection();\n }\n }\n\n /**\n * Enter на ссылке браузер сам превращает в `click`, и переход делает `routerLink`. Пробел ссылка\n * не нажимает — его переводим в тот же `click`, погасив прокрутку страницы.\n */\n #onLinkKey(event: Event): void {\n if (event instanceof KeyboardEvent && event.key === ' ') {\n event.preventDefault();\n this.#elementRef.nativeElement.querySelector<HTMLElement>('a')?.click();\n }\n }\n\n #openConfirm(message: string): void {\n const data: IRtMenu.ConfirmData = {\n message,\n title: this.confirmTitle(),\n confirmLabel: this.confirmLabel() || this.#t_uiConfirm(),\n cancelLabel: this.confirmCancelLabel() || this.#t_uiCancel(),\n tone: this.confirmTone(),\n };\n // Открытие модалки и подписка на результат — в конструкторном стриме\n // (см. #confirmRequestSource); здесь только эмит данных модалки.\n this.#confirmRequestSource.next(data);\n }\n\n #commitSelection(): void {\n this.selected.emit();\n // Закрыть родительское меню: событие всплывает к панели rt-menu в overlay.\n this.#elementRef.nativeElement.dispatchEvent(new CustomEvent(RT_MENU_SELECT_EVENT, { bubbles: true }));\n }\n}\n","<ng-container rtBlock=\"rt-menu-item\">\n @if (isLink()) {\n <a\n rtElem=\"link\"\n role=\"menuitem\"\n qa-dataid=\"menu-item-link\"\n [routerLink]=\"linkTarget()\"\n [attr.aria-current]=\"current() ? 'true' : null\"\n [attr.aria-disabled]=\"disabled() ? 'true' : null\"\n [attr.tabindex]=\"disabled() ? null : 0\">\n <ng-container [ngTemplateOutlet]=\"content\" />\n </a>\n } @else {\n <ng-container [ngTemplateOutlet]=\"content\" />\n }\n\n <ng-template #content>\n @if (ownIcon(); as own) {\n <span rtElem=\"icon\" qa-dataid=\"menu-item-own-icon\" aria-hidden=\"true\" [rtMod]=\"{ own: true }\">\n <ng-container [ngTemplateOutlet]=\"own.templateRef\" />\n </span>\n } @else if (iconName(); as name) {\n <rt-icon rtElem=\"icon\" size=\"sm\" [name]=\"name\" [fill]=\"fill()\" />\n }\n\n <span rtElem=\"label\" qa-dataid=\"menu-item-label\">{{ label() }}</span>\n </ng-template>\n</ng-container>\n","import { FocusKeyManager } from '@angular/cdk/a11y';\nimport { BooleanInput } from '@angular/cdk/coercion';\nimport { CdkConnectedOverlay, CdkOverlayOrigin, ConnectedPosition, OverlayModule } from '@angular/cdk/overlay';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n output,\n OutputEmitterRef,\n Signal,\n signal,\n viewChild,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { carryThemeScope, materialPresetClassesOf } from '@rt-tools/ui-kit-v2/core';\nimport { IRtIconButton, RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { IRtMenu } from './rt-menu.model';\n\nconst BEM_BLOCK: string = 'rt-menu';\n\nconst POSITION_BELOW_END: ConnectedPosition = {\n originX: 'end',\n originY: 'bottom',\n overlayX: 'end',\n overlayY: 'top',\n offsetY: 4,\n};\nconst POSITION_ABOVE_END: ConnectedPosition = {\n originX: 'end',\n originY: 'top',\n overlayX: 'end',\n overlayY: 'bottom',\n offsetY: -4,\n};\nconst POSITION_BELOW_START: ConnectedPosition = {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n offsetY: 4,\n};\nconst POSITION_ABOVE_START: ConnectedPosition = {\n originX: 'start',\n originY: 'top',\n overlayX: 'start',\n overlayY: 'bottom',\n offsetY: -4,\n};\n\n/**\n * Dropdown-меню действий: icon-only триггер «…» + плавающая панель с пунктами\n * `rt-menu-item`, спроецированными через `<ng-content>`. Типовое применение —\n * per-row действия в конце строки `rt-table` (см. `[showRowActions]`).\n *\n * Движок — CDK `cdkConnectedOverlay` с прозрачным backdrop: авто-flip у края\n * viewport (4 fallback-позиции), backdrop-click и `(detach)` закрывают, Escape\n * закрывает через `(overlayKeydown)`. Панель не режется `overflow: hidden`\n * предками (таблицы, карточки), т.к. рендерится в overlay-контейнере.\n *\n * Выбор пункта закрывает меню: `rt-menu-item` всплывающе диспатчит DOM-событие\n * `rtMenuSelect`, которое панель ловит, — это переживает content-projection.\n *\n * @example\n * ```html\n * <rt-menu ariaLabel=\"Действия\">\n * <rt-menu-item icon=\"ico-edit\" label=\"Редактировать\" (selected)=\"edit()\" />\n * <rt-menu-item icon=\"ico-trash\" label=\"Удалить\" danger (selected)=\"remove()\" />\n * </rt-menu>\n * ```\n */\n@Component({\n selector: 'rt-menu',\n templateUrl: './rt-menu.component.html',\n styleUrl: './rt-menu.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // @angular/cdk\n OverlayModule,\n\n // standalone components / directives\n RtIconButtonComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n host: {\n class: BEM_BLOCK,\n '[class.rt-menu--open]': 'isOpen()',\n },\n})\nexport class RtMenuComponent {\n readonly #host: ElementRef<HTMLElement> = inject<ElementRef<HTMLElement>>(ElementRef);\n readonly #t_uiActions: Signal<string> = rtKitLabel('uiActions');\n\n /** Ход стрелками по пунктам открытой панели; у закрытой его нет. */\n #keyManager: FocusKeyManager<IRtMenu.Focusable> | null = null;\n\n protected readonly overlay: Signal<CdkConnectedOverlay> = viewChild.required(CdkConnectedOverlay);\n protected readonly trigger: Signal<CdkOverlayOrigin> = viewChild.required(CdkOverlayOrigin);\n\n protected readonly isOpen: WritableSignal<boolean> = signal<boolean>(false);\n\n /** Класс набора, найденный над меню при открытии: панель лежит вне контейнера с признаком. */\n protected readonly presetClasses: WritableSignal<string[]> = signal<string[]>([]);\n\n /** Классы панели: заданные входом и класс набора. */\n protected readonly panelClasses: Signal<string[]> = computed((): string[] => {\n const own: string | string[] = this.panelClass();\n return [...(Array.isArray(own) ? own : own.split(/\\s+/).filter(Boolean)), ...this.presetClasses()];\n });\n\n protected readonly ariaText: Signal<string> = computed((): string => this.ariaLabel() || this.#t_uiActions());\n\n /** Fallback-цепочка позиций панели: первой идёт сторона по `align`. */\n protected readonly overlayPositions: Signal<ConnectedPosition[]> = computed((): ConnectedPosition[] =>\n this.align() === 'end'\n ? [POSITION_BELOW_END, POSITION_ABOVE_END, POSITION_BELOW_START, POSITION_ABOVE_START]\n : [POSITION_BELOW_START, POSITION_ABOVE_START, POSITION_BELOW_END, POSITION_ABOVE_END]\n );\n\n /** Иконка триггера. Default `ellipsis-h` («…» — три точки в конце строки). */\n public readonly icon: InputSignal<IRtIcon.Name> = input<IRtIcon.Name>('ellipsis-h');\n\n /** ARIA-метка триггера (icon-only кнопка) + текст tooltip'а. */\n /** Пусто — берётся переведённая подпись по умолчанию */\n public readonly ariaLabel: InputSignal<string> = input<string>('');\n\n /** Сторона раскрытия панели относительно триггера. */\n public readonly align: InputSignal<IRtMenu.Align> = input<IRtMenu.Align>('end');\n\n /**\n * Классы панели. Панель живёт поверх страницы, вне хоста меню, и признаки вида над хостом до неё\n * не доходят: семья, нарисованная своим набором, отдаёт его панели этим входом.\n */\n public readonly panelClass: InputSignal<string | string[]> = input<string | string[]>([]);\n\n /** Размер кнопки-триггера: мельче `md` — в плотной строке рядом с другими действиями строки. */\n public readonly triggerSize: InputSignal<IRtIconButton.Size> = input<IRtIconButton.Size>('md');\n\n /** Размер панели: компактная — у меню действий строки таблицы. */\n public readonly size: InputSignal<IRtMenu.Size> = input<IRtMenu.Size>('md');\n\n /** Триггер отключён — меню не открыть. */\n public readonly disabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Панель открылась (`true`) или закрылась (`false`); повтор того же состояния не приходит. */\n public readonly openedChange: OutputEmitterRef<boolean> = output<boolean>();\n\n protected toggle(event: MouseEvent): void {\n // Клик по триггеру не должен активировать строку таблицы под ним.\n event.stopPropagation();\n this.#setOpen(!this.isOpen());\n }\n\n protected close(): void {\n this.#setOpen(false);\n }\n\n /**\n * Панель легла на страницу — фокус уходит на первый пункт, как у меню Material. Пункты берутся\n * из разметки панели, а не запросом компонентов: таблица кладёт их шаблоном приложения, и\n * запрос содержимого меню их не видит.\n */\n protected onAttach(): void {\n const pane: HTMLElement = this.overlay().overlayRef.overlayElement;\n\n // Тема куска `rtTheme` вокруг меню едет на коробку панели, как у поповера и подсказки:\n // панель лежит в конце страницы, и без этого меню из тёмной карточки рисовалось темой\n // страницы. Зовётся на каждом открытии — кусок вокруг кнопки мог смениться.\n carryThemeScope(pane, this.trigger().elementRef.nativeElement);\n\n const nodes: HTMLElement[] = Array.from(pane.querySelectorAll<HTMLElement>('[role=\"menuitem\"]'));\n const focusables: IRtMenu.Focusable[] = nodes.map((node: HTMLElement): IRtMenu.Focusable => ({\n disabled: node.getAttribute('aria-disabled') === 'true',\n focus: (): void => node.focus(),\n }));\n\n this.#keyManager = new FocusKeyManager<IRtMenu.Focusable>(focusables).withWrap().withHomeAndEnd();\n this.#keyManager.setFirstItemActive();\n }\n\n /** Выбранный пункт закрывает панель и возвращает фокус кнопке, откуда меню открыли. */\n protected onSelect(): void {\n this.close();\n this.#focusTrigger();\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape') {\n // Escape закрывает один слой: меню, а не боковую панель или окно под ним.\n event.stopPropagation();\n this.close();\n this.#focusTrigger();\n return;\n }\n\n if (event.key === 'Tab') {\n // Tab уводит фокус дальше по порядку — панель за ним не остаётся. Панель лежит в конце\n // страницы, и без возврата Tab ушёл бы с неё в никуда: фокус ставится на кнопку, а\n // умолчание клавиши не отменяется — браузер ведёт его от кнопки к следующему, как у\n // меню Material.\n this.close();\n this.#focusTrigger();\n return;\n }\n\n this.#keyManager?.onKeydown(event);\n }\n\n #focusTrigger(): void {\n this.trigger().elementRef.nativeElement.querySelector('button')?.focus();\n }\n\n #setOpen(open: boolean): void {\n if (open !== this.isOpen()) {\n if (!open) {\n this.#keyManager?.destroy();\n this.#keyManager = null;\n }\n if (open) {\n this.presetClasses.set(materialPresetClassesOf(this.#host.nativeElement));\n }\n this.isOpen.set(open);\n this.openedChange.emit(open);\n }\n }\n}\n","<rt-icon-button\n cdkOverlayOrigin\n qa-dataid=\"menu-trigger\"\n #trigger=\"cdkOverlayOrigin\"\n variant=\"ghost\"\n [size]=\"triggerSize()\"\n [icon]=\"icon()\"\n [ariaLabel]=\"ariaText()\"\n [tooltip]=\"ariaText()\"\n [disabled]=\"disabled()\"\n (clicked)=\"toggle($event)\" />\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayHasBackdrop\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPositions]=\"overlayPositions()\"\n [cdkConnectedOverlayPanelClass]=\"panelClasses()\"\n (backdropClick)=\"close()\"\n (attach)=\"onAttach()\"\n (detach)=\"close()\"\n (overlayKeydown)=\"onKeydown($event)\">\n <ng-container rtBlock=\"rt-menu\">\n <div rtElem=\"panel\" qa-dataid=\"menu-panel\" role=\"menu\" [rtMod]=\"{ size: size() }\" (rtMenuSelect)=\"onSelect()\">\n <ng-content />\n </div>\n </ng-container>\n</ng-template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-message.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/message/rt-message.component.ts","../../../projects/ui-kit-v2/src/lib/components/message/rt-message.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n computed,\n inject,\n input,\n output,\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { IRtTag } from '@rt-tools/ui-kit-v2/tag';\n\nconst BEM_BLOCK: string = 'rt-message';\n\n/**\n * Alert / banner для уведомлений с 6 severities и default icon mapping.\n *\n * Использует `role=\"alert\"` на корневом `<aside>` — screen reader озвучивает\n * содержимое сразу после маунта (полезно для inline-фидбэка форм типа\n * «Сохранено успешно» / «{{ assignError() }}»).\n *\n * Severity-палитра идентична `rt-tag` (`info` / `success` / `warning` / `danger` /\n * `secondary` / `neutral`); тип `IRtTag.Severity` переиспользуется напрямую, чтобы\n * не дублировать union. Цвета — через семантические `--rt-color-state-*` токены,\n * layout — через primitive `--rt-space-*` / `--rt-radius-*`. BEM-разметка через\n * директивы `rtBlock` / `rtElem` / `rtMod` из `@rt-tools/core`.\n *\n * Default icon по severity:\n * - `info` → `ico-info`\n * - `success` → `check`\n * - `warning` → `ico-warning`\n * - `danger` → `ico-error`\n * - `secondary` / `neutral` → `null` (icon не рендерится)\n *\n * Любой default можно переопределить через `[icon]=\"...\"`, либо явно отключить\n * передачей `[icon]=\"null\"` (override срабатывает только для truthy значений).\n */\n@Component({\n selector: 'rt-message',\n templateUrl: './rt-message.component.html',\n styleUrl: './rt-message.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtIconButtonComponent,\n RtIconComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtMessageComponent {\n /** Default icon mapping для каждой severity. `null` — иконка не рендерится. */\n readonly #severityIconDefaults: Readonly<Record<IRtTag.Severity, IRtIcon.Name | null>> = {\n info: 'ico-info',\n success: 'check',\n warning: 'ico-warning',\n danger: 'ico-error',\n secondary: null,\n neutral: null,\n };\n\n /**\n * Финальное имя иконки: явный override через `[icon]` имеет приоритет; иначе —\n * default по severity. Чтобы скрыть иконку у severity, у которой есть default,\n * передайте пустую строку как `[icon]` — она будет falsy и не «победит» default.\n * Полное отключение делается через severity `secondary` / `neutral`.\n */\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly effectiveIcon: Signal<IRtIcon.Name | null> = computed((): IRtIcon.Name | null => {\n if (this.hideIcon()) {\n return null;\n }\n const override: IRtIcon.Name | null = this.icon();\n if (override) {\n return override;\n }\n return this.#severityIconDefaults[this.severity()];\n });\n\n /** Семантическая палитра. По умолчанию `info` (синий info-banner). */\n public readonly severity: InputSignal<IRtTag.Severity> = input<IRtTag.Severity>('info');\n\n /** Override default-icon. `null` — использовать default по severity. */\n public readonly icon: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /** Полностью скрыть иконку (даже если у severity есть default) — только текст. */\n public readonly hideIcon: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Рендерит close-button справа (rt-icon-button ghost sm). */\n public readonly closable: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Эмиттится при клике на close-button (только если `closable=true`). */\n public readonly closed: OutputEmitterRef<void> = output<void>();\n\n protected onClose(): void {\n this.closed.emit();\n }\n}\n","<aside rtBlock=\"rt-message\" qa-dataid=\"message-alert\" role=\"alert\" [attr.data-severity]=\"severity()\" [rtMod]=\"{ severity: severity() }\">\n @if (effectiveIcon(); as iconName) {\n <rt-icon rtElem=\"icon\" [name]=\"iconName\" />\n }\n <div rtElem=\"body\" qa-dataid=\"message-body\">\n <ng-content />\n </div>\n @if (closable()) {\n <rt-icon-button\n rtElem=\"close\"\n qa-dataid=\"message-close\"\n icon=\"ico-close\"\n variant=\"ghost\"\n size=\"sm\"\n radius=\"full\"\n [ariaLabel]=\"t().uiClose\"\n (clicked)=\"onClose()\" />\n }\n</aside>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-message.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/message/rt-message.component.ts","../../../projects/ui-kit-v2/src/lib/components/message/rt-message.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n computed,\n inject,\n input,\n output,\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { IRtTag } from '@rt-tools/ui-kit-v2/tag';\n\nconst BEM_BLOCK: string = 'rt-message';\n\n/**\n * Alert / banner для уведомлений с 6 severities и default icon mapping.\n *\n * Использует `role=\"alert\"` на корневом `<aside>` — screen reader озвучивает\n * содержимое сразу после маунта (полезно для inline-фидбэка форм типа\n * «Сохранено успешно» / «{{ assignError() }}»).\n *\n * Severity-палитра идентична `rt-tag` (`info` / `success` / `warning` / `danger` /\n * `secondary` / `neutral`); тип `IRtTag.Severity` переиспользуется напрямую, чтобы\n * не дублировать union. Цвета — через семантические `--rt-color-state-*` токены,\n * layout — через primitive `--rt-space-*` / `--rt-radius-*`. BEM-разметка через\n * директивы `rtBlock` / `rtElem` / `rtMod` из `@rt-tools/core`.\n *\n * Default icon по severity:\n * - `info` → `ico-info`\n * - `success` → `check`\n * - `warning` → `ico-warning`\n * - `danger` → `ico-error`\n * - `secondary` / `neutral` → `null` (icon не рендерится)\n *\n * Любой default можно переопределить через `[icon]=\"...\"`, либо явно отключить\n * передачей `[icon]=\"null\"` (override срабатывает только для truthy значений).\n */\n@Component({\n selector: 'rt-message',\n templateUrl: './rt-message.component.html',\n styleUrl: './rt-message.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtIconButtonComponent,\n RtIconComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtMessageComponent {\n /** Default icon mapping для каждой severity. `null` — иконка не рендерится. */\n readonly #severityIconDefaults: Readonly<Record<IRtTag.Severity, IRtIcon.Name | null>> = {\n info: 'ico-info',\n success: 'check',\n warning: 'ico-warning',\n danger: 'ico-error',\n secondary: null,\n neutral: null,\n };\n\n /**\n * Финальное имя иконки: явный override через `[icon]` имеет приоритет; иначе —\n * default по severity. Чтобы скрыть иконку у severity, у которой есть default,\n * передайте пустую строку как `[icon]` — она будет falsy и не «победит» default.\n * Полное отключение делается через severity `secondary` / `neutral`.\n */\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly effectiveIcon: Signal<IRtIcon.Name | null> = computed((): IRtIcon.Name | null => {\n if (this.hideIcon()) {\n return null;\n }\n const override: IRtIcon.Name | null = this.icon();\n if (override) {\n return override;\n }\n return this.#severityIconDefaults[this.severity()];\n });\n\n /** Семантическая палитра. По умолчанию `info` (синий info-banner). */\n public readonly severity: InputSignal<IRtTag.Severity> = input<IRtTag.Severity>('info');\n\n /** Override default-icon. `null` — использовать default по severity. */\n public readonly icon: InputSignal<IRtIcon.Name | null> = input<IRtIcon.Name | null>(null);\n\n /** Полностью скрыть иконку (даже если у severity есть default) — только текст. */\n public readonly hideIcon: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Рендерит close-button справа (rt-icon-button ghost sm). */\n public readonly closable: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Эмиттится при клике на close-button (только если `closable=true`). */\n public readonly closed: OutputEmitterRef<void> = output<void>();\n\n protected onClose(): void {\n this.closed.emit();\n }\n}\n","<aside rtBlock=\"rt-message\" qa-dataid=\"message-alert\" role=\"alert\" [attr.data-severity]=\"severity()\" [rtMod]=\"{ severity: severity() }\">\n @if (effectiveIcon(); as iconName) {\n <rt-icon rtElem=\"icon\" [name]=\"iconName\" />\n }\n <div rtElem=\"body\" qa-dataid=\"message-body\">\n <ng-content />\n </div>\n @if (closable()) {\n <rt-icon-button\n rtElem=\"close\"\n qa-dataid=\"message-close\"\n icon=\"ico-close\"\n variant=\"ghost\"\n size=\"sm\"\n radius=\"full\"\n [ariaLabel]=\"t().uiClose\"\n (clicked)=\"onClose()\" />\n }\n</aside>\n"],"mappings":"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"}
|