@sdcorejs/angular 19.2.0 → 19.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/api-contract-builder/index.d.ts +8 -0
- package/components/api-contract-builder/src/api-contract-builder.component.d.ts +123 -0
- package/components/api-contract-builder/src/api-contract.configuration.d.ts +41 -0
- package/components/api-contract-builder/src/api-contract.expression.d.ts +43 -0
- package/components/api-contract-builder/src/api-contract.model.d.ts +167 -0
- package/components/api-contract-builder/src/api-contract.samples.d.ts +25 -0
- package/components/api-contract-builder/src/api-contract.schema.d.ts +126 -0
- package/components/api-contract-builder/src/api-contract.serializer.d.ts +17 -0
- package/components/api-contract-builder/src/api-contract.validation.d.ts +12 -0
- package/components/api-contract-builder/src/components/api-contract-diagnostic-list.component.d.ts +18 -0
- package/components/api-contract-builder/src/components/api-contract-node-drawer.component.d.ts +130 -0
- package/components/api-contract-builder/src/components/api-contract-node-editor.component.d.ts +35 -0
- package/components/api-contract-builder/src/components/api-contract-node-summary.component.d.ts +41 -0
- package/components/api-contract-builder/src/components/api-contract-record-editor.component.d.ts +36 -0
- package/components/api-contract-builder/src/components/api-contract-source-editor.component.d.ts +86 -0
- package/components/api-contract-builder/src/components/api-contract-suggestion.model.d.ts +17 -0
- package/components/badge/src/badge.component.d.ts +1 -0
- package/components/index.d.ts +1 -0
- package/components/section/src/section.component.d.ts +2 -0
- package/fesm2022/sdcorejs-angular-components-api-contract-builder.mjs +3411 -0
- package/fesm2022/sdcorejs-angular-components-api-contract-builder.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-components-badge.mjs +14 -2
- package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-operator.mjs +2 -2
- package/fesm2022/sdcorejs-angular-components-operator.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-section.mjs +22 -5
- package/fesm2022/sdcorejs-angular-components-section.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-table.mjs +14 -13
- package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components.mjs +1 -0
- package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-i18n.mjs +405 -0
- package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-icon.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-layout.mjs +15 -5
- package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
- package/i18n/src/en.d.ts +80 -0
- package/modules/layout/components/sidebar-v1/components/sidebar/sidebar.component.d.ts +8 -0
- package/package.json +13 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdcorejs-angular-modules-icon.mjs","sources":["../../../projects/sdcorejs-angular/modules/icon/src/icon.model.ts","../../../projects/sdcorejs-angular/modules/icon/src/icon.provider.ts","../../../projects/sdcorejs-angular/modules/icon/src/icon.component.ts","../../../projects/sdcorejs-angular/modules/icon/sdcorejs-angular-modules-icon.ts"],"sourcesContent":["import { type LucideConfig, type LucideIcon, type LucideIconData } from '@lucide/angular';\nimport { type Size } from '@sdcorejs/utils/models';\nimport { DefaultSdIconSet, type SdIconSet, type SdMaterialIconSet } from '@sdcorejs/angular/utilities/models';\n\n/**\n * Chọn renderer icon chính cho `SdIcon`.\n *\n * Material dùng đúng tên font set để tránh thêm mapping nội bộ; `lucide` chuyển sang renderer SVG của `@lucide/angular`.\n */\nexport type { SdIconSet, SdMaterialIconSet };\n\n/** @deprecated Use `SdIconSet` instead. */\nexport type SdIconFontSet = SdIconSet;\n\n/**\n * Một icon Lucide có thể đăng ký bằng class icon Angular hoặc dữ liệu path thuần.\n */\nexport type SdLucideIconRegistration = LucideIcon | LucideIconData;\n\n/**\n * Danh sách đăng ký Lucide cho provider, hỗ trợ cả array và object map để app có thể giữ cấu trúc import riêng.\n */\nexport type SdLucideIconRegistrations = SdLucideIconRegistration[] | Record<string, SdLucideIconRegistration>;\n\n/**\n * Cấu hình app-level cho `SdIcon`.\n *\n * Các alias tách riêng theo renderer để app có thể giữ tên Material trong template trong lúc chuyển dần sang Lucide.\n */\nexport interface ISdIconConfiguration {\n /** Default icon font set when component does not pass `fontSet`. */\n defaultFontSet?: SdIconSet;\n /** Alias áp dụng khi renderer hiện tại là Material. */\n materialAliases?: Record<string, string>;\n /** Alias áp dụng khi renderer hiện tại là Lucide. */\n lucideAliases?: Record<string, string>;\n /** Cấu hình stroke toàn cục cho Lucide SVG. */\n lucideConfig?: Partial<LucideConfig>;\n /** Icon Lucide cần đăng ký vào `@lucide/angular`. */\n lucideIcons?: SdLucideIconRegistrations;\n}\n\n/**\n * Cấu hình đã resolve đầy đủ để component không phải tự xử lý fallback nhiều lần.\n */\nexport type ISdIconResolvedConfiguration = Required<Omit<ISdIconConfiguration, 'lucideIcons'>>;\n\n/**\n * Quy đổi token `Size` chung của SDCoreJS sang pixel cho icon.\n */\nexport const SD_ICON_SIZE_MAP: Record<Size, number> = {\n sm: 16,\n md: 20,\n lg: 24,\n};\n\n/**\n * Alias mặc định giúp template giữ tên Material trong khi renderer có thể là Lucide.\n */\nexport const SD_DEFAULT_LUCIDE_ALIASES: Record<string, string> = {\n account_balance: 'landmark',\n account_circle: 'circle-user-round',\n account_tree: 'workflow',\n add: 'plus',\n add_circle: 'circle-plus',\n arrow_back: 'arrow-left',\n arrow_downward: 'arrow-down',\n arrow_drop_down: 'chevron-down',\n arrow_drop_up: 'chevron-up',\n arrow_forward: 'arrow-right',\n arrow_upward: 'arrow-up',\n bar_chart: 'chart-column',\n block: 'ban',\n bookmark_add: 'bookmark-plus',\n bookmark_border: 'bookmark',\n build: 'wrench',\n calendar_month: 'calendar-days',\n campaign: 'megaphone',\n cancel: 'circle-x',\n celebration: 'party-popper',\n chevron_left: 'chevron-left',\n chevron_right: 'chevron-right',\n check: 'check',\n check_circle: 'circle-check',\n close: 'x',\n cloud_download: 'cloud-download',\n contact_page: 'contact',\n content_copy: 'copy',\n dashboard: 'layout-dashboard',\n delete: 'trash-2',\n delete_sweep: 'trash-2',\n description: 'file-text',\n done: 'check',\n done_all: 'check-check',\n drag_indicator: 'grip-vertical',\n edit: 'pencil',\n edit_note: 'file-pen-line',\n error: 'circle-alert',\n error_outline: 'circle-alert',\n expand_less: 'chevron-up',\n expand_more: 'chevron-down',\n filter_alt: 'list-filter',\n file_download: 'download',\n file_upload: 'upload',\n fiber_manual_record: 'circle',\n fit_screen: 'scan',\n folder: 'folder',\n first_page: 'chevrons-left',\n format_indent_decrease: 'list-indent-decrease',\n format_indent_increase: 'list-indent-increase',\n fullscreen: 'maximize',\n fullscreen_exit: 'minimize',\n get_app: 'download',\n group: 'users',\n hourglass_empty: 'hourglass',\n hourglass_top: 'hourglass',\n image: 'image',\n image_not_supported: 'image-off',\n info: 'info',\n info_outline: 'info',\n insert_drive_file: 'file',\n inventory_2: 'package',\n keyboard_arrow_down: 'chevron-down',\n keyboard_arrow_left: 'chevron-left',\n keyboard_arrow_right: 'chevron-right',\n keyboard_arrow_up: 'chevron-up',\n last_page: 'chevrons-right',\n list: 'list',\n local_offer: 'tag',\n lock: 'lock-keyhole',\n lock_outline: 'lock-keyhole',\n login: 'log-in',\n logout: 'log-out',\n match_case: 'case-sensitive',\n menu: 'menu',\n menu_open: 'panel-left-close',\n more_horiz: 'ellipsis',\n more_vert: 'ellipsis-vertical',\n notifications: 'bell',\n open_in_new: 'external-link',\n open_in_full: 'maximize',\n person: 'user',\n picture_as_pdf: 'file-text',\n play_arrow: 'play',\n print: 'printer',\n refresh: 'refresh-cw',\n remove: 'minus',\n remove_circle: 'circle-minus',\n restart_alt: 'rotate-ccw',\n rotate_right: 'rotate-cw',\n search_off: 'search-x',\n settings: 'settings',\n share: 'share-2',\n smart_toy: 'bot',\n space_dashboard: 'layout-dashboard',\n storefront: 'store',\n swap_horiz: 'arrow-left-right',\n table_chart: 'table',\n table_view: 'table-2',\n task_alt: 'circle-check',\n text_fields: 'text',\n today: 'calendar',\n unfold_more: 'chevrons-up-down',\n upload_file: 'upload',\n view_carousel: 'gallery-horizontal',\n view_day: 'panel-top',\n view_list: 'list',\n visibility: 'eye',\n visibility_off: 'eye-off',\n warning: 'triangle-alert',\n warning_amber: 'triangle-alert',\n widgets: 'layout-grid',\n zoom_in: 'zoom-in',\n};\n\n/**\n * Alias mac dinh giup template dung ten Lucide van render duoc khi quay ve Material font.\n */\nexport const SD_DEFAULT_MATERIAL_ALIASES: Record<string, string> = {\n 'arrow-down': 'arrow_downward',\n 'arrow-left': 'arrow_back',\n 'arrow-right': 'arrow_forward',\n 'arrow-up': 'arrow_upward',\n 'calendar-days': 'calendar_month',\n 'case-sensitive': 'match_case',\n 'chart-column': 'bar_chart',\n 'check-check': 'done_all',\n 'chevron-down': 'expand_more',\n 'chevron-left': 'chevron_left',\n 'chevron-right': 'chevron_right',\n 'chevron-up': 'expand_less',\n 'chevrons-left': 'first_page',\n 'chevrons-right': 'last_page',\n 'circle-alert': 'error',\n 'circle-check': 'check_circle',\n 'circle-minus': 'remove_circle',\n 'circle-plus': 'add_circle',\n 'circle-user-round': 'account_circle',\n 'circle-x': 'cancel',\n 'cloud-download': 'cloud_download',\n 'file-down': 'file_download',\n 'file-pen-line': 'edit_note',\n 'file-text': 'description',\n 'file-up': 'upload_file',\n 'gallery-horizontal': 'view_carousel',\n get_app: 'file_download',\n 'grip-vertical': 'drag_indicator',\n 'layout-dashboard': 'dashboard',\n 'layout-grid': 'widgets',\n 'list-indent-decrease': 'format_indent_decrease',\n 'list-indent-increase': 'format_indent_increase',\n 'list-filter': 'filter_alt',\n 'lock-keyhole': 'lock',\n 'log-in': 'login',\n 'log-out': 'logout',\n 'panel-left-close': 'menu_open',\n 'party-popper': 'celebration',\n 'refresh-cw': 'refresh',\n 'rotate-ccw': 'restart_alt',\n 'rotate-cw': 'rotate_right',\n 'share-2': 'share',\n 'square-pen': 'edit',\n 'trash-2': 'delete',\n 'triangle-alert': 'warning',\n 'zoom-in': 'zoom_in',\n ban: 'block',\n contact: 'contact_page',\n copy: 'content_copy',\n circle: 'fiber_manual_record',\n download: 'file_download',\n ellipsis: 'more_horiz',\n 'ellipsis-vertical': 'more_vert',\n error_outline: 'error',\n eye: 'visibility',\n 'eye-off': 'visibility_off',\n file: 'insert_drive_file',\n folder: 'folder',\n fullscreen: 'fullscreen',\n hourglass: 'hourglass_top',\n image: 'image',\n 'image-off': 'image_not_supported',\n info_outline: 'info',\n landmark: 'account_balance',\n list: 'list',\n lock_outline: 'lock',\n maximize: 'fullscreen',\n megaphone: 'campaign',\n menu: 'menu',\n minimize: 'fullscreen_exit',\n minus: 'remove',\n package: 'inventory_2',\n pencil: 'edit',\n plus: 'add',\n play: 'play_arrow',\n printer: 'print',\n scan: 'fit_screen',\n 'search-x': 'search_off',\n settings: 'settings',\n 'save-all': 'done_all',\n store: 'storefront',\n tag: 'local_offer',\n text: 'text_fields',\n upload: 'upload_file',\n user: 'person',\n users: 'group',\n workflow: 'account_tree',\n wrench: 'build',\n x: 'close',\n};\n\n/**\n * Cấu hình mặc định của Core UI icon.\n *\n * `material-icons-outlined` được giữ làm mặc định để không đổi visual của các component Material hiện có.\n */\nexport const SD_ICON_DEFAULT_CONFIG: ISdIconResolvedConfiguration = {\n defaultFontSet: DefaultSdIconSet,\n materialAliases: SD_DEFAULT_MATERIAL_ALIASES,\n lucideAliases: SD_DEFAULT_LUCIDE_ALIASES,\n lucideConfig: {},\n};\n","import { InjectionToken, makeEnvironmentProviders, type EnvironmentProviders, type Provider } from '@angular/core';\nimport { provideLucideConfig, provideLucideIcons } from '@lucide/angular';\nimport {\n SD_ICON_DEFAULT_CONFIG,\n type ISdIconConfiguration,\n type ISdIconResolvedConfiguration,\n type SdLucideIconRegistration,\n type SdLucideIconRegistrations,\n} from './icon.model';\n\n/**\n * Injection token chứa cấu hình icon đã resolve cho toàn bộ app.\n *\n * Token có factory mặc định để `SdIcon` vẫn chạy khi app chưa gọi `provideSdIcon`.\n */\nexport const SD_ICON_CONFIGURATION = new InjectionToken<ISdIconResolvedConfiguration>('SD_ICON_CONFIGURATION', {\n providedIn: 'root',\n factory: () => resolveSdIconConfig(),\n});\n\n/**\n * Đăng ký cấu hình icon Core UI ở app-level.\n *\n * Provider này gom cả cấu hình `SdIcon` và registry của `@lucide/angular` để consumer chỉ cần gọi một hàm.\n *\n * @param config - cấu hình app-level cho Material/Lucide icon.\n * @returns environment providers dùng được trong `ApplicationConfig.providers`.\n */\nexport function provideSdIcon(config: ISdIconConfiguration = {}): EnvironmentProviders {\n const providers: Provider[] = [\n {\n provide: SD_ICON_CONFIGURATION,\n useValue: resolveSdIconConfig(config),\n },\n ];\n\n if (config.lucideConfig) {\n providers.push(provideLucideConfig(config.lucideConfig));\n }\n\n const lucideIcons = normalizeSdLucideIcons(config.lucideIcons);\n if (lucideIcons.length) {\n // why: @lucide/angular chỉ render dynamic icon đã được đăng ký trước qua provider\n providers.push(provideLucideIcons(...lucideIcons));\n }\n\n return makeEnvironmentProviders(providers);\n}\n\n/**\n * Resolve cấu hình `SdIcon` thành object đầy đủ, không còn field optional.\n *\n * Alias mặc định đứng trước để app có thể override từng key mà không phải copy toàn bộ bảng alias.\n *\n * @param config - cấu hình rời rạc từ consumer hoặc mặc định rỗng.\n * @returns cấu hình đầy đủ dùng trực tiếp trong component.\n */\nexport function resolveSdIconConfig(config: ISdIconConfiguration = {}): ISdIconResolvedConfiguration {\n return {\n defaultFontSet: config.defaultFontSet ?? SD_ICON_DEFAULT_CONFIG.defaultFontSet,\n materialAliases: {\n ...SD_ICON_DEFAULT_CONFIG.materialAliases,\n ...config.materialAliases,\n },\n lucideAliases: {\n ...SD_ICON_DEFAULT_CONFIG.lucideAliases,\n ...config.lucideAliases,\n },\n lucideConfig: {\n ...SD_ICON_DEFAULT_CONFIG.lucideConfig,\n ...config.lucideConfig,\n },\n };\n}\n\n/**\n * Chuẩn hóa nhiều kiểu khai báo Lucide icon về array cho `provideLucideIcons`.\n *\n * @param registrations - array hoặc object map icon Lucide từ consumer.\n * @returns danh sách icon Lucide đã sẵn sàng để spread vào provider của Lucide.\n */\nexport function normalizeSdLucideIcons(registrations?: SdLucideIconRegistrations): SdLucideIconRegistration[] {\n if (!registrations) {\n return [];\n }\n\n return Array.isArray(registrations) ? registrations : Object.values(registrations);\n}\n","import { ChangeDetectionStrategy, Component, booleanAttribute, computed, inject, input } from '@angular/core';\nimport { MatIconModule } from '@angular/material/icon';\nimport { LucideDynamicIcon } from '@lucide/angular';\nimport { type Size } from '@sdcorejs/utils/models';\nimport { DefaultSdMaterialIconSet } from '@sdcorejs/angular/utilities/models';\nimport { SD_ICON_SIZE_MAP, type SdIconSet, type SdMaterialIconSet } from './icon.model';\nimport { SD_ICON_CONFIGURATION } from './icon.provider';\n\n/**\n * Facade icon dùng chung cho Core UI.\n *\n * Component này giữ template app theo tên icon ổn định, còn renderer có thể đổi giữa Material font và Lucide SVG qua provider hoặc input.\n */\n@Component({\n selector: 'sd-icon',\n standalone: true,\n imports: [MatIconModule, LucideDynamicIcon],\n template: `\n @if (resolvedName(); as _name) {\n @if (resolvedFontSet() === 'lucide') {\n <svg\n class=\"sd-icon__svg\"\n [lucideIcon]=\"_name\"\n [size]=\"resolvedSize()\"\n [strokeWidth]=\"resolvedStrokeWidth()\"\n [absoluteStrokeWidth]=\"resolvedAbsoluteStrokeWidth()\"\n [title]=\"ariaLabel()\"></svg>\n } @else {\n <mat-icon\n class=\"sd-icon__material\"\n [fontSet]=\"resolvedMaterialFontSet()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-hidden]=\"ariaLabel() ? null : 'true'\">\n {{ _name }}\n </mat-icon>\n }\n }\n `,\n styles: [\n `\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--sd-icon-size);\n height: var(--sd-icon-size);\n min-width: var(--sd-icon-size);\n color: currentColor;\n font-size: var(--sd-icon-size);\n line-height: 1;\n vertical-align: middle;\n flex: 0 0 auto;\n }\n\n /* why: base CSS của Material nhắm thẳng .mat-icon con trong menu/list/button item và ép\n width/height 24px + margin-right 12px lên nó. Glyph khi đó to hơn host --sd-icon-size,\n bị overflow hidden xén mất và lệch sang trái — lỗi \"icon bị cắt đè\" trong mat-menu. Selector\n đi qua :host (0,3,0) để luôn thắng .mat-mdc-menu-item .mat-icon (0,2,0) bất kể thứ tự nạp\n stylesheet; khoảng cách với nhãn để menu/list lo ở cấp host, không nhét vào trong glyph. */\n :host .sd-icon__material {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n margin: 0;\n color: currentColor;\n font-size: inherit;\n line-height: 1;\n overflow: hidden;\n }\n\n .sd-icon__svg {\n display: block;\n width: 100%;\n height: 100%;\n color: currentColor;\n stroke: currentColor;\n flex: 0 0 auto;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'sd-icon',\n '[class.sd-icon--material]': 'resolvedFontSet() !== \"lucide\"',\n '[class.sd-icon--material-icons-outlined]': 'resolvedFontSet() === \"material-icons-outlined\"',\n '[class.sd-icon--lucide]': 'resolvedFontSet() === \"lucide\"',\n '[style.--sd-icon-size]': 'resolvedCssSize()',\n '[attr.aria-label]': 'ariaLabel()',\n '[attr.aria-hidden]': 'ariaLabel() ? null : \"true\"',\n '[attr.color]': 'color()',\n },\n})\nexport class SdIcon {\n // why: InjectionToken cho phép app đổi default/alias mà không buộc từng component nhận thêm input cấu hình\n private readonly config = inject(SD_ICON_CONFIGURATION);\n\n /**\n * Tên icon theo namespace hiện tại.\n *\n * Khi `set` là `lucide`, tên này sẽ đi qua alias để app có thể tiếp tục dùng tên Material trong template.\n */\n name = input<string | undefined, string | undefined | null>(undefined, {\n transform: coerceStringInput,\n });\n\n fontIcon = input<string | undefined, string | undefined | null>(undefined, {\n transform: coerceStringInput,\n });\n\n color = input<string | undefined, string | undefined | null>(undefined, {\n transform: coerceStringInput,\n });\n\n /**\n * Renderer icon của riêng instance này.\n *\n * Deprecated alias for `fontSet`.\n */\n set = input<SdIconSet | undefined, SdIconSet | undefined | null>(undefined, {\n transform: value => value ?? undefined,\n });\n\n /**\n * Escape hatch cho Material icon font set.\n *\n * Prefer this input for both Material font families and Lucide SVG icons.\n */\n fontSet = input<SdIconSet | undefined, SdIconSet | undefined | null>(undefined, {\n transform: value => value ?? undefined,\n });\n\n /**\n * Kích thước icon theo token SDCoreJS hoặc CSS size tùy biến.\n *\n * Token `sm | md | lg` giữ icon đồng bộ với các component Core UI; CSS string xử lý các ngoại lệ layout.\n */\n size = input<Size | (string & {}), Size | (string & {}) | undefined | null>('md', {\n transform: value => value ?? 'md',\n });\n\n /**\n * Độ dày stroke riêng cho Lucide SVG.\n *\n * Bỏ trống để nhận giá trị từ `lucideConfig` app-level.\n */\n strokeWidth = input<number | string | undefined, number | string | undefined | null>(undefined, {\n transform: value => value ?? undefined,\n });\n\n /**\n * Giữ stroke width tuyệt đối cho Lucide khi SVG đổi kích thước.\n *\n * Input này đi qua `booleanAttribute` để hỗ trợ cả attribute trần trong template.\n */\n absoluteStrokeWidth = input<boolean | undefined, boolean | string | undefined | null>(undefined, {\n transform: value => (value == null ? undefined : booleanAttribute(value)),\n });\n\n /**\n * Nhãn truy cập cho icon có ý nghĩa.\n *\n * Khi không có nhãn, component tự đánh dấu decorative bằng `aria-hidden`.\n */\n ariaLabel = input<string | undefined, string | undefined | null>(undefined, {\n transform: coerceStringInput,\n });\n\n /**\n * Set icon cuối cùng sau khi áp dụng input và provider.\n *\n * @returns renderer hiện tại của component.\n */\n resolvedFontSet = computed<SdIconSet>(() => this.fontSet() ?? this.set() ?? this.config.defaultFontSet);\n\n /** @deprecated Use `resolvedFontSet` instead. */\n resolvedSet = computed<SdIconSet>(() => this.resolvedFontSet());\n\n /**\n * Tên icon cuối cùng theo renderer hiện tại.\n *\n * @returns tên icon đã áp alias nếu renderer yêu cầu.\n */\n resolvedName = computed(() => {\n const name = this.name() ?? this.fontIcon();\n if (!name) {\n return undefined;\n }\n\n const aliases = this.resolvedFontSet() === 'lucide' ? this.config.lucideAliases : this.config.materialAliases;\n return aliases[name] ?? name;\n });\n\n /**\n * Font set Material cuối cùng.\n *\n * @returns font set dùng cho `mat-icon`; với Lucide trả về fallback Material để computed luôn có type ổn định.\n */\n resolvedMaterialFontSet = computed<SdMaterialIconSet>(() => {\n const fontSet = this.resolvedFontSet();\n return fontSet === 'lucide' ? DefaultSdMaterialIconSet : fontSet;\n });\n\n /**\n * Kích thước runtime cho renderer hiện tại.\n *\n * @returns số pixel cho token chuẩn hoặc CSS string nguyên bản cho custom size.\n */\n resolvedSize = computed<number | string>(() => {\n const size = this.size();\n return isSizeToken(size) ? SD_ICON_SIZE_MAP[size] : size;\n });\n\n /**\n * Kích thước CSS cuối cùng cho host element.\n *\n * @returns CSS length dùng cho custom property `--sd-icon-size`.\n */\n resolvedCssSize = computed(() => {\n const size = this.resolvedSize();\n return typeof size === 'number' ? `${size}px` : size;\n });\n\n /**\n * Stroke width cuối cùng cho Lucide SVG.\n *\n * @returns giá trị input instance hoặc fallback từ provider.\n */\n resolvedStrokeWidth = computed(() => this.strokeWidth() ?? this.config.lucideConfig.strokeWidth);\n\n /**\n * Absolute stroke width cuối cùng cho Lucide SVG.\n *\n * @returns giá trị input instance hoặc fallback từ provider.\n */\n resolvedAbsoluteStrokeWidth = computed(() => this.absoluteStrokeWidth() ?? this.config.lucideConfig.absoluteStrokeWidth);\n}\n\n/**\n * Chuẩn hóa string input rỗng thành `undefined` để fallback provider hoạt động nhất quán.\n *\n * @param value - giá trị string từ input Angular.\n * @returns string đã trim hoặc `undefined`.\n */\nfunction coerceStringInput(value: string | undefined | null): string | undefined {\n const trimmed = value?.trim();\n return trimmed || undefined;\n}\n\n/**\n * Kiểm tra một size có phải token chuẩn của SDCoreJS hay không.\n *\n * @param value - token size hoặc CSS size string.\n * @returns `true` khi value có mapping pixel trong `SD_ICON_SIZE_MAP`.\n */\nfunction isSizeToken(value: Size | (string & {})): value is Size {\n return value in SD_ICON_SIZE_MAP;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sdcorejs-angular-modules-icon.mjs","sources":["../../../projects/sdcorejs-angular/modules/icon/src/icon.model.ts","../../../projects/sdcorejs-angular/modules/icon/src/icon.provider.ts","../../../projects/sdcorejs-angular/modules/icon/src/icon.component.ts","../../../projects/sdcorejs-angular/modules/icon/sdcorejs-angular-modules-icon.ts"],"sourcesContent":["import { type LucideConfig, type LucideIcon, type LucideIconData } from '@lucide/angular';\nimport { type Size } from '@sdcorejs/utils/models';\nimport { DefaultSdIconSet, type SdIconSet, type SdMaterialIconSet } from '@sdcorejs/angular/utilities/models';\n\n/**\n * Chọn renderer icon chính cho `SdIcon`.\n *\n * Material dùng đúng tên font set để tránh thêm mapping nội bộ; `lucide` chuyển sang renderer SVG của `@lucide/angular`.\n */\nexport type { SdIconSet, SdMaterialIconSet };\n\n/** @deprecated Use `SdIconSet` instead. */\nexport type SdIconFontSet = SdIconSet;\n\n/**\n * Một icon Lucide có thể đăng ký bằng class icon Angular hoặc dữ liệu path thuần.\n */\nexport type SdLucideIconRegistration = LucideIcon | LucideIconData;\n\n/**\n * Danh sách đăng ký Lucide cho provider, hỗ trợ cả array và object map để app có thể giữ cấu trúc import riêng.\n */\nexport type SdLucideIconRegistrations = SdLucideIconRegistration[] | Record<string, SdLucideIconRegistration>;\n\n/**\n * Cấu hình app-level cho `SdIcon`.\n *\n * Các alias tách riêng theo renderer để app có thể giữ tên Material trong template trong lúc chuyển dần sang Lucide.\n */\nexport interface ISdIconConfiguration {\n /** Default icon font set when component does not pass `fontSet`. */\n defaultFontSet?: SdIconSet;\n /** Alias áp dụng khi renderer hiện tại là Material. */\n materialAliases?: Record<string, string>;\n /** Alias áp dụng khi renderer hiện tại là Lucide. */\n lucideAliases?: Record<string, string>;\n /** Cấu hình stroke toàn cục cho Lucide SVG. */\n lucideConfig?: Partial<LucideConfig>;\n /** Icon Lucide cần đăng ký vào `@lucide/angular`. */\n lucideIcons?: SdLucideIconRegistrations;\n}\n\n/**\n * Cấu hình đã resolve đầy đủ để component không phải tự xử lý fallback nhiều lần.\n */\nexport type ISdIconResolvedConfiguration = Required<Omit<ISdIconConfiguration, 'lucideIcons'>>;\n\n/**\n * Quy đổi token `Size` chung của SDCoreJS sang pixel cho icon.\n */\nexport const SD_ICON_SIZE_MAP: Record<Size, number> = {\n sm: 16,\n md: 20,\n lg: 24,\n};\n\n/**\n * Alias mặc định giúp template giữ tên Material trong khi renderer có thể là Lucide.\n */\nexport const SD_DEFAULT_LUCIDE_ALIASES: Record<string, string> = {\n account_balance: 'landmark',\n account_circle: 'circle-user-round',\n account_tree: 'workflow',\n add: 'plus',\n add_circle: 'circle-plus',\n arrow_back: 'arrow-left',\n arrow_downward: 'arrow-down',\n arrow_drop_down: 'chevron-down',\n arrow_drop_up: 'chevron-up',\n arrow_forward: 'arrow-right',\n arrow_upward: 'arrow-up',\n bar_chart: 'chart-column',\n block: 'ban',\n bookmark_add: 'bookmark-plus',\n bookmark_border: 'bookmark',\n build: 'wrench',\n calendar_month: 'calendar-days',\n campaign: 'megaphone',\n cancel: 'circle-x',\n celebration: 'party-popper',\n chevron_left: 'chevron-left',\n chevron_right: 'chevron-right',\n check: 'check',\n check_circle: 'circle-check',\n close: 'x',\n cloud_download: 'cloud-download',\n contact_page: 'contact',\n content_copy: 'copy',\n dashboard: 'layout-dashboard',\n delete: 'trash-2',\n delete_sweep: 'trash-2',\n description: 'file-text',\n done: 'check',\n done_all: 'check-check',\n drag_indicator: 'grip-vertical',\n edit: 'pencil',\n edit_note: 'file-pen-line',\n error: 'circle-alert',\n error_outline: 'circle-alert',\n expand_less: 'chevron-up',\n expand_more: 'chevron-down',\n filter_alt: 'list-filter',\n file_download: 'download',\n file_upload: 'upload',\n fiber_manual_record: 'circle',\n fit_screen: 'scan',\n folder: 'folder',\n first_page: 'chevrons-left',\n format_indent_decrease: 'list-indent-decrease',\n format_indent_increase: 'list-indent-increase',\n fullscreen: 'maximize',\n fullscreen_exit: 'minimize',\n get_app: 'download',\n group: 'users',\n hourglass_empty: 'hourglass',\n hourglass_top: 'hourglass',\n image: 'image',\n image_not_supported: 'image-off',\n info: 'info',\n info_outline: 'info',\n insert_drive_file: 'file',\n inventory_2: 'package',\n keyboard_arrow_down: 'chevron-down',\n keyboard_arrow_left: 'chevron-left',\n keyboard_arrow_right: 'chevron-right',\n keyboard_arrow_up: 'chevron-up',\n last_page: 'chevrons-right',\n list: 'list',\n local_offer: 'tag',\n lock: 'lock-keyhole',\n lock_outline: 'lock-keyhole',\n login: 'log-in',\n logout: 'log-out',\n match_case: 'case-sensitive',\n menu: 'menu',\n menu_open: 'panel-left-close',\n more_horiz: 'ellipsis',\n more_vert: 'ellipsis-vertical',\n notifications: 'bell',\n open_in_new: 'external-link',\n open_in_full: 'maximize',\n person: 'user',\n picture_as_pdf: 'file-text',\n play_arrow: 'play',\n print: 'printer',\n refresh: 'refresh-cw',\n remove: 'minus',\n remove_circle: 'circle-minus',\n restart_alt: 'rotate-ccw',\n rotate_right: 'rotate-cw',\n search_off: 'search-x',\n settings: 'settings',\n share: 'share-2',\n smart_toy: 'bot',\n space_dashboard: 'layout-dashboard',\n storefront: 'store',\n swap_horiz: 'arrow-left-right',\n table_chart: 'table',\n table_view: 'table-2',\n task_alt: 'circle-check',\n text_fields: 'text',\n today: 'calendar',\n unfold_more: 'chevrons-up-down',\n upload_file: 'upload',\n view_carousel: 'gallery-horizontal',\n view_day: 'panel-top',\n view_list: 'list',\n visibility: 'eye',\n visibility_off: 'eye-off',\n warning: 'triangle-alert',\n warning_amber: 'triangle-alert',\n widgets: 'layout-grid',\n zoom_in: 'zoom-in',\n};\n\n/**\n * Alias mac dinh giup template dung ten Lucide van render duoc khi quay ve Material font.\n */\nexport const SD_DEFAULT_MATERIAL_ALIASES: Record<string, string> = {\n 'arrow-down': 'arrow_downward',\n 'arrow-left': 'arrow_back',\n 'arrow-right': 'arrow_forward',\n 'arrow-up': 'arrow_upward',\n 'calendar-days': 'calendar_month',\n 'case-sensitive': 'match_case',\n 'chart-column': 'bar_chart',\n 'check-check': 'done_all',\n 'chevron-down': 'expand_more',\n 'chevron-left': 'chevron_left',\n 'chevron-right': 'chevron_right',\n 'chevron-up': 'expand_less',\n 'chevrons-left': 'first_page',\n 'chevrons-right': 'last_page',\n 'circle-alert': 'error',\n 'circle-check': 'check_circle',\n 'circle-minus': 'remove_circle',\n 'circle-plus': 'add_circle',\n 'circle-user-round': 'account_circle',\n 'circle-x': 'cancel',\n 'cloud-download': 'cloud_download',\n 'file-down': 'file_download',\n 'file-pen-line': 'edit_note',\n 'file-text': 'description',\n 'file-up': 'upload_file',\n 'gallery-horizontal': 'view_carousel',\n get_app: 'file_download',\n 'grip-vertical': 'drag_indicator',\n 'layout-dashboard': 'dashboard',\n 'layout-grid': 'widgets',\n 'list-indent-decrease': 'format_indent_decrease',\n 'list-indent-increase': 'format_indent_increase',\n 'list-filter': 'filter_alt',\n 'lock-keyhole': 'lock',\n 'log-in': 'login',\n 'log-out': 'logout',\n 'panel-left-close': 'menu_open',\n 'party-popper': 'celebration',\n 'refresh-cw': 'refresh',\n 'rotate-ccw': 'restart_alt',\n 'rotate-cw': 'rotate_right',\n 'share-2': 'share',\n 'square-pen': 'edit',\n 'trash-2': 'delete',\n 'triangle-alert': 'warning',\n 'zoom-in': 'zoom_in',\n ban: 'block',\n contact: 'contact_page',\n copy: 'content_copy',\n circle: 'fiber_manual_record',\n download: 'file_download',\n ellipsis: 'more_horiz',\n 'ellipsis-vertical': 'more_vert',\n error_outline: 'error',\n eye: 'visibility',\n 'eye-off': 'visibility_off',\n file: 'insert_drive_file',\n folder: 'folder',\n fullscreen: 'fullscreen',\n hourglass: 'hourglass_top',\n image: 'image',\n 'image-off': 'image_not_supported',\n info_outline: 'info',\n landmark: 'account_balance',\n list: 'list',\n lock_outline: 'lock',\n maximize: 'fullscreen',\n megaphone: 'campaign',\n menu: 'menu',\n minimize: 'fullscreen_exit',\n minus: 'remove',\n package: 'inventory_2',\n pencil: 'edit',\n plus: 'add',\n play: 'play_arrow',\n printer: 'print',\n scan: 'fit_screen',\n 'search-x': 'search_off',\n settings: 'settings',\n 'save-all': 'done_all',\n store: 'storefront',\n tag: 'local_offer',\n text: 'text_fields',\n upload: 'upload_file',\n user: 'person',\n users: 'group',\n workflow: 'account_tree',\n wrench: 'build',\n x: 'close',\n};\n\n/**\n * Cấu hình mặc định của Core UI icon.\n *\n * `material-icons-outlined` được giữ làm mặc định để không đổi visual của các component Material hiện có.\n */\nexport const SD_ICON_DEFAULT_CONFIG: ISdIconResolvedConfiguration = {\n defaultFontSet: DefaultSdIconSet,\n materialAliases: SD_DEFAULT_MATERIAL_ALIASES,\n lucideAliases: SD_DEFAULT_LUCIDE_ALIASES,\n lucideConfig: {},\n};\n","import { InjectionToken, makeEnvironmentProviders, type EnvironmentProviders, type Provider } from '@angular/core';\nimport { provideLucideConfig, provideLucideIcons } from '@lucide/angular';\nimport {\n SD_ICON_DEFAULT_CONFIG,\n type ISdIconConfiguration,\n type ISdIconResolvedConfiguration,\n type SdLucideIconRegistration,\n type SdLucideIconRegistrations,\n} from './icon.model';\n\n/**\n * Injection token chứa cấu hình icon đã resolve cho toàn bộ app.\n *\n * Token có factory mặc định để `SdIcon` vẫn chạy khi app chưa gọi `provideSdIcon`.\n */\nexport const SD_ICON_CONFIGURATION = new InjectionToken<ISdIconResolvedConfiguration>('SD_ICON_CONFIGURATION', {\n providedIn: 'root',\n factory: () => resolveSdIconConfig(),\n});\n\n/**\n * Đăng ký cấu hình icon Core UI ở app-level.\n *\n * Provider này gom cả cấu hình `SdIcon` và registry của `@lucide/angular` để consumer chỉ cần gọi một hàm.\n *\n * @param config - cấu hình app-level cho Material/Lucide icon.\n * @returns environment providers dùng được trong `ApplicationConfig.providers`.\n */\nexport function provideSdIcon(config: ISdIconConfiguration = {}): EnvironmentProviders {\n const providers: Provider[] = [\n {\n provide: SD_ICON_CONFIGURATION,\n useValue: resolveSdIconConfig(config),\n },\n ];\n\n if (config.lucideConfig) {\n providers.push(provideLucideConfig(config.lucideConfig));\n }\n\n const lucideIcons = normalizeSdLucideIcons(config.lucideIcons);\n if (lucideIcons.length) {\n // why: @lucide/angular chỉ render dynamic icon đã được đăng ký trước qua provider\n providers.push(provideLucideIcons(...lucideIcons));\n }\n\n return makeEnvironmentProviders(providers);\n}\n\n/**\n * Resolve cấu hình `SdIcon` thành object đầy đủ, không còn field optional.\n *\n * Alias mặc định đứng trước để app có thể override từng key mà không phải copy toàn bộ bảng alias.\n *\n * @param config - cấu hình rời rạc từ consumer hoặc mặc định rỗng.\n * @returns cấu hình đầy đủ dùng trực tiếp trong component.\n */\nexport function resolveSdIconConfig(config: ISdIconConfiguration = {}): ISdIconResolvedConfiguration {\n return {\n defaultFontSet: config.defaultFontSet ?? SD_ICON_DEFAULT_CONFIG.defaultFontSet,\n materialAliases: {\n ...SD_ICON_DEFAULT_CONFIG.materialAliases,\n ...config.materialAliases,\n },\n lucideAliases: {\n ...SD_ICON_DEFAULT_CONFIG.lucideAliases,\n ...config.lucideAliases,\n },\n lucideConfig: {\n ...SD_ICON_DEFAULT_CONFIG.lucideConfig,\n ...config.lucideConfig,\n },\n };\n}\n\n/**\n * Chuẩn hóa nhiều kiểu khai báo Lucide icon về array cho `provideLucideIcons`.\n *\n * @param registrations - array hoặc object map icon Lucide từ consumer.\n * @returns danh sách icon Lucide đã sẵn sàng để spread vào provider của Lucide.\n */\nexport function normalizeSdLucideIcons(registrations?: SdLucideIconRegistrations): SdLucideIconRegistration[] {\n if (!registrations) {\n return [];\n }\n\n return Array.isArray(registrations) ? registrations : Object.values(registrations);\n}\n","import { ChangeDetectionStrategy, Component, booleanAttribute, computed, inject, input } from '@angular/core';\nimport { MatIconModule } from '@angular/material/icon';\nimport { LucideDynamicIcon } from '@lucide/angular';\nimport { type Size } from '@sdcorejs/utils/models';\nimport { DefaultSdMaterialIconSet } from '@sdcorejs/angular/utilities/models';\nimport { SD_ICON_SIZE_MAP, type SdIconSet, type SdMaterialIconSet } from './icon.model';\nimport { SD_ICON_CONFIGURATION } from './icon.provider';\n\n/**\n * Facade icon dùng chung cho Core UI.\n *\n * Component này giữ template app theo tên icon ổn định, còn renderer có thể đổi giữa Material font và Lucide SVG qua provider hoặc input.\n */\n@Component({\n selector: 'sd-icon',\n standalone: true,\n imports: [MatIconModule, LucideDynamicIcon],\n template: `\n @if (resolvedName(); as _name) {\n @if (resolvedFontSet() === 'lucide') {\n <svg\n class=\"sd-icon__svg\"\n [lucideIcon]=\"_name\"\n [size]=\"resolvedSize()\"\n [strokeWidth]=\"resolvedStrokeWidth()\"\n [absoluteStrokeWidth]=\"resolvedAbsoluteStrokeWidth()\"\n [title]=\"ariaLabel()\"></svg>\n } @else {\n <mat-icon\n class=\"sd-icon__material\"\n [fontSet]=\"resolvedMaterialFontSet()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-hidden]=\"ariaLabel() ? null : 'true'\">\n {{ _name }}\n </mat-icon>\n }\n }\n `,\n // why `:host .sd-icon__material` tồn tại: base CSS của Material nhắm thẳng .mat-icon con trong\n // menu/list/button item và ép width/height 24px + margin-right 12px lên nó. Glyph khi đó to hơn host\n // --sd-icon-size, bị overflow hidden xén mất và lệch sang trái — lỗi \"icon bị cắt đè\" trong mat-menu.\n // Selector đi qua :host (0,3,0) để luôn thắng .mat-mdc-menu-item .mat-icon (0,2,0) bất kể thứ tự nạp\n // stylesheet; khoảng cách với nhãn để menu/list lo ở cấp host, không nhét vào trong glyph.\n // Comment để ngoài `styles`: `check:i18n` quét chuỗi tiếng Việt trong template và style.\n styles: [\n `\n :host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--sd-icon-size);\n height: var(--sd-icon-size);\n min-width: var(--sd-icon-size);\n color: currentColor;\n font-size: var(--sd-icon-size);\n line-height: 1;\n vertical-align: middle;\n flex: 0 0 auto;\n }\n\n :host .sd-icon__material {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n margin: 0;\n color: currentColor;\n font-size: inherit;\n line-height: 1;\n overflow: hidden;\n }\n\n .sd-icon__svg {\n display: block;\n width: 100%;\n height: 100%;\n color: currentColor;\n stroke: currentColor;\n flex: 0 0 auto;\n }\n `,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'sd-icon',\n '[class.sd-icon--material]': 'resolvedFontSet() !== \"lucide\"',\n '[class.sd-icon--material-icons-outlined]': 'resolvedFontSet() === \"material-icons-outlined\"',\n '[class.sd-icon--lucide]': 'resolvedFontSet() === \"lucide\"',\n '[style.--sd-icon-size]': 'resolvedCssSize()',\n '[attr.aria-label]': 'ariaLabel()',\n '[attr.aria-hidden]': 'ariaLabel() ? null : \"true\"',\n '[attr.color]': 'color()',\n },\n})\nexport class SdIcon {\n // why: InjectionToken cho phép app đổi default/alias mà không buộc từng component nhận thêm input cấu hình\n private readonly config = inject(SD_ICON_CONFIGURATION);\n\n /**\n * Tên icon theo namespace hiện tại.\n *\n * Khi `set` là `lucide`, tên này sẽ đi qua alias để app có thể tiếp tục dùng tên Material trong template.\n */\n name = input<string | undefined, string | undefined | null>(undefined, {\n transform: coerceStringInput,\n });\n\n fontIcon = input<string | undefined, string | undefined | null>(undefined, {\n transform: coerceStringInput,\n });\n\n color = input<string | undefined, string | undefined | null>(undefined, {\n transform: coerceStringInput,\n });\n\n /**\n * Renderer icon của riêng instance này.\n *\n * Deprecated alias for `fontSet`.\n */\n set = input<SdIconSet | undefined, SdIconSet | undefined | null>(undefined, {\n transform: value => value ?? undefined,\n });\n\n /**\n * Escape hatch cho Material icon font set.\n *\n * Prefer this input for both Material font families and Lucide SVG icons.\n */\n fontSet = input<SdIconSet | undefined, SdIconSet | undefined | null>(undefined, {\n transform: value => value ?? undefined,\n });\n\n /**\n * Kích thước icon theo token SDCoreJS hoặc CSS size tùy biến.\n *\n * Token `sm | md | lg` giữ icon đồng bộ với các component Core UI; CSS string xử lý các ngoại lệ layout.\n */\n size = input<Size | (string & {}), Size | (string & {}) | undefined | null>('md', {\n transform: value => value ?? 'md',\n });\n\n /**\n * Độ dày stroke riêng cho Lucide SVG.\n *\n * Bỏ trống để nhận giá trị từ `lucideConfig` app-level.\n */\n strokeWidth = input<number | string | undefined, number | string | undefined | null>(undefined, {\n transform: value => value ?? undefined,\n });\n\n /**\n * Giữ stroke width tuyệt đối cho Lucide khi SVG đổi kích thước.\n *\n * Input này đi qua `booleanAttribute` để hỗ trợ cả attribute trần trong template.\n */\n absoluteStrokeWidth = input<boolean | undefined, boolean | string | undefined | null>(undefined, {\n transform: value => (value == null ? undefined : booleanAttribute(value)),\n });\n\n /**\n * Nhãn truy cập cho icon có ý nghĩa.\n *\n * Khi không có nhãn, component tự đánh dấu decorative bằng `aria-hidden`.\n */\n ariaLabel = input<string | undefined, string | undefined | null>(undefined, {\n transform: coerceStringInput,\n });\n\n /**\n * Set icon cuối cùng sau khi áp dụng input và provider.\n *\n * @returns renderer hiện tại của component.\n */\n resolvedFontSet = computed<SdIconSet>(() => this.fontSet() ?? this.set() ?? this.config.defaultFontSet);\n\n /** @deprecated Use `resolvedFontSet` instead. */\n resolvedSet = computed<SdIconSet>(() => this.resolvedFontSet());\n\n /**\n * Tên icon cuối cùng theo renderer hiện tại.\n *\n * @returns tên icon đã áp alias nếu renderer yêu cầu.\n */\n resolvedName = computed(() => {\n const name = this.name() ?? this.fontIcon();\n if (!name) {\n return undefined;\n }\n\n const aliases = this.resolvedFontSet() === 'lucide' ? this.config.lucideAliases : this.config.materialAliases;\n return aliases[name] ?? name;\n });\n\n /**\n * Font set Material cuối cùng.\n *\n * @returns font set dùng cho `mat-icon`; với Lucide trả về fallback Material để computed luôn có type ổn định.\n */\n resolvedMaterialFontSet = computed<SdMaterialIconSet>(() => {\n const fontSet = this.resolvedFontSet();\n return fontSet === 'lucide' ? DefaultSdMaterialIconSet : fontSet;\n });\n\n /**\n * Kích thước runtime cho renderer hiện tại.\n *\n * @returns số pixel cho token chuẩn hoặc CSS string nguyên bản cho custom size.\n */\n resolvedSize = computed<number | string>(() => {\n const size = this.size();\n return isSizeToken(size) ? SD_ICON_SIZE_MAP[size] : size;\n });\n\n /**\n * Kích thước CSS cuối cùng cho host element.\n *\n * @returns CSS length dùng cho custom property `--sd-icon-size`.\n */\n resolvedCssSize = computed(() => {\n const size = this.resolvedSize();\n return typeof size === 'number' ? `${size}px` : size;\n });\n\n /**\n * Stroke width cuối cùng cho Lucide SVG.\n *\n * @returns giá trị input instance hoặc fallback từ provider.\n */\n resolvedStrokeWidth = computed(() => this.strokeWidth() ?? this.config.lucideConfig.strokeWidth);\n\n /**\n * Absolute stroke width cuối cùng cho Lucide SVG.\n *\n * @returns giá trị input instance hoặc fallback từ provider.\n */\n resolvedAbsoluteStrokeWidth = computed(() => this.absoluteStrokeWidth() ?? this.config.lucideConfig.absoluteStrokeWidth);\n}\n\n/**\n * Chuẩn hóa string input rỗng thành `undefined` để fallback provider hoạt động nhất quán.\n *\n * @param value - giá trị string từ input Angular.\n * @returns string đã trim hoặc `undefined`.\n */\nfunction coerceStringInput(value: string | undefined | null): string | undefined {\n const trimmed = value?.trim();\n return trimmed || undefined;\n}\n\n/**\n * Kiểm tra một size có phải token chuẩn của SDCoreJS hay không.\n *\n * @param value - token size hoặc CSS size string.\n * @returns `true` khi value có mapping pixel trong `SD_ICON_SIZE_MAP`.\n */\nfunction isSizeToken(value: Size | (string & {})): value is Size {\n return value in SD_ICON_SIZE_MAP;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1020,8 +1020,18 @@ class SdSidebarV1Panel {
|
|
|
1020
1020
|
onToggleMenuNode = (menu) => {
|
|
1021
1021
|
this.treeControl.toggle(menu);
|
|
1022
1022
|
};
|
|
1023
|
-
|
|
1024
|
-
|
|
1023
|
+
menuNodeHref = (node) => {
|
|
1024
|
+
if (sdIsExternalHttpUrl(node.path))
|
|
1025
|
+
return node.path;
|
|
1026
|
+
return this.#router.serializeUrl(this.#router.createUrlTree([node.path.split('?')[0]], {
|
|
1027
|
+
queryParams: node.queryParams ?? {},
|
|
1028
|
+
}));
|
|
1029
|
+
};
|
|
1030
|
+
onMenuNodeClick = (event, node) => {
|
|
1031
|
+
event.preventDefault();
|
|
1032
|
+
this.navigate({ path: node.path, queryParams: node.queryParams ?? {} });
|
|
1033
|
+
};
|
|
1034
|
+
// why: giữ public keyboard handler cũ để không làm thay đổi declaration API.
|
|
1025
1035
|
onMenuNodeKeydown = (event, node) => {
|
|
1026
1036
|
if (event.target !== event.currentTarget)
|
|
1027
1037
|
return;
|
|
@@ -1029,7 +1039,7 @@ class SdSidebarV1Panel {
|
|
|
1029
1039
|
event.preventDefault();
|
|
1030
1040
|
this.navigate({ path: node.path, queryParams: node.queryParams ?? {} });
|
|
1031
1041
|
};
|
|
1032
|
-
// why:
|
|
1042
|
+
// why: giữ public keyboard handler cũ; native branch button now owns keyboard activation.
|
|
1033
1043
|
onToggleMenuNodeKeydown = (event, menu) => {
|
|
1034
1044
|
if (event.target !== event.currentTarget)
|
|
1035
1045
|
return;
|
|
@@ -1474,7 +1484,7 @@ class SdSidebarV1Panel {
|
|
|
1474
1484
|
return count;
|
|
1475
1485
|
};
|
|
1476
1486
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdSidebarV1Panel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1477
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdSidebarV1Panel, isStandalone: true, selector: "sd-sidebar-v1-panel", inputs: { isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: true, transformFunction: null }, menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: true, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null }, isMobile: { classPropertyName: "isMobile", publicName: "isMobile", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expandSideBar: "expandSideBar", popupUserMenuClosed: "popupUserMenuClosed", popupUserMenuOpened: "popupUserMenuOpened", showSideBar: "showSideBar" }, ngImport: i0, template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div class=\"wrapper\" [style.height]=\"isMobile() ? '100dvh' : '100%'\">\n <div class=\"c-header\">\n <div class=\"c-logo\">\n <a href=\"javascript:;\" [attr.aria-label]=\"'core.module.layout.home.tab-name' | sdTranslate\" (click)=\"openHomePage()\">\n @if (logoUrl(); as _logoUrl) {\n <img alt=\"\" [src]=\"_logoUrl\" />\n } @else {\n <sd-icon name=\"apps\"></sd-icon>\n }\n </a>\n </div>\n <div class=\"c-title-menu-group\" [class.d-none]=\"!isShowSidebar()\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && pinnedMenuGroup().children?.length) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, pinnedMenuGroup())\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, pinnedMenuGroup())\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'core.module.layout.sidebar.pinned' | sdTranslate\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <sd-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive()\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #44474f)',\n backgroundColor: isPinnedMenuGroupActive()\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\"\n name=\"push_pin\"></sd-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <sd-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #44474f)',\n backgroundColor:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\"\n [name]=\"nodeMenuGroup.icon || 'widgets'\"></sd-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\" [class.d-none]=\"!isShowSidebar()\" [attr.inert]=\"!isShowSidebar() ? '' : null\">\n @if (totalMenuInMenusByGroup() > 10) {\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\n <sd-input\n size=\"sm\"\n [placeholder]=\"'core.module.layout.sidebar.search' | sdTranslate\"\n [autoId]=\"'layout-v1-menu-search'\"\n [model]=\"searchText()\"\n (sdChange)=\"onFilterSearchText($event)\">\n <ng-template sdSuffixDef>\n @if (searchText()) {\n <sd-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\" name=\"cancel\"></sd-icon>\n } @else {\n <sd-icon class=\"c-search-prefix-icon search\" name=\"search\"></sd-icon>\n }\n </ng-template>\n </sd-input>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <li\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor:\n (currentPath() | menuFocus: node) ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)' : 'transparent',\n }\">\n <!-- why: role=button KH\u00D4NG \u0111\u01B0\u1EE3c b\u1ECDc ph\u1EA7n t\u1EED t\u01B0\u01A1ng t\u00E1c kh\u00E1c (n\u00FAt ghim b\u00EAn trong) \u2014\n AT coi c\u1EA3 c\u1EE5m l\u00E0 M\u1ED8T n\u00FAt v\u00E0 n\u00FAt ghim bi\u1EBFn m\u1EA5t kh\u1ECFi accessibility tree. Nay\n role=button + tabindex + Enter/Space + aria-current + (click) n\u1EB1m C\u00D9NG tr\u00EAn\n ph\u1EA7n TI\u00CAU \u0110\u1EC0, n\u00FAt ghim l\u00E0 sibling \u0111\u1ED9c l\u1EADp; c\u1EA3 hai \u0111\u1EC1u focus \u0111\u01B0\u1EE3c. -->\n <div class=\"c-menu-node-description\" [class.d-none]=\"!isShowSidebar()\">\n <div\n class=\"c-menu-node-description-content\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-current]=\"(currentPath() | menuFocus: node) ? 'page' : null\"\n (click)=\"navigate(node)\"\n (keydown.enter)=\"onMenuNodeKeydown($event, node)\"\n (keydown.space)=\"onMenuNodeKeydown($event, node)\"\n [ngStyle]=\"{\n color:\n (currentPath() | menuFocus: node)\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text, #1a1b1f)',\n }\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n\n <!-- why: n\u00FAt ghim tr\u01B0\u1EDBc \u0111\u00E2y l\u00E0 <sd-icon (click)> \u2014 custom element kh\u00F4ng nh\u1EADn\n focus b\u00E0n ph\u00EDm v\u00E0 kh\u00F4ng c\u00F3 t\u00EAn kh\u1EA3 truy c\u1EADp, n\u00EAn kh\u00F4ng ghim \u0111\u01B0\u1EE3c b\u1EB1ng ph\u00EDm.\n \u0110\u1ED5i sang <button type=\"button\"> + aria-pressed, gi\u1ED1ng pattern \u0111\u00E3 d\u00F9ng \u1EDF\n `shared/menu-tree`. -->\n @if (_sidebar?.pin?.enabled) {\n <button\n type=\"button\"\n class=\"c-menu-node-description-icon-pin\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"\n isPinnedNode(node) || isHoveredNode(node) ? sidebar().brandColor || 'var(--sd-primary, #005cbb)' : null\n \"\n [attr.aria-pressed]=\"isPinnedNode(node)\"\n [attr.aria-label]=\"\n (isPinnedNode(node) ? 'core.module.layout.menu.unpin' : 'core.module.layout.menu.pin')\n | sdTranslate: { title: node.title }\n \"\n (click)=\"onTogglePin($event, node)\">\n <sd-icon name=\"push_pin\"></sd-icon>\n </button>\n }\n </div>\n </li>\n </mat-nested-tree-node>\n\n <!-- why: b\u1ECF aria-hidden=\"true\" \u2014 n\u00F3 \u1EA9n TO\u00C0N B\u1ED8 nh\u00E1nh menu c\u00F3 con (ti\u00EAu \u0111\u1EC1 nh\u00F3m l\u1EABn\n m\u1ECDi m\u1EE5c con b\u00EAn trong) kh\u1ECFi accessibility tree. -->\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node }\">\n <li>\n <div\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <!-- why: nh\u00E1nh c\u00F3 con l\u00E0 n\u00FAt G\u1EACP/M\u1EDE th\u1EADt nh\u01B0ng tr\u01B0\u1EDBc \u0111\u00E2y ch\u1EC9 c\u00F3 (click) v\u00E0\n kh\u00F4ng khai tr\u1EA1ng th\u00E1i. Nay role=button + tabindex + aria-expanded +\n Enter/Space. -->\n <div\n [class.d-none]=\"!isShowSidebar()\"\n class=\"c-menu-node-description\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-expanded]=\"treeControl.isExpanded(node)\"\n (click)=\"onToggleMenuNode(node)\"\n (keydown.enter)=\"onToggleMenuNodeKeydown($event, node)\"\n (keydown.space)=\"onToggleMenuNodeKeydown($event, node)\">\n <div\n class=\"c-menu-node-description-content\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n <sd-icon\n class=\"c-menu-node-description-icon-expand\"\n [name]=\"treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down'\"></sd-icon>\n </div>\n </div>\n </div>\n <ul class=\"p-0\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </ul>\n </li>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobile()\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </lib-layout-user>\n </div>\n\n <div class=\"c-vertical\"></div>\n </div>\n}\n", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host ::ng-deep .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:16px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:32px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:48px!important}ul,li{margin-top:0;margin-bottom:0;list-style-type:none}.wrapper{display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{display:flex;align-items:center;height:52px;padding:3px;gap:16px}.wrapper .c-header .c-logo{display:flex;justify-content:center;align-items:center;width:52px;height:52px}.wrapper .c-header .c-logo a{display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:var(--sd-text-secondary, #44474f)}.wrapper .c-header .c-logo img{width:32px;height:32px;object-fit:contain}.wrapper .c-header .c-title-menu-group{display:flex;align-items:center;font-size:18px;font-weight:500;flex:1}.wrapper .c-body{flex:1;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{display:flex;flex-direction:column;align-items:center;flex:0 0 60px;min-width:60px;width:60px;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon{display:flex;justify-content:center;align-items:center;min-height:50px;width:52px;border-radius:8px;transition:all .15s}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon img{height:24px;width:24px;object-fit:contain}.wrapper .c-body .c-menu .c-menu-tree{flex:1;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon{cursor:pointer;color:#757575;padding:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.search{width:20px;height:20px;font-size:18px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.cancel{width:16px;height:16px;font-size:16px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container{flex:1;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node{width:100%;display:flex;cursor:pointer;min-height:44px;padding:8px;border-radius:8px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-icon{display:flex;justify-content:center;align-items:center;height:100%}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description{flex:1;display:flex;align-items:center}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-content{flex:1;display:flex;align-items:center;flex-wrap:wrap;white-space:pre-wrap;font-size:15px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-expand{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:20px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;padding:0;font-size:18px;opacity:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin:focus-visible{opacity:1;outline:2px solid var(--sd-primary, #005cbb);outline-offset:2px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description[role=button]:focus-visible{outline:2px solid var(--sd-primary, #005cbb);outline-offset:-2px}.wrapper .c-footer{height:80px}.wrapper .c-vertical{position:fixed;height:100vh;left:58px;width:2px;background-color:#f8f9fa;pointer-events:none}:host ::ng-deep .c-menu-tree-search input:focus-visible{outline:1px solid var(--sd-primary, #005cbb);outline-offset:1px}\n"], dependencies: [{ kind: "component", type: SdIcon, selector: "sd-icon", inputs: ["name", "fontIcon", "color", "set", "fontSet", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "mask", "hideInlineError", "blurOnEnter", "clearable", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatTreeModule }, { kind: "directive", type: i2.MatNestedTreeNode, selector: "mat-nested-tree-node", inputs: ["matNestedTreeNode", "disabled", "tabIndex"], outputs: ["activation", "expandedChange"], exportAs: ["matNestedTreeNode"] }, { kind: "directive", type: i2.MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "component", type: i2.MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: i2.MatTreeNodeOutlet, selector: "[matTreeNodeOutlet]" }, { kind: "pipe", type: SdSafeHtmlPipe, name: "sdSafeHtml" }, { kind: "ngmodule", type: MatInputModule }, { kind: "pipe", type: MenuFocusPipe, name: "menuFocus" }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: HighlightSearchPipe, name: "highLightSearch" }, { kind: "directive", type: SdSuffixDefDirective, selector: "[sdSuffixDef]" }, { kind: "component", type: LayoutUserComponent$1, selector: "lib-layout-user", inputs: ["isMobileOrTablet", "isMenuLock", "isShowSidebar", "userInfo"], outputs: ["menuClosed", "menuOpened", "toggleMenuLock"] }, { kind: "pipe", type: SdTranslatePipe, name: "sdTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1487
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdSidebarV1Panel, isStandalone: true, selector: "sd-sidebar-v1-panel", inputs: { isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: true, transformFunction: null }, menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: true, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null }, isMobile: { classPropertyName: "isMobile", publicName: "isMobile", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expandSideBar: "expandSideBar", popupUserMenuClosed: "popupUserMenuClosed", popupUserMenuOpened: "popupUserMenuOpened", showSideBar: "showSideBar" }, ngImport: i0, template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div class=\"wrapper\" [style.height]=\"isMobile() ? '100dvh' : '100%'\">\n <div class=\"c-header\">\n <div class=\"c-logo\">\n <a\n href=\"/layout/home\"\n [attr.aria-label]=\"'core.module.layout.home.tab-name' | sdTranslate\"\n (click)=\"$event.preventDefault(); openHomePage()\">\n @if (logoUrl(); as _logoUrl) {\n <img alt=\"\" [src]=\"_logoUrl\" />\n } @else {\n <sd-icon name=\"apps\"></sd-icon>\n }\n </a>\n </div>\n <div class=\"c-title-menu-group\" [class.d-none]=\"!isShowSidebar()\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && pinnedMenuGroup().children?.length) {\n <button\n type=\"button\"\n [attr.aria-label]=\"'core.module.layout.sidebar.pinned' | sdTranslate\"\n (mouseenter)=\"onMouseOverMenuGroupNode($event, pinnedMenuGroup())\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, pinnedMenuGroup())\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'core.module.layout.sidebar.pinned' | sdTranslate\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <sd-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive()\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #44474f)',\n backgroundColor: isPinnedMenuGroupActive()\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\"\n name=\"push_pin\"></sd-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n type=\"button\"\n [attr.aria-label]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <sd-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #44474f)',\n backgroundColor:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\"\n [name]=\"nodeMenuGroup.icon || 'widgets'\"></sd-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\" [class.d-none]=\"!isShowSidebar()\" [attr.inert]=\"!isShowSidebar() ? '' : null\">\n @if (totalMenuInMenusByGroup() > 10) {\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\n <sd-input\n size=\"sm\"\n [placeholder]=\"'core.module.layout.sidebar.search' | sdTranslate\"\n [autoId]=\"'layout-v1-menu-search'\"\n [model]=\"searchText()\"\n (sdChange)=\"onFilterSearchText($event)\">\n <ng-template sdSuffixDef>\n @if (searchText()) {\n <sd-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\" name=\"cancel\"></sd-icon>\n } @else {\n <sd-icon class=\"c-search-prefix-icon search\" name=\"search\"></sd-icon>\n }\n </ng-template>\n </sd-input>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <div\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor:\n (currentPath() | menuFocus: node) ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)' : 'transparent',\n }\">\n <div class=\"c-menu-node-description\" [class.d-none]=\"!isShowSidebar()\">\n <a\n class=\"c-menu-node-description-content\"\n [href]=\"menuNodeHref(node)\"\n [attr.aria-current]=\"(currentPath() | menuFocus: node) ? 'page' : null\"\n (click)=\"onMenuNodeClick($event, node)\"\n [ngStyle]=\"{\n color:\n (currentPath() | menuFocus: node)\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text, #1a1b1f)',\n }\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></a>\n\n <!-- why: n\u00FAt ghim tr\u01B0\u1EDBc \u0111\u00E2y l\u00E0 <sd-icon (click)> \u2014 custom element kh\u00F4ng nh\u1EADn\n focus b\u00E0n ph\u00EDm v\u00E0 kh\u00F4ng c\u00F3 t\u00EAn kh\u1EA3 truy c\u1EADp, n\u00EAn kh\u00F4ng ghim \u0111\u01B0\u1EE3c b\u1EB1ng ph\u00EDm.\n \u0110\u1ED5i sang <button type=\"button\"> + aria-pressed, gi\u1ED1ng pattern \u0111\u00E3 d\u00F9ng \u1EDF\n `shared/menu-tree`. -->\n @if (_sidebar?.pin?.enabled) {\n <button\n type=\"button\"\n class=\"c-menu-node-description-icon-pin\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"\n isPinnedNode(node) || isHoveredNode(node) ? sidebar().brandColor || 'var(--sd-primary, #005cbb)' : null\n \"\n [attr.aria-pressed]=\"isPinnedNode(node)\"\n [attr.aria-label]=\"\n (isPinnedNode(node) ? 'core.module.layout.menu.unpin' : 'core.module.layout.menu.pin')\n | sdTranslate: { title: node.title }\n \"\n (click)=\"onTogglePin($event, node)\">\n <sd-icon name=\"push_pin\"></sd-icon>\n </button>\n }\n </div>\n </div>\n </mat-nested-tree-node>\n\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node }\">\n <div class=\"c-menu-node\" (mouseenter)=\"onMouseOverMenuNode($event, node)\" (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <button\n type=\"button\"\n [class.d-none]=\"!isShowSidebar()\"\n class=\"c-menu-node-description\"\n [attr.aria-expanded]=\"treeControl.isExpanded(node)\"\n (click)=\"onToggleMenuNode(node)\">\n <span\n class=\"c-menu-node-description-content\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></span>\n <sd-icon\n aria-hidden=\"true\"\n class=\"c-menu-node-description-icon-expand\"\n [name]=\"treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down'\"></sd-icon>\n </button>\n </div>\n </div>\n <div class=\"c-menu-node-group p-0\" role=\"group\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </div>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobile()\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </lib-layout-user>\n </div>\n\n <div class=\"c-vertical\"></div>\n </div>\n}\n", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host ::ng-deep .mat-nested-tree-node .c-menu-node-group .c-menu-node-description-content{margin-left:16px!important}:host ::ng-deep .mat-nested-tree-node .c-menu-node-group .mat-nested-tree-node .c-menu-node-group .c-menu-node-description-content{margin-left:32px!important}:host ::ng-deep .mat-nested-tree-node .c-menu-node-group .mat-nested-tree-node .c-menu-node-group .mat-nested-tree-node .c-menu-node-group .c-menu-node-description-content{margin-left:48px!important}.c-menu-node-group{margin-top:0;margin-bottom:0}.wrapper{display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{display:flex;align-items:center;height:52px;padding:3px;gap:16px}.wrapper .c-header .c-logo{display:flex;justify-content:center;align-items:center;width:52px;height:52px}.wrapper .c-header .c-logo a{display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:var(--sd-text-secondary, #44474f)}.wrapper .c-header .c-logo img{width:32px;height:32px;object-fit:contain}.wrapper .c-header .c-title-menu-group{display:flex;align-items:center;font-size:18px;font-weight:500;flex:1}.wrapper .c-body{flex:1;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{display:flex;flex-direction:column;align-items:center;flex:0 0 60px;min-width:60px;width:60px;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon{display:flex;justify-content:center;align-items:center;min-height:50px;width:52px;border-radius:8px;transition:all .15s}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon img{height:24px;width:24px;object-fit:contain}.wrapper .c-body .c-menu .c-menu-tree{flex:1;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon{cursor:pointer;color:#757575;padding:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.search{width:20px;height:20px;font-size:18px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.cancel{width:16px;height:16px;font-size:16px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container{flex:1;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node{width:100%;display:flex;cursor:pointer;min-height:44px;padding:8px;border-radius:8px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-icon{display:flex;justify-content:center;align-items:center;height:100%}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node button.c-menu-node-description{width:100%;padding:0;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description{flex:1;display:flex;align-items:center}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-content{flex:1;display:flex;align-items:center;flex-wrap:wrap;white-space:pre-wrap;font-size:15px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-expand{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:20px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;padding:0;font-size:18px;opacity:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin:focus-visible{opacity:1;outline:2px solid var(--sd-primary, #005cbb);outline-offset:2px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node a.c-menu-node-description-content{color:inherit;text-decoration:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description-content:focus-visible,.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node button.c-menu-node-description:focus-visible{outline:2px solid var(--sd-primary, #005cbb);outline-offset:-2px}.wrapper .c-footer{height:80px}.wrapper .c-vertical{position:fixed;height:100vh;left:58px;width:2px;background-color:#f8f9fa;pointer-events:none}:host ::ng-deep .c-menu-tree-search input:focus-visible{outline:1px solid var(--sd-primary, #005cbb);outline-offset:1px}\n"], dependencies: [{ kind: "component", type: SdIcon, selector: "sd-icon", inputs: ["name", "fontIcon", "color", "set", "fontSet", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "mask", "hideInlineError", "blurOnEnter", "clearable", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatTreeModule }, { kind: "directive", type: i2.MatNestedTreeNode, selector: "mat-nested-tree-node", inputs: ["matNestedTreeNode", "disabled", "tabIndex"], outputs: ["activation", "expandedChange"], exportAs: ["matNestedTreeNode"] }, { kind: "directive", type: i2.MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "component", type: i2.MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: i2.MatTreeNodeOutlet, selector: "[matTreeNodeOutlet]" }, { kind: "pipe", type: SdSafeHtmlPipe, name: "sdSafeHtml" }, { kind: "ngmodule", type: MatInputModule }, { kind: "pipe", type: MenuFocusPipe, name: "menuFocus" }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: HighlightSearchPipe, name: "highLightSearch" }, { kind: "directive", type: SdSuffixDefDirective, selector: "[sdSuffixDef]" }, { kind: "component", type: LayoutUserComponent$1, selector: "lib-layout-user", inputs: ["isMobileOrTablet", "isMenuLock", "isShowSidebar", "userInfo"], outputs: ["menuClosed", "menuOpened", "toggleMenuLock"] }, { kind: "pipe", type: SdTranslatePipe, name: "sdTranslate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1478
1488
|
}
|
|
1479
1489
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdSidebarV1Panel, decorators: [{
|
|
1480
1490
|
type: Component,
|
|
@@ -1493,7 +1503,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
|
|
|
1493
1503
|
SdSuffixDefDirective,
|
|
1494
1504
|
LayoutUserComponent$1,
|
|
1495
1505
|
SdTranslatePipe,
|
|
1496
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div class=\"wrapper\" [style.height]=\"isMobile() ? '100dvh' : '100%'\">\n <div class=\"c-header\">\n <div class=\"c-logo\">\n <a href=\"javascript:;\" [attr.aria-label]=\"'core.module.layout.home.tab-name' | sdTranslate\" (click)=\"openHomePage()\">\n @if (logoUrl(); as _logoUrl) {\n <img alt=\"\" [src]=\"_logoUrl\" />\n } @else {\n <sd-icon name=\"apps\"></sd-icon>\n }\n </a>\n </div>\n <div class=\"c-title-menu-group\" [class.d-none]=\"!isShowSidebar()\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && pinnedMenuGroup().children?.length) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, pinnedMenuGroup())\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, pinnedMenuGroup())\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'core.module.layout.sidebar.pinned' | sdTranslate\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <sd-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive()\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #44474f)',\n backgroundColor: isPinnedMenuGroupActive()\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\"\n name=\"push_pin\"></sd-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <sd-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #44474f)',\n backgroundColor:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\"\n [name]=\"nodeMenuGroup.icon || 'widgets'\"></sd-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\" [class.d-none]=\"!isShowSidebar()\" [attr.inert]=\"!isShowSidebar() ? '' : null\">\n @if (totalMenuInMenusByGroup() > 10) {\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\n <sd-input\n size=\"sm\"\n [placeholder]=\"'core.module.layout.sidebar.search' | sdTranslate\"\n [autoId]=\"'layout-v1-menu-search'\"\n [model]=\"searchText()\"\n (sdChange)=\"onFilterSearchText($event)\">\n <ng-template sdSuffixDef>\n @if (searchText()) {\n <sd-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\" name=\"cancel\"></sd-icon>\n } @else {\n <sd-icon class=\"c-search-prefix-icon search\" name=\"search\"></sd-icon>\n }\n </ng-template>\n </sd-input>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <li\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor:\n (currentPath() | menuFocus: node) ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)' : 'transparent',\n }\">\n <!-- why: role=button KH\u00D4NG \u0111\u01B0\u1EE3c b\u1ECDc ph\u1EA7n t\u1EED t\u01B0\u01A1ng t\u00E1c kh\u00E1c (n\u00FAt ghim b\u00EAn trong) \u2014\n AT coi c\u1EA3 c\u1EE5m l\u00E0 M\u1ED8T n\u00FAt v\u00E0 n\u00FAt ghim bi\u1EBFn m\u1EA5t kh\u1ECFi accessibility tree. Nay\n role=button + tabindex + Enter/Space + aria-current + (click) n\u1EB1m C\u00D9NG tr\u00EAn\n ph\u1EA7n TI\u00CAU \u0110\u1EC0, n\u00FAt ghim l\u00E0 sibling \u0111\u1ED9c l\u1EADp; c\u1EA3 hai \u0111\u1EC1u focus \u0111\u01B0\u1EE3c. -->\n <div class=\"c-menu-node-description\" [class.d-none]=\"!isShowSidebar()\">\n <div\n class=\"c-menu-node-description-content\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-current]=\"(currentPath() | menuFocus: node) ? 'page' : null\"\n (click)=\"navigate(node)\"\n (keydown.enter)=\"onMenuNodeKeydown($event, node)\"\n (keydown.space)=\"onMenuNodeKeydown($event, node)\"\n [ngStyle]=\"{\n color:\n (currentPath() | menuFocus: node)\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text, #1a1b1f)',\n }\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n\n <!-- why: n\u00FAt ghim tr\u01B0\u1EDBc \u0111\u00E2y l\u00E0 <sd-icon (click)> \u2014 custom element kh\u00F4ng nh\u1EADn\n focus b\u00E0n ph\u00EDm v\u00E0 kh\u00F4ng c\u00F3 t\u00EAn kh\u1EA3 truy c\u1EADp, n\u00EAn kh\u00F4ng ghim \u0111\u01B0\u1EE3c b\u1EB1ng ph\u00EDm.\n \u0110\u1ED5i sang <button type=\"button\"> + aria-pressed, gi\u1ED1ng pattern \u0111\u00E3 d\u00F9ng \u1EDF\n `shared/menu-tree`. -->\n @if (_sidebar?.pin?.enabled) {\n <button\n type=\"button\"\n class=\"c-menu-node-description-icon-pin\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"\n isPinnedNode(node) || isHoveredNode(node) ? sidebar().brandColor || 'var(--sd-primary, #005cbb)' : null\n \"\n [attr.aria-pressed]=\"isPinnedNode(node)\"\n [attr.aria-label]=\"\n (isPinnedNode(node) ? 'core.module.layout.menu.unpin' : 'core.module.layout.menu.pin')\n | sdTranslate: { title: node.title }\n \"\n (click)=\"onTogglePin($event, node)\">\n <sd-icon name=\"push_pin\"></sd-icon>\n </button>\n }\n </div>\n </li>\n </mat-nested-tree-node>\n\n <!-- why: b\u1ECF aria-hidden=\"true\" \u2014 n\u00F3 \u1EA9n TO\u00C0N B\u1ED8 nh\u00E1nh menu c\u00F3 con (ti\u00EAu \u0111\u1EC1 nh\u00F3m l\u1EABn\n m\u1ECDi m\u1EE5c con b\u00EAn trong) kh\u1ECFi accessibility tree. -->\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node }\">\n <li>\n <div\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <!-- why: nh\u00E1nh c\u00F3 con l\u00E0 n\u00FAt G\u1EACP/M\u1EDE th\u1EADt nh\u01B0ng tr\u01B0\u1EDBc \u0111\u00E2y ch\u1EC9 c\u00F3 (click) v\u00E0\n kh\u00F4ng khai tr\u1EA1ng th\u00E1i. Nay role=button + tabindex + aria-expanded +\n Enter/Space. -->\n <div\n [class.d-none]=\"!isShowSidebar()\"\n class=\"c-menu-node-description\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-expanded]=\"treeControl.isExpanded(node)\"\n (click)=\"onToggleMenuNode(node)\"\n (keydown.enter)=\"onToggleMenuNodeKeydown($event, node)\"\n (keydown.space)=\"onToggleMenuNodeKeydown($event, node)\">\n <div\n class=\"c-menu-node-description-content\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n <sd-icon\n class=\"c-menu-node-description-icon-expand\"\n [name]=\"treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down'\"></sd-icon>\n </div>\n </div>\n </div>\n <ul class=\"p-0\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </ul>\n </li>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobile()\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </lib-layout-user>\n </div>\n\n <div class=\"c-vertical\"></div>\n </div>\n}\n", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host ::ng-deep .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:16px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:32px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:48px!important}ul,li{margin-top:0;margin-bottom:0;list-style-type:none}.wrapper{display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{display:flex;align-items:center;height:52px;padding:3px;gap:16px}.wrapper .c-header .c-logo{display:flex;justify-content:center;align-items:center;width:52px;height:52px}.wrapper .c-header .c-logo a{display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:var(--sd-text-secondary, #44474f)}.wrapper .c-header .c-logo img{width:32px;height:32px;object-fit:contain}.wrapper .c-header .c-title-menu-group{display:flex;align-items:center;font-size:18px;font-weight:500;flex:1}.wrapper .c-body{flex:1;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{display:flex;flex-direction:column;align-items:center;flex:0 0 60px;min-width:60px;width:60px;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon{display:flex;justify-content:center;align-items:center;min-height:50px;width:52px;border-radius:8px;transition:all .15s}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon img{height:24px;width:24px;object-fit:contain}.wrapper .c-body .c-menu .c-menu-tree{flex:1;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon{cursor:pointer;color:#757575;padding:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.search{width:20px;height:20px;font-size:18px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.cancel{width:16px;height:16px;font-size:16px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container{flex:1;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node{width:100%;display:flex;cursor:pointer;min-height:44px;padding:8px;border-radius:8px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-icon{display:flex;justify-content:center;align-items:center;height:100%}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description{flex:1;display:flex;align-items:center}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-content{flex:1;display:flex;align-items:center;flex-wrap:wrap;white-space:pre-wrap;font-size:15px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-expand{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:20px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;padding:0;font-size:18px;opacity:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin:focus-visible{opacity:1;outline:2px solid var(--sd-primary, #005cbb);outline-offset:2px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description[role=button]:focus-visible{outline:2px solid var(--sd-primary, #005cbb);outline-offset:-2px}.wrapper .c-footer{height:80px}.wrapper .c-vertical{position:fixed;height:100vh;left:58px;width:2px;background-color:#f8f9fa;pointer-events:none}:host ::ng-deep .c-menu-tree-search input:focus-visible{outline:1px solid var(--sd-primary, #005cbb);outline-offset:1px}\n"] }]
|
|
1506
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div class=\"wrapper\" [style.height]=\"isMobile() ? '100dvh' : '100%'\">\n <div class=\"c-header\">\n <div class=\"c-logo\">\n <a\n href=\"/layout/home\"\n [attr.aria-label]=\"'core.module.layout.home.tab-name' | sdTranslate\"\n (click)=\"$event.preventDefault(); openHomePage()\">\n @if (logoUrl(); as _logoUrl) {\n <img alt=\"\" [src]=\"_logoUrl\" />\n } @else {\n <sd-icon name=\"apps\"></sd-icon>\n }\n </a>\n </div>\n <div class=\"c-title-menu-group\" [class.d-none]=\"!isShowSidebar()\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && pinnedMenuGroup().children?.length) {\n <button\n type=\"button\"\n [attr.aria-label]=\"'core.module.layout.sidebar.pinned' | sdTranslate\"\n (mouseenter)=\"onMouseOverMenuGroupNode($event, pinnedMenuGroup())\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, pinnedMenuGroup())\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'core.module.layout.sidebar.pinned' | sdTranslate\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <sd-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive()\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #44474f)',\n backgroundColor: isPinnedMenuGroupActive()\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\"\n name=\"push_pin\"></sd-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n type=\"button\"\n [attr.aria-label]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <sd-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text-secondary, #44474f)',\n backgroundColor:\n idMenuGroupActive() === nodeMenuGroup?.id\n ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)'\n : 'transparent',\n }\"\n [name]=\"nodeMenuGroup.icon || 'widgets'\"></sd-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\" [class.d-none]=\"!isShowSidebar()\" [attr.inert]=\"!isShowSidebar() ? '' : null\">\n @if (totalMenuInMenusByGroup() > 10) {\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\n <sd-input\n size=\"sm\"\n [placeholder]=\"'core.module.layout.sidebar.search' | sdTranslate\"\n [autoId]=\"'layout-v1-menu-search'\"\n [model]=\"searchText()\"\n (sdChange)=\"onFilterSearchText($event)\">\n <ng-template sdSuffixDef>\n @if (searchText()) {\n <sd-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\" name=\"cancel\"></sd-icon>\n } @else {\n <sd-icon class=\"c-search-prefix-icon search\" name=\"search\"></sd-icon>\n }\n </ng-template>\n </sd-input>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <div\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor:\n (currentPath() | menuFocus: node) ? _sidebar.brandLightColor || 'var(--sd-primary-light, #d7e3ff)' : 'transparent',\n }\">\n <div class=\"c-menu-node-description\" [class.d-none]=\"!isShowSidebar()\">\n <a\n class=\"c-menu-node-description-content\"\n [href]=\"menuNodeHref(node)\"\n [attr.aria-current]=\"(currentPath() | menuFocus: node) ? 'page' : null\"\n (click)=\"onMenuNodeClick($event, node)\"\n [ngStyle]=\"{\n color:\n (currentPath() | menuFocus: node)\n ? _sidebar.brandColor || 'var(--sd-primary, #005cbb)'\n : 'var(--sd-text, #1a1b1f)',\n }\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></a>\n\n <!-- why: n\u00FAt ghim tr\u01B0\u1EDBc \u0111\u00E2y l\u00E0 <sd-icon (click)> \u2014 custom element kh\u00F4ng nh\u1EADn\n focus b\u00E0n ph\u00EDm v\u00E0 kh\u00F4ng c\u00F3 t\u00EAn kh\u1EA3 truy c\u1EADp, n\u00EAn kh\u00F4ng ghim \u0111\u01B0\u1EE3c b\u1EB1ng ph\u00EDm.\n \u0110\u1ED5i sang <button type=\"button\"> + aria-pressed, gi\u1ED1ng pattern \u0111\u00E3 d\u00F9ng \u1EDF\n `shared/menu-tree`. -->\n @if (_sidebar?.pin?.enabled) {\n <button\n type=\"button\"\n class=\"c-menu-node-description-icon-pin\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"\n isPinnedNode(node) || isHoveredNode(node) ? sidebar().brandColor || 'var(--sd-primary, #005cbb)' : null\n \"\n [attr.aria-pressed]=\"isPinnedNode(node)\"\n [attr.aria-label]=\"\n (isPinnedNode(node) ? 'core.module.layout.menu.unpin' : 'core.module.layout.menu.pin')\n | sdTranslate: { title: node.title }\n \"\n (click)=\"onTogglePin($event, node)\">\n <sd-icon name=\"push_pin\"></sd-icon>\n </button>\n }\n </div>\n </div>\n </mat-nested-tree-node>\n\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node }\">\n <div class=\"c-menu-node\" (mouseenter)=\"onMouseOverMenuNode($event, node)\" (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <button\n type=\"button\"\n [class.d-none]=\"!isShowSidebar()\"\n class=\"c-menu-node-description\"\n [attr.aria-expanded]=\"treeControl.isExpanded(node)\"\n (click)=\"onToggleMenuNode(node)\">\n <span\n class=\"c-menu-node-description-content\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></span>\n <sd-icon\n aria-hidden=\"true\"\n class=\"c-menu-node-description-icon-expand\"\n [name]=\"treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down'\"></sd-icon>\n </button>\n </div>\n </div>\n <div class=\"c-menu-node-group p-0\" role=\"group\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </div>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobile()\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </lib-layout-user>\n </div>\n\n <div class=\"c-vertical\"></div>\n </div>\n}\n", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host ::ng-deep .mat-nested-tree-node .c-menu-node-group .c-menu-node-description-content{margin-left:16px!important}:host ::ng-deep .mat-nested-tree-node .c-menu-node-group .mat-nested-tree-node .c-menu-node-group .c-menu-node-description-content{margin-left:32px!important}:host ::ng-deep .mat-nested-tree-node .c-menu-node-group .mat-nested-tree-node .c-menu-node-group .mat-nested-tree-node .c-menu-node-group .c-menu-node-description-content{margin-left:48px!important}.c-menu-node-group{margin-top:0;margin-bottom:0}.wrapper{display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{display:flex;align-items:center;height:52px;padding:3px;gap:16px}.wrapper .c-header .c-logo{display:flex;justify-content:center;align-items:center;width:52px;height:52px}.wrapper .c-header .c-logo a{display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:var(--sd-text-secondary, #44474f)}.wrapper .c-header .c-logo img{width:32px;height:32px;object-fit:contain}.wrapper .c-header .c-title-menu-group{display:flex;align-items:center;font-size:18px;font-weight:500;flex:1}.wrapper .c-body{flex:1;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{display:flex;flex-direction:column;align-items:center;flex:0 0 60px;min-width:60px;width:60px;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon{display:flex;justify-content:center;align-items:center;min-height:50px;width:52px;border-radius:8px;transition:all .15s}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon img{height:24px;width:24px;object-fit:contain}.wrapper .c-body .c-menu .c-menu-tree{flex:1;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon{cursor:pointer;color:#757575;padding:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.search{width:20px;height:20px;font-size:18px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.cancel{width:16px;height:16px;font-size:16px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container{flex:1;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node{width:100%;display:flex;cursor:pointer;min-height:44px;padding:8px;border-radius:8px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-icon{display:flex;justify-content:center;align-items:center;height:100%}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node button.c-menu-node-description{width:100%;padding:0;border:0;background:transparent;color:inherit;text-align:left;cursor:pointer}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description{flex:1;display:flex;align-items:center}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-content{flex:1;display:flex;align-items:center;flex-wrap:wrap;white-space:pre-wrap;font-size:15px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-expand{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:20px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;padding:0;font-size:18px;opacity:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin:focus-visible{opacity:1;outline:2px solid var(--sd-primary, #005cbb);outline-offset:2px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node a.c-menu-node-description-content{color:inherit;text-decoration:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description-content:focus-visible,.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node button.c-menu-node-description:focus-visible{outline:2px solid var(--sd-primary, #005cbb);outline-offset:-2px}.wrapper .c-footer{height:80px}.wrapper .c-vertical{position:fixed;height:100vh;left:58px;width:2px;background-color:#f8f9fa;pointer-events:none}:host ::ng-deep .c-menu-tree-search input:focus-visible{outline:1px solid var(--sd-primary, #005cbb);outline-offset:1px}\n"] }]
|
|
1497
1507
|
}], ctorParameters: () => [] });
|
|
1498
1508
|
|
|
1499
1509
|
class SdSidebarV1 {
|