From 37e722d7aee3eb6e404c0135770dca9c19b7539a Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Thu, 9 Apr 2026 19:30:30 +0700 Subject: [PATCH 1/3] =?UTF-8?q?menu:=20=D1=81=D1=82=D0=B8=D0=BB=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8F,=20=D1=81=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B8=D1=81=D1=8B,=20=D0=BE=D0=B1=D1=91=D1=80=D1=82=D0=BA?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/components/menu/menu.component.ts | 51 ++++ src/prime-preset/map-tokens.ts | 5 + src/prime-preset/tokens/components/menu.ts | 65 +++++ .../menu/examples/menu-basic.component.ts | 23 ++ .../menu/examples/menu-custom.component.ts | 35 +++ .../menu/examples/menu-grouped.component.ts | 35 +++ .../menu/examples/menu-popup.component.ts | 31 ++ .../examples/menu-with-icons.component.ts | 25 ++ src/stories/components/menu/menu.stories.ts | 276 ++++++++++++++++++ 9 files changed, 546 insertions(+) create mode 100644 src/lib/components/menu/menu.component.ts create mode 100644 src/prime-preset/tokens/components/menu.ts create mode 100644 src/stories/components/menu/examples/menu-basic.component.ts create mode 100644 src/stories/components/menu/examples/menu-custom.component.ts create mode 100644 src/stories/components/menu/examples/menu-grouped.component.ts create mode 100644 src/stories/components/menu/examples/menu-popup.component.ts create mode 100644 src/stories/components/menu/examples/menu-with-icons.component.ts create mode 100644 src/stories/components/menu/menu.stories.ts diff --git a/src/lib/components/menu/menu.component.ts b/src/lib/components/menu/menu.component.ts new file mode 100644 index 0000000..272cf36 --- /dev/null +++ b/src/lib/components/menu/menu.component.ts @@ -0,0 +1,51 @@ +import { Component, Input, ViewChild } from '@angular/core'; +import { Menu } from 'primeng/menu'; +import { MenuItem, PrimeTemplate } from 'primeng/api'; + +export interface MenuModel extends MenuItem { + caption?: string; +} + +@Component({ + selector: 'menu', + host: { style: 'display: contents' }, + standalone: true, + imports: [Menu, PrimeTemplate], + template: ` + + + + @if (item.icon) { + + } + @if ($any(item).caption) { + + } @else { + {{ item.label }} + } + + + + `, +}) +export class MenuComponent { + @ViewChild('menuRef') menuRef!: Menu; + + @Input() model: MenuModel[] = []; + @Input() popup = false; + + toggle(event: Event): void { + this.menuRef.toggle(event); + } +} diff --git a/src/prime-preset/map-tokens.ts b/src/prime-preset/map-tokens.ts index 3962758..0ce8e00 100644 --- a/src/prime-preset/map-tokens.ts +++ b/src/prime-preset/map-tokens.ts @@ -4,6 +4,7 @@ import type { AuraBaseDesignTokens } from '@primeuix/themes/aura/base'; import tokens from './tokens/tokens.json'; import { buttonCss } from './tokens/components/button'; +import { menuCss } from './tokens/components/menu'; const presetTokens: Preset = { primitive: tokens.primitive as unknown as AuraBaseDesignTokens['primitive'], @@ -14,6 +15,10 @@ const presetTokens: Preset = { ...(tokens.components.button as unknown as ComponentsDesignTokens['button']), css: buttonCss, }, + menu: { + ...(tokens.components.menu as unknown as ComponentsDesignTokens['menu']), + css: menuCss, + }, } as ComponentsDesignTokens, }; diff --git a/src/prime-preset/tokens/components/menu.ts b/src/prime-preset/tokens/components/menu.ts new file mode 100644 index 0000000..7722ffc --- /dev/null +++ b/src/prime-preset/tokens/components/menu.ts @@ -0,0 +1,65 @@ +export const menuCss = ({ dt }: { dt: (token: string) => string }): string => ` + .p-menu.p-component { + padding: ${dt('menu.extend.paddingY')} ${dt('menu.extend.paddingX')}; + } + + .p-menu .p-menu-item-content .p-menu-item-link { + font-family: ${dt('fonts.fontFamily.base')}; + font-size: ${dt('fonts.fontSize.base')}; + font-weight: ${dt('fonts.fontWeight.regular')}; + line-height: ${dt('fonts.lineHeight.250')}; + } + + .p-menu .p-menu-item-content .menu-item-label { + display: flex; + flex-direction: column; + gap: ${dt('menu.extend.extItem.caption.gap')}; + } + + .p-menu .p-menu-item-content .menu-item-caption { + font-family: ${dt('fonts.fontFamily.base')}; + font-size: ${dt('fonts.fontSize.sm')}; + font-weight: ${dt('fonts.fontWeight.regular')}; + color: ${dt('menu.colorScheme.light.extend.extItem.caption.color')}; + } + + .p-menu .p-menu-item:not(.p-disabled) .p-menu-item-content:hover, + .p-menu .p-menu-item:not(.p-disabled) .p-menu-item-content:hover .p-menu-item-link, + .p-menu .p-menu-item:not(.p-disabled) .p-menu-item-content:hover .p-menu-item-label { + color: ${dt('menu.colorScheme.light.item.color')}; + } + + .p-menu .p-menu-item.p-menuitem-checked > .p-menu-item-content, + .p-menu .p-menu-item.p-focus > .p-menu-item-content { + background: ${dt('menu.extend.extItem.activeBackground')}; + color: ${dt('menu.extend.extItem.activeColor')}; + } + + .p-menu .p-menu-item.p-menuitem-checked > .p-menu-item-content .p-menu-item-link, + .p-menu .p-menu-item.p-menuitem-checked > .p-menu-item-content .p-menu-item-label, + .p-menu .p-menu-item.p-focus > .p-menu-item-content .p-menu-item-link, + .p-menu .p-menu-item.p-focus > .p-menu-item-content .p-menu-item-label { + color: ${dt('menu.extend.extItem.activeColor')}; + } + + .p-menu .p-menu-item.p-menuitem-checked > .p-menu-item-content .p-menu-item-icon, + .p-menu .p-menu-item.p-focus > .p-menu-item-content .p-menu-item-icon { + color: ${dt('menu.colorScheme.light.extend.extItem.icon.activeColor')}; + } + + .p-menu .p-menu-item.p-menuitem-checked:not(.p-disabled) > .p-menu-item-content:hover { + background: ${dt('menu.extend.extItem.activeBackground')}; + color: ${dt('menu.extend.extItem.activeColor')}; + } + + .p-menu .p-menu-item.p-menuitem-checked:not(.p-disabled) > .p-menu-item-content:hover .p-menu-item-icon { + color: ${dt('menu.colorScheme.light.extend.extItem.icon.activeColor')}; + } + + .p-menu .p-menu-submenu-label { + text-transform: uppercase; + font-size: ${dt('fonts.fontSize.sm')}; + font-family: ${dt('fonts.fontFamily.heading')}; + line-height: ${dt('fonts.lineHeight.250')}; + } +`; diff --git a/src/stories/components/menu/examples/menu-basic.component.ts b/src/stories/components/menu/examples/menu-basic.component.ts new file mode 100644 index 0000000..e18fe08 --- /dev/null +++ b/src/stories/components/menu/examples/menu-basic.component.ts @@ -0,0 +1,23 @@ +import { Component } from '@angular/core'; +import { MenuComponent, MenuModel } from '../../../../lib/components/menu/menu.component'; + +const template = ` +
+ +
+`; + +@Component({ + selector: 'app-menu-basic', + standalone: true, + imports: [MenuComponent], + template, +}) +export class MenuBasicComponent { + items: MenuModel[] = [ + { label: 'Новый заказ' }, + { label: 'Поиск отправления' }, + { separator: true }, + { label: 'Экспорт' }, + ]; +} diff --git a/src/stories/components/menu/examples/menu-custom.component.ts b/src/stories/components/menu/examples/menu-custom.component.ts new file mode 100644 index 0000000..3d04f2b --- /dev/null +++ b/src/stories/components/menu/examples/menu-custom.component.ts @@ -0,0 +1,35 @@ +import { Component } from '@angular/core'; +import { MenuComponent, MenuModel } from '../../../../lib/components/menu/menu.component'; + +const template = ` +
+ +
+`; + +@Component({ + selector: 'app-menu-custom', + standalone: true, + imports: [MenuComponent], + template, +}) +export class MenuCustomComponent { + items: MenuModel[] = [ + { + label: 'Создать отправление', + caption: 'Оформление нового заказа', + icon: 'ti ti-file-plus', + }, + { + label: 'Найти посылку', + caption: 'Поиск по трек-номеру', + icon: 'ti ti-map-pin', + }, + { separator: true }, + { + label: 'Экспорт данных', + caption: 'Выгрузка в CSV или Excel', + icon: 'ti ti-download', + }, + ]; +} diff --git a/src/stories/components/menu/examples/menu-grouped.component.ts b/src/stories/components/menu/examples/menu-grouped.component.ts new file mode 100644 index 0000000..d1050f3 --- /dev/null +++ b/src/stories/components/menu/examples/menu-grouped.component.ts @@ -0,0 +1,35 @@ +import { Component } from '@angular/core'; +import { MenuComponent, MenuModel } from '../../../../lib/components/menu/menu.component'; + +const template = ` +
+ +
+`; + +@Component({ + selector: 'app-menu-grouped', + standalone: true, + imports: [MenuComponent], + template, +}) +export class MenuGroupedComponent { + items: MenuModel[] = [ + { + label: 'Заказы', + items: [ + { label: 'Новый заказ', icon: 'ti ti-plus' }, + { label: 'Список заказов', icon: 'ti ti-list' }, + { label: 'Архив', icon: 'ti ti-archive' }, + ], + }, + { + label: 'Отправления', + items: [ + { label: 'Создать накладную', icon: 'ti ti-file-invoice' }, + { label: 'Отследить посылку', icon: 'ti ti-map-pin' }, + { label: 'Отменить отправление', icon: 'ti ti-ban' }, + ], + }, + ]; +} diff --git a/src/stories/components/menu/examples/menu-popup.component.ts b/src/stories/components/menu/examples/menu-popup.component.ts new file mode 100644 index 0000000..2b18c79 --- /dev/null +++ b/src/stories/components/menu/examples/menu-popup.component.ts @@ -0,0 +1,31 @@ +import { Component, ViewChild } from '@angular/core'; +import { Button } from 'primeng/button'; +import { MenuComponent, MenuModel } from '../../../../lib/components/menu/menu.component'; + +const template = ` +
+ + +
+`; + +@Component({ + selector: 'app-menu-popup', + standalone: true, + imports: [MenuComponent, Button], + template, +}) +export class MenuPopupComponent { + @ViewChild('menuRef') menuRef!: MenuComponent; + + items: MenuModel[] = [ + { label: 'Создать отправление', icon: 'ti ti-file-plus' }, + { label: 'Найти по трек-номеру', icon: 'ti ti-search' }, + { separator: true }, + { label: 'Экспорт данных', icon: 'ti ti-download' }, + ]; + + toggle(event: Event): void { + this.menuRef.toggle(event); + } +} diff --git a/src/stories/components/menu/examples/menu-with-icons.component.ts b/src/stories/components/menu/examples/menu-with-icons.component.ts new file mode 100644 index 0000000..dbffd8d --- /dev/null +++ b/src/stories/components/menu/examples/menu-with-icons.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; +import { MenuComponent, MenuModel } from '../../../../lib/components/menu/menu.component'; + +const template = ` +
+ +
+`; + +@Component({ + selector: 'app-menu-with-icons', + standalone: true, + imports: [MenuComponent], + template, +}) +export class MenuWithIconsComponent { + items: MenuModel[] = [ + { label: 'Создать отправление', icon: 'ti ti-file-plus' }, + { label: 'Открыть список заказов', icon: 'ti ti-folder-open' }, + { label: 'Сохранить черновик', icon: 'ti ti-device-floppy' }, + { separator: true }, + { label: 'Распечатать накладную', icon: 'ti ti-printer' }, + { label: 'Экспорт данных', icon: 'ti ti-download' }, + ]; +} diff --git a/src/stories/components/menu/menu.stories.ts b/src/stories/components/menu/menu.stories.ts new file mode 100644 index 0000000..b226d21 --- /dev/null +++ b/src/stories/components/menu/menu.stories.ts @@ -0,0 +1,276 @@ +import { Meta, StoryObj, moduleMetadata } from '@storybook/angular'; +import { MenuComponent } from '../../../lib/components/menu/menu.component'; +import { MenuPopupComponent } from './examples/menu-popup.component'; +import { MenuBasicComponent } from './examples/menu-basic.component'; +import { MenuWithIconsComponent } from './examples/menu-with-icons.component'; +import { MenuGroupedComponent } from './examples/menu-grouped.component'; +import { MenuCustomComponent } from './examples/menu-custom.component'; + +const meta: Meta = { + title: 'Components/Menu/Menu', + component: MenuComponent, + tags: ['autodocs'], + parameters: { + docs: { + description: { + component: `Компонент навигационного меню. Поддерживает режим popup (по нажатию на триггер) и inline-отображение, группировку пунктов и пункты с описанием (caption). + +\`\`\`typescript +import { MenuComponent } from '@cdek-it/angular-ui-kit'; +\`\`\``, + }, + }, + designTokens: { prefix: '--p-menu' }, + }, + argTypes: { + model: { + control: false, + description: 'Массив пунктов меню.', + table: { + category: 'Props', + type: { summary: 'MenuModel[]' }, + }, + }, + popup: { + control: 'boolean', + description: 'Режим popup — меню отображается при вызове метода toggle().', + table: { + category: 'Props', + defaultValue: { summary: 'false' }, + type: { summary: 'boolean' }, + }, + }, + }, +}; + +export default meta; +type Story = StoryObj; + +// ── Popup ───────────────────────────────────────────────────────────────────── + +export const Default: Story = { + name: 'Popup', + decorators: [moduleMetadata({ imports: [MenuPopupComponent] })], + render: () => ({ template: `` }), + parameters: { + docs: { + description: { + story: 'Меню вызывается по нажатию на кнопку. Используйте метод toggle() для показа/скрытия.', + }, + source: { + language: 'ts', + code: ` +import { Component, ViewChild } from '@angular/core'; +import { Button } from 'primeng/button'; +import { MenuComponent, MenuModel } from '@cdek-it/angular-ui-kit'; + +@Component({ + selector: 'app-menu-popup', + standalone: true, + imports: [MenuComponent, Button], + template: \` + + + \`, +}) +export class MenuPopupComponent { + @ViewChild('menuRef') menuRef!: MenuComponent; + + items: MenuModel[] = [ + { label: 'Создать отправление', icon: 'ti ti-file-plus' }, + { label: 'Найти по трек-номеру', icon: 'ti ti-search' }, + { separator: true }, + { label: 'Экспорт данных', icon: 'ti ti-download' }, + ]; + + toggle(event: Event): void { + this.menuRef.toggle(event); + } +} + `, + }, + }, + }, +}; + +// ── Basic ───────────────────────────────────────────────────────────────────── + +export const Basic: Story = { + name: 'Basic', + decorators: [moduleMetadata({ imports: [MenuBasicComponent] })], + render: () => ({ template: `` }), + parameters: { + docs: { + description: { + story: 'Базовый вариант inline-меню без иконок.', + }, + source: { + language: 'ts', + code: ` +import { Component } from '@angular/core'; +import { MenuComponent, MenuModel } from '@cdek-it/angular-ui-kit'; + +@Component({ + selector: 'app-menu-basic', + standalone: true, + imports: [MenuComponent], + template: \` + + \`, +}) +export class MenuBasicComponent { + items: MenuModel[] = [ + { label: 'Новый заказ' }, + { label: 'Поиск отправления' }, + { separator: true }, + { label: 'Экспорт' }, + ]; +} + `, + }, + }, + }, +}; + +// ── WithIcons ───────────────────────────────────────────────────────────────── + +export const WithIcons: Story = { + name: 'WithIcons', + decorators: [moduleMetadata({ imports: [MenuWithIconsComponent] })], + render: () => ({ template: `` }), + parameters: { + docs: { + description: { + story: 'Пункты меню с иконками.', + }, + source: { + language: 'ts', + code: ` +import { Component } from '@angular/core'; +import { MenuComponent, MenuModel } from '@cdek-it/angular-ui-kit'; + +@Component({ + selector: 'app-menu-with-icons', + standalone: true, + imports: [MenuComponent], + template: \` + + \`, +}) +export class MenuWithIconsComponent { + items: MenuModel[] = [ + { label: 'Создать отправление', icon: 'ti ti-file-plus' }, + { label: 'Открыть список заказов', icon: 'ti ti-folder-open' }, + { label: 'Сохранить черновик', icon: 'ti ti-device-floppy' }, + { separator: true }, + { label: 'Распечатать накладную', icon: 'ti ti-printer' }, + { label: 'Экспорт данных', icon: 'ti ti-download' }, + ]; +} + `, + }, + }, + }, +}; + +// ── Grouped ─────────────────────────────────────────────────────────────────── + +export const Grouped: Story = { + name: 'Grouped', + decorators: [moduleMetadata({ imports: [MenuGroupedComponent] })], + render: () => ({ template: `` }), + parameters: { + docs: { + description: { + story: 'Группировка пунктов меню через label у родительского элемента.', + }, + source: { + language: 'ts', + code: ` +import { Component } from '@angular/core'; +import { MenuComponent, MenuModel } from '@cdek-it/angular-ui-kit'; + +@Component({ + selector: 'app-menu-grouped', + standalone: true, + imports: [MenuComponent], + template: \` + + \`, +}) +export class MenuGroupedComponent { + items: MenuModel[] = [ + { + label: 'Заказы', + items: [ + { label: 'Новый заказ', icon: 'ti ti-plus' }, + { label: 'Список заказов', icon: 'ti ti-list' }, + { label: 'Архив', icon: 'ti ti-archive' }, + ], + }, + { + label: 'Отправления', + items: [ + { label: 'Создать накладную', icon: 'ti ti-file-invoice' }, + { label: 'Отследить посылку', icon: 'ti ti-map-pin' }, + { label: 'Отменить отправление', icon: 'ti ti-ban' }, + ], + }, + ]; +} + `, + }, + }, + }, +}; + +// ── Custom ──────────────────────────────────────────────────────────────────── + +export const Custom: Story = { + name: 'Custom', + decorators: [moduleMetadata({ imports: [MenuCustomComponent] })], + render: () => ({ template: `` }), + parameters: { + docs: { + description: { + story: 'Пункты меню с иконкой и описанием (caption). Поле caption передаётся через MenuModel.', + }, + source: { + language: 'ts', + code: ` +import { Component } from '@angular/core'; +import { MenuComponent, MenuModel } from '@cdek-it/angular-ui-kit'; + +@Component({ + selector: 'app-menu-custom', + standalone: true, + imports: [MenuComponent], + template: \` + + \`, +}) +export class MenuCustomComponent { + items: MenuModel[] = [ + { + label: 'Создать отправление', + caption: 'Оформление нового заказа', + icon: 'ti ti-file-plus', + }, + { + label: 'Найти посылку', + caption: 'Поиск по трек-номеру', + icon: 'ti ti-map-pin', + }, + { separator: true }, + { + label: 'Экспорт данных', + caption: 'Выгрузка в CSV или Excel', + icon: 'ti ti-download', + }, + ]; +} + `, + }, + }, + }, +}; From 7593a1cdce9ce5ceeed17f9338c107a7ecd4dc49 Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Thu, 9 Apr 2026 19:57:42 +0700 Subject: [PATCH 2/3] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=20=D1=81=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D1=8F=D0=BD=D0=B8=D1=8F=20=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=B8=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BF=D1=83=D0=BD=D0=BA?= =?UTF-8?q?=D1=82=D0=B0=20=D0=BC=D0=B5=D0=BD=D1=8E=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D0=BD=D0=B0=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/prime-preset/tokens/components/menu.ts | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/prime-preset/tokens/components/menu.ts b/src/prime-preset/tokens/components/menu.ts index 7722ffc..2ef5fcf 100644 --- a/src/prime-preset/tokens/components/menu.ts +++ b/src/prime-preset/tokens/components/menu.ts @@ -3,11 +3,11 @@ export const menuCss = ({ dt }: { dt: (token: string) => string }): string => ` padding: ${dt('menu.extend.paddingY')} ${dt('menu.extend.paddingX')}; } - .p-menu .p-menu-item-content .p-menu-item-link { + .p-menu .p-menu-item-content .p-menu-item-link .p-menu-item-label { font-family: ${dt('fonts.fontFamily.base')}; - font-size: ${dt('fonts.fontSize.base')}; + font-size: ${dt('fonts.fontSize.300')}; font-weight: ${dt('fonts.fontWeight.regular')}; - line-height: ${dt('fonts.lineHeight.250')}; + line-height: ${dt('fonts.lineHeight.400')}; } .p-menu .p-menu-item-content .menu-item-label { @@ -18,15 +18,17 @@ export const menuCss = ({ dt }: { dt: (token: string) => string }): string => ` .p-menu .p-menu-item-content .menu-item-caption { font-family: ${dt('fonts.fontFamily.base')}; - font-size: ${dt('fonts.fontSize.sm')}; + font-size: ${dt('fonts.fontSize.200')}; font-weight: ${dt('fonts.fontWeight.regular')}; color: ${dt('menu.colorScheme.light.extend.extItem.caption.color')}; } .p-menu .p-menu-item:not(.p-disabled) .p-menu-item-content:hover, .p-menu .p-menu-item:not(.p-disabled) .p-menu-item-content:hover .p-menu-item-link, - .p-menu .p-menu-item:not(.p-disabled) .p-menu-item-content:hover .p-menu-item-label { - color: ${dt('menu.colorScheme.light.item.color')}; + .p-menu .p-menu-item:not(.p-disabled) .p-menu-item-content:hover .p-menu-item-label, + .p-menu .p-menu-item:not(.p-disabled) .p-menu-item-content:hover .p-menu-item-icon { + background: ${dt('menu.colorScheme.light.item.focusBackground')}; + color: ${dt('menu.colorScheme.light.item.focusColor')}; } .p-menu .p-menu-item.p-menuitem-checked > .p-menu-item-content, @@ -48,18 +50,18 @@ export const menuCss = ({ dt }: { dt: (token: string) => string }): string => ` } .p-menu .p-menu-item.p-menuitem-checked:not(.p-disabled) > .p-menu-item-content:hover { - background: ${dt('menu.extend.extItem.activeBackground')}; - color: ${dt('menu.extend.extItem.activeColor')}; + background: ${dt('menu.colorScheme.light.item.focusBackground')}; + color: ${dt('menu.colorScheme.light.item.focusColor')}; } .p-menu .p-menu-item.p-menuitem-checked:not(.p-disabled) > .p-menu-item-content:hover .p-menu-item-icon { - color: ${dt('menu.colorScheme.light.extend.extItem.icon.activeColor')}; + color: ${dt('menu.colorScheme.light.item.focusColor')}; } .p-menu .p-menu-submenu-label { text-transform: uppercase; - font-size: ${dt('fonts.fontSize.sm')}; + font-size: ${dt('fonts.fontSize.200')}; font-family: ${dt('fonts.fontFamily.heading')}; - line-height: ${dt('fonts.lineHeight.250')}; + line-height: ${dt('fonts.lineHeight.400')}; } `; From 7896268e4d8dc53bae61073173fa24d71061a510 Mon Sep 17 00:00:00 2001 From: Danil Khaliulin Date: Mon, 13 Apr 2026 18:55:47 +0700 Subject: [PATCH 3/3] =?UTF-8?q?menu:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20itemTemplate=20=D0=B4=D0=BB=D1=8F=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=BE=D0=BC=D0=B8=D0=B7=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D0=B8=20=D1=8D=D0=BB=D0=B5=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=20?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/components/menu/menu.component.ts | 52 +++++++++++++---------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/lib/components/menu/menu.component.ts b/src/lib/components/menu/menu.component.ts index 272cf36..a692f69 100644 --- a/src/lib/components/menu/menu.component.ts +++ b/src/lib/components/menu/menu.component.ts @@ -1,4 +1,5 @@ -import { Component, Input, ViewChild } from '@angular/core'; +import { Component, Input, TemplateRef, ViewChild } from '@angular/core'; +import { NgTemplateOutlet } from '@angular/common'; import { Menu } from 'primeng/menu'; import { MenuItem, PrimeTemplate } from 'primeng/api'; @@ -10,31 +11,37 @@ export interface MenuModel extends MenuItem { selector: 'menu', host: { style: 'display: contents' }, standalone: true, - imports: [Menu, PrimeTemplate], + imports: [Menu, PrimeTemplate, NgTemplateOutlet], template: ` - - @if (item.icon) { - - } - @if ($any(item).caption) { - - } @else { - {{ item.label }} - } - + } + + } `, @@ -44,6 +51,7 @@ export class MenuComponent { @Input() model: MenuModel[] = []; @Input() popup = false; + @Input() itemTemplate: TemplateRef | null = null; toggle(event: Event): void { this.menuRef.toggle(event);