@rt-tools/ui-kit-v2 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs +92 -5
- package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-badge.mjs +191 -0
- package/fesm2022/rt-tools-ui-kit-v2-badge.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs +3 -2
- package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-button.mjs +6 -1
- package/fesm2022/rt-tools-ui-kit-v2-button.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-checkbox.mjs +35 -4
- package/fesm2022/rt-tools-ui-kit-v2-checkbox.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-color-palette.mjs +13 -4
- package/fesm2022/rt-tools-ui-kit-v2-color-palette.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-container.mjs +245 -60
- package/fesm2022/rt-tools-ui-kit-v2-container.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-copy-value.mjs +30 -5
- package/fesm2022/rt-tools-ui-kit-v2-copy-value.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-core.mjs +113 -2
- package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs +14 -3
- package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs +17 -3
- package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs +6 -3
- package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs +2 -2
- package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-divider.mjs +112 -0
- package/fesm2022/rt-tools-ui-kit-v2-divider.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-drawer.mjs +854 -0
- package/fesm2022/rt-tools-ui-kit-v2-drawer.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs +16 -5
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +580 -65
- package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-expansion-panel.mjs +203 -15
- package/fesm2022/rt-tools-ui-kit-v2-expansion-panel.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-field.mjs +40 -8
- package/fesm2022/rt-tools-ui-kit-v2-field.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs +7 -3
- package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs +53 -2
- package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs +14 -4
- package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs +6 -3
- package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs +16 -5
- package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs +14 -4
- package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs +3 -2
- package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-input.mjs +207 -7
- package/fesm2022/rt-tools-ui-kit-v2-input.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-menu.mjs +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-menu.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs +3 -2
- package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +2 -0
- package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs +3 -2
- package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-profile-menu.mjs +3 -2
- package/fesm2022/rt-tools-ui-kit-v2-profile-menu.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-progress-bar.mjs +171 -0
- package/fesm2022/rt-tools-ui-kit-v2-progress-bar.mjs.map +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-radio-button.mjs +176 -6
- package/fesm2022/rt-tools-ui-kit-v2-radio-button.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +2 -1
- package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-select.mjs +142 -23
- package/fesm2022/rt-tools-ui-kit-v2-select.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +22 -9
- package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs +3 -2
- package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs +105 -8
- package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-table.mjs +13 -2
- package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +609 -33
- package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +1 -0
- package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs +45 -7
- package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs +2 -2
- package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +11 -2
- package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-toast.mjs +152 -11
- package/fesm2022/rt-tools-ui-kit-v2-toast.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs +199 -17
- package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs +35 -5
- package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs +14 -4
- package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-tree.mjs +6 -3
- package/fesm2022/rt-tools-ui-kit-v2-tree.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs +21 -6
- package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs.map +1 -1
- package/fesm2022/rt-tools-ui-kit-v2.mjs +4 -0
- package/package.json +17 -1
- package/src/assets/icons/volume-off.svg +2 -1
- package/src/lib/components/autocomplete/CONTEXT.md +25 -14
- package/src/lib/components/autocomplete/rt-autocomplete.component.scss +19 -0
- package/src/lib/components/badge/CONTEXT.md +33 -0
- package/src/lib/components/badge/rt-badge.directive.scss +104 -0
- package/src/lib/components/breadcrumbs/rt-breadcrumbs.component.scss +2 -2
- package/src/lib/components/button/CONTEXT.md +5 -0
- package/src/lib/components/button/rt-button.directive.scss +3 -1
- package/src/lib/components/checkbox/CONTEXT.md +15 -8
- package/src/lib/components/color-palette/rt-color-palette.component.scss +2 -2
- package/src/lib/components/container/CONTEXT.md +23 -6
- package/src/lib/components/container/rt-container.component.scss +90 -1
- package/src/lib/components/copy-value/CONTEXT.md +6 -5
- package/src/lib/components/copy-value/rt-copy-value.component.scss +16 -0
- package/src/lib/components/date-picker/rt-date-picker.component.scss +7 -0
- package/src/lib/components/date-range/rt-date-range.component.scss +7 -0
- package/src/lib/components/divider/CONTEXT.md +21 -0
- package/src/lib/components/divider/rt-divider.component.scss +34 -0
- package/src/lib/components/drawer/CONTEXT.md +73 -0
- package/src/lib/components/drawer/rt-drawer-container.component.scss +19 -0
- package/src/lib/components/drawer/rt-drawer.component.scss +168 -0
- package/src/lib/components/drawer/rt-resize-handle.component.scss +42 -0
- package/src/lib/components/dynamic-selector/CONTEXT.md +5 -0
- package/src/lib/components/expansion-panel/CONTEXT.md +32 -8
- package/src/lib/components/expansion-panel/rt-expansion-panel.component.scss +67 -2
- package/src/lib/components/field/CONTEXT.md +43 -0
- package/src/lib/components/field/rt-field-label-inside.scss +179 -0
- package/src/lib/components/field/rt-field.component.scss +51 -2
- package/src/lib/components/icon-button/CONTEXT.md +17 -15
- package/src/lib/components/icon-button/rt-icon-button.component.scss +3 -1
- package/src/lib/components/inline-edit/rt-inline-edit.component.scss +4 -4
- package/src/lib/components/input/CONTEXT.md +45 -11
- package/src/lib/components/input/rt-input-floating-label.scss +192 -0
- package/src/lib/components/input/rt-input-icons.scss +105 -0
- package/src/lib/components/input/rt-input.component.scss +91 -13
- package/src/lib/components/input-number/CONTEXT.md +7 -0
- package/src/lib/components/input-number/rt-input-number.component.scss +58 -1
- package/src/lib/components/menu/CONTEXT.md +1 -0
- package/src/lib/components/multiselect/CONTEXT.md +2 -1
- package/src/lib/components/multiselect/rt-multiselect.component.scss +7 -0
- package/src/lib/components/pagination/CONTEXT.md +3 -0
- package/src/lib/components/pagination/rt-pagination.component.scss +7 -0
- package/src/lib/components/progress-bar/CONTEXT.md +22 -0
- package/src/lib/components/progress-bar/rt-progress-bar.component.scss +77 -0
- package/src/lib/components/radio-button/CONTEXT.md +9 -0
- package/src/lib/components/radio-button/rt-radio-group.component.scss +13 -0
- package/src/lib/components/select/CONTEXT.md +28 -0
- package/src/lib/components/select/rt-select-clear.scss +88 -0
- package/src/lib/components/select/rt-select-floating-label.scss +155 -0
- package/src/lib/components/select/rt-select-material.scss +54 -0
- package/src/lib/components/select/rt-select.component.scss +54 -16
- package/src/lib/components/side-menu/CONTEXT.md +5 -0
- package/src/lib/components/speed-menu/rt-speed-menu.component.scss +5 -5
- package/src/lib/components/stepper/CONTEXT.md +13 -5
- package/src/lib/components/stepper/rt-stepper.component.scss +93 -0
- package/src/lib/components/tabs/CONTEXT.md +57 -9
- package/src/lib/components/tabs/rt-tabs.component.scss +201 -5
- package/src/lib/components/textarea/CONTEXT.md +12 -1
- package/src/lib/components/textarea/rt-textarea.component.scss +116 -1
- package/src/lib/components/toast/CONTEXT.md +23 -0
- package/src/lib/components/toast/rt-toast.component.scss +37 -0
- package/src/lib/components/toggle-button-group/CONTEXT.md +24 -4
- package/src/lib/components/toggle-button-group/rt-toggle-button-group-chips.scss +151 -0
- package/src/lib/components/toggle-button-group/rt-toggle-button-group.component.scss +35 -0
- package/src/lib/components/tooltip/CONTEXT.md +7 -1
- package/src/lib/components/tree/rt-tree.component.scss +2 -2
- package/src/styles/_color-scheme.scss +1 -1
- package/src/styles/_density.scss +48 -0
- package/src/styles/_index.scss +8 -0
- package/src/styles/_preset-material.scss +160 -70
- package/src/styles/_primitives.scss +1 -0
- package/src/styles/_semantic-navigation.scss +117 -0
- package/src/styles/_semantic.scss +29 -98
- package/src/styles/_theme-dark.scss +8 -0
- package/styles/tokens.css +2066 -1134
- package/types/rt-tools-ui-kit-v2-autocomplete.d.ts +34 -0
- package/types/rt-tools-ui-kit-v2-badge.d.ts +71 -0
- package/types/rt-tools-ui-kit-v2-checkbox.d.ts +17 -3
- package/types/rt-tools-ui-kit-v2-container.d.ts +65 -9
- package/types/rt-tools-ui-kit-v2-copy-value.d.ts +11 -1
- package/types/rt-tools-ui-kit-v2-core.d.ts +109 -4
- package/types/rt-tools-ui-kit-v2-divider.d.ts +29 -0
- package/types/rt-tools-ui-kit-v2-drawer.d.ts +257 -0
- package/types/rt-tools-ui-kit-v2-dynamic-selector.d.ts +240 -25
- package/types/rt-tools-ui-kit-v2-expansion-panel.d.ts +87 -3
- package/types/rt-tools-ui-kit-v2-field.d.ts +18 -1
- package/types/rt-tools-ui-kit-v2-form-control.d.ts +42 -4
- package/types/rt-tools-ui-kit-v2-icon-button.d.ts +2 -1
- package/types/rt-tools-ui-kit-v2-input-number.d.ts +1 -0
- package/types/rt-tools-ui-kit-v2-input.d.ts +98 -4
- package/types/rt-tools-ui-kit-v2-progress-bar.d.ts +53 -0
- package/types/rt-tools-ui-kit-v2-radio-button.d.ts +80 -1
- package/types/rt-tools-ui-kit-v2-select.d.ts +65 -1
- package/types/rt-tools-ui-kit-v2-side-menu.d.ts +3 -0
- package/types/rt-tools-ui-kit-v2-stepper.d.ts +57 -4
- package/types/rt-tools-ui-kit-v2-tabs.d.ts +291 -6
- package/types/rt-tools-ui-kit-v2-textarea.d.ts +16 -0
- package/types/rt-tools-ui-kit-v2-toast.d.ts +38 -2
- package/types/rt-tools-ui-kit-v2-toggle-button-group.d.ts +83 -3
- package/types/rt-tools-ui-kit-v2-tooltip.d.ts +17 -2
- package/types/rt-tools-ui-kit-v2.d.ts +4 -0
- package/src/lib/components/dynamic-selector/stories/component/test-dynamic-selector-popup-frame.component.scss +0 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-pagination.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/pagination/rt-pagination.logic.ts","../../../projects/ui-kit-v2/src/lib/components/pagination/rt-pagination.component.ts","../../../projects/ui-kit-v2/src/lib/components/pagination/rt-pagination.component.html"],"sourcesContent":["import { IPageModel } from '@rt-tools/utils';\n\nimport { IRtPagination } from './rt-pagination.model';\n\n/** Сколько всего страниц. Пустой список — одна страница, листать нечего. */\nexport function lastPageOf(page: IPageModel): number {\n if (page.pageSize <= 0) {\n return 1;\n }\n\n return Math.max(1, Math.ceil(page.totalCount / page.pageSize));\n}\n\n/** Номер первой записи открытой страницы. */\nexport function rangeFromOf(page: IPageModel): number {\n return (page.pageNumber - 1) * page.pageSize + 1;\n}\n\n/** Номер последней записи открытой страницы — на последней странице она короче. */\nexport function rangeToOf(page: IPageModel): number {\n return Math.min(page.pageNumber * page.pageSize, page.totalCount);\n}\n\n/**\n * Полоса номеров страниц с разрывами «…»: первая, последняя и соседи открытой.\n * Пуста при единственной странице — показывать нечего.\n */\nexport function pageItemsOf(page: IPageModel, neighbours: number): ReadonlyArray<IRtPagination.PageItem> {\n const lastPage: number = lastPageOf(page);\n if (lastPage <= 1) {\n return [];\n }\n\n const items: IRtPagination.PageItem[] = [];\n let previous: number = 0;\n for (let candidate: number = 1; candidate <= lastPage; candidate++) {\n const isEdge: boolean = candidate === 1 || candidate === lastPage;\n const isNeighbour: boolean = candidate >= page.pageNumber - neighbours && candidate <= page.pageNumber + neighbours;\n if (!isEdge && !isNeighbour) {\n continue;\n }\n if (previous && candidate - previous > 1) {\n items.push('gap');\n }\n items.push(candidate);\n previous = candidate;\n }\n\n return items;\n}\n\n/** Номера с `from` по `to` включительно. */\nfunction pagesBetween(from: number, to: number): number[] {\n return Array.from({ length: to - from + 1 }, (_value: unknown, index: number): number => from + index);\n}\n\n/**\n * Полоса номеров первого кита — семь мест: до шести страниц видны все, дальше края по три\n * (`1 2 3 … 11 12 13`) или первая, соседи открытой и последняя (`1 … 6 7 8 … 13`); у края разрыв\n * съезжает на одно место за открытой страницей. Одна страница — один номер.\n */\nexport function pageSlotsOf(page: IPageModel): ReadonlyArray<IRtPagination.PageItem> {\n const lastPage: number = lastPageOf(page);\n const current: number = page.pageNumber;\n\n if (lastPage <= 6) {\n return pagesBetween(1, lastPage);\n }\n if (current < 3 || current > lastPage - 2) {\n return [...pagesBetween(1, 3), 'gap', ...pagesBetween(lastPage - 2, lastPage)];\n }\n if (current === 3) {\n return [...pagesBetween(1, 4), 'gap', ...pagesBetween(lastPage - 1, lastPage)];\n }\n if (current === 4) {\n return [...pagesBetween(1, 5), 'gap', lastPage];\n }\n if (current <= lastPage - 4) {\n return [1, 'gap', current - 1, current, current + 1, 'gap', lastPage];\n }\n if (current === lastPage - 3) {\n return [1, 'gap', ...pagesBetween(lastPage - 4, lastPage)];\n }\n\n return [1, 2, 'gap', ...pagesBetween(lastPage - 3, lastPage)];\n}\n","import {\n booleanAttribute,\n computed,\n inject,\n input,\n output,\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\nimport { IPageModel } from '@rt-tools/utils';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap, TRtKitLabelParams, rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { RtSelectComponent } from '@rt-tools/ui-kit-v2/select';\nimport { IRtSelect } from '@rt-tools/ui-kit-v2/select';\nimport { lastPageOf, pageItemsOf, pageSlotsOf, rangeFromOf, rangeToOf } from './rt-pagination.logic';\nimport { IRtPagination } from './rt-pagination.model';\n\nconst BEM_BLOCK: string = 'rt-pagination';\nconst NEIGHBOURS: number = 1; // соседей вокруг открытой страницы\n\n@Component({\n selector: 'rt-pagination',\n templateUrl: './rt-pagination.component.html',\n styleUrl: './rt-pagination.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n FormsModule,\n\n // standalone components / directives\n RtIconButtonComponent,\n RtSelectComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n '[style.display]': \"isVisible() ? null : 'none'\",\n },\n})\nexport class RtPaginationComponent {\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly perPageSelectOptions: Signal<ReadonlyArray<IRtSelect.Option<number>>> = computed(\n (): ReadonlyArray<IRtSelect.Option<number>> =>\n this.perPageOptions().map((n: number): IRtSelect.Option<number> => ({ label: String(n), value: n }))\n );\n\n /**\n * Диапазон записей и номер страницы — с подстановками, поэтому карте подписей\n * они не годятся: числа приходят из модели страницы.\n */\n protected readonly rangeLabel: Signal<string> = rtKitLabel(\n 'uiRangeOf',\n computed((): TRtKitLabelParams => ({ from: this.rangeFrom(), to: this.rangeTo(), total: this.pageModel().totalCount }))\n );\n\n protected readonly pageLabel: Signal<string> = rtKitLabel(\n 'uiPageOf',\n computed((): TRtKitLabelParams => ({ page: this.pageModel().pageNumber, last: this.lastPage() }))\n );\n\n protected readonly isFirst: Signal<boolean> = computed((): boolean => this.pageModel().pageNumber <= 1);\n\n protected readonly isLast: Signal<boolean> = computed((): boolean => this.pageModel().pageNumber >= this.lastPage());\n\n public readonly pageModel: InputSignal<IPageModel> = input.required<IPageModel>();\n\n public readonly perPageOptions: InputSignal<ReadonlyArray<number>> = input<ReadonlyArray<number>>([20, 50, 100]);\n\n /** Значок стрелки «назад»: вид первого кита рисует стрелку, а не шеврон. */\n public readonly prevIcon: InputSignal<IRtIcon.Name> = input<IRtIcon.Name>('chevron-left');\n\n /** Значок стрелки «вперёд». */\n public readonly nextIcon: InputSignal<IRtIcon.Name> = input<IRtIcon.Name>('chevron-right');\n\n /** Счёт номеров: список под материальным набором просит семь мест первого кита. */\n public readonly numbering: InputSignal<IRtPagination.Numbering> = input<IRtPagination.Numbering>('neighbours');\n\n public readonly loading: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n public readonly pageChange: OutputEmitterRef<number> = output<number>();\n\n public readonly perPageChange: OutputEmitterRef<number> = output<number>();\n\n /**\n * Пагинацию показываем, только когда есть что листать/менять: всё не влезает\n * на одну страницу даже при минимальной опции размера (`total > наименьший\n * perPageOption`). Иначе и навигация, и селектор размера бесполезны — прячем\n * весь бар (включая пустой и пустой-по-фильтру список).\n */\n public readonly isVisible: Signal<boolean> = computed((): boolean => {\n const options: ReadonlyArray<number> = this.perPageOptions();\n const smallest: number = options.length > 0 ? Math.min(...options) : 0;\n return this.pageModel().totalCount > smallest;\n });\n\n /** Сколько всего страниц при нынешнем размере страницы. */\n public readonly lastPage: Signal<number> = computed((): number => lastPageOf(this.pageModel()));\n\n /**\n * Границы диапазона записей открытой страницы. Собираются числами, а сама\n * подпись — в шаблоне: только там подстановка проходит через словарь и\n * переживает смену языка.\n */\n public readonly rangeFrom: Signal<number> = computed((): number => rangeFromOf(this.pageModel()));\n\n public readonly rangeTo: Signal<number> = computed((): number => rangeToOf(this.pageModel()));\n\n /** Полоса номеров страниц с разрывами «…». По соседям пуста при единственной странице. */\n public readonly pageItems: Signal<ReadonlyArray<IRtPagination.PageItem>> = computed((): ReadonlyArray<IRtPagination.PageItem> =>\n this.numbering() === 'seven' ? pageSlotsOf(this.pageModel()) : pageItemsOf(this.pageModel(), NEIGHBOURS)\n );\n\n public goTo(pageNumber: number): void {\n if (this.loading() || pageNumber === this.pageModel().pageNumber || pageNumber < 1 || pageNumber > this.lastPage()) {\n return;\n }\n this.pageChange.emit(pageNumber);\n }\n\n protected onPerPage(value: number | null): void {\n if (value === null || this.loading() || value === this.pageModel().pageSize) {\n return;\n }\n this.perPageChange.emit(value);\n }\n}\n","<ng-container rtBlock=\"rt-pagination\">\n <!--\n Ветки «ничего не найдено» здесь нет намеренно: пустой набор прячет весь\n бар целиком (`isVisible`), так что до этой строки дело не доходит. Пока\n такая ветка тут висела, она читалась как рабочее состояние, а показать\n её было нельзя ни при каких входах.\n -->\n <span rtElem=\"range\" qa-dataid=\"pagination-range\">\n {{ rangeLabel() }}\n </span>\n\n @if (pageItems().length) {\n <nav rtElem=\"compact\" qa-dataid=\"pagination-compact\" [attr.aria-label]=\"t().uiPagination\">\n <rt-icon-button\n qa-dataid=\"pagination-compact-prev\"\n variant=\"ghost\"\n size=\"sm\"\n [icon]=\"prevIcon()\"\n [ariaLabel]=\"t().uiPrevPage\"\n [tooltip]=\"t().uiBack\"\n [disabled]=\"isFirst() || loading()\"\n (clicked)=\"goTo(pageModel().pageNumber - 1)\" />\n\n <span rtElem=\"compact-label\" qa-dataid=\"pagination-compact-label\">\n {{ pageLabel() }}\n </span>\n\n <rt-icon-button\n qa-dataid=\"pagination-compact-next\"\n variant=\"ghost\"\n size=\"sm\"\n [icon]=\"nextIcon()\"\n [ariaLabel]=\"t().uiNextPage\"\n [tooltip]=\"t().uiForward\"\n [disabled]=\"isLast() || loading()\"\n (clicked)=\"goTo(pageModel().pageNumber + 1)\" />\n </nav>\n\n <nav rtElem=\"nav\" qa-dataid=\"pagination-nav\" [attr.aria-label]=\"t().uiPagination\">\n <rt-icon-button\n qa-dataid=\"pagination-prev\"\n variant=\"ghost\"\n size=\"sm\"\n [icon]=\"prevIcon()\"\n [ariaLabel]=\"t().uiPrevPage\"\n [tooltip]=\"t().uiBack\"\n [disabled]=\"isFirst() || loading()\"\n (clicked)=\"goTo(pageModel().pageNumber - 1)\" />\n\n @for (item of pageItems(); track $index) {\n @if (item === 'gap') {\n <span rtElem=\"gap\" aria-hidden=\"true\">…</span>\n } @else {\n <button\n rtElem=\"page\"\n qa-dataid=\"pagination-page\"\n type=\"button\"\n [attr.data-page]=\"item\"\n [rtMod]=\"{ current: item === pageModel().pageNumber }\"\n [attr.aria-current]=\"item === pageModel().pageNumber ? 'page' : null\"\n [disabled]=\"loading()\"\n (click)=\"goTo(item)\">\n {{ item }}\n </button>\n }\n }\n\n <rt-icon-button\n qa-dataid=\"pagination-next\"\n variant=\"ghost\"\n size=\"sm\"\n [icon]=\"nextIcon()\"\n [ariaLabel]=\"t().uiNextPage\"\n [tooltip]=\"t().uiForward\"\n [disabled]=\"isLast() || loading()\"\n (clicked)=\"goTo(pageModel().pageNumber + 1)\" />\n </nav>\n }\n\n <div rtElem=\"per-page\">\n <span rtElem=\"per-page-label\">{{ t().uiPerPage }}</span>\n <rt-select\n qa-dataid=\"pagination-per-page\"\n [ariaLabel]=\"t().uiItemsPerPage\"\n [options]=\"perPageSelectOptions()\"\n [clearable]=\"false\"\n [ngModel]=\"pageModel().pageSize\"\n [ngModelOptions]=\"{ standalone: true }\"\n (selectionChange)=\"onPerPage($event)\" />\n </div>\n</ng-container>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-pagination.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/pagination/rt-pagination.logic.ts","../../../projects/ui-kit-v2/src/lib/components/pagination/rt-pagination.component.ts","../../../projects/ui-kit-v2/src/lib/components/pagination/rt-pagination.component.html"],"sourcesContent":["import { IPageModel } from '@rt-tools/utils';\n\nimport { IRtPagination } from './rt-pagination.model';\n\n/** Сколько всего страниц. Пустой список — одна страница, листать нечего. */\nexport function lastPageOf(page: IPageModel): number {\n if (page.pageSize <= 0) {\n return 1;\n }\n\n return Math.max(1, Math.ceil(page.totalCount / page.pageSize));\n}\n\n/** Номер первой записи открытой страницы. */\nexport function rangeFromOf(page: IPageModel): number {\n return (page.pageNumber - 1) * page.pageSize + 1;\n}\n\n/** Номер последней записи открытой страницы — на последней странице она короче. */\nexport function rangeToOf(page: IPageModel): number {\n return Math.min(page.pageNumber * page.pageSize, page.totalCount);\n}\n\n/**\n * Полоса номеров страниц с разрывами «…»: первая, последняя и соседи открытой.\n * Пуста при единственной странице — показывать нечего.\n */\nexport function pageItemsOf(page: IPageModel, neighbours: number): ReadonlyArray<IRtPagination.PageItem> {\n const lastPage: number = lastPageOf(page);\n if (lastPage <= 1) {\n return [];\n }\n\n const items: IRtPagination.PageItem[] = [];\n let previous: number = 0;\n for (let candidate: number = 1; candidate <= lastPage; candidate++) {\n const isEdge: boolean = candidate === 1 || candidate === lastPage;\n const isNeighbour: boolean = candidate >= page.pageNumber - neighbours && candidate <= page.pageNumber + neighbours;\n if (!isEdge && !isNeighbour) {\n continue;\n }\n if (previous && candidate - previous > 1) {\n items.push('gap');\n }\n items.push(candidate);\n previous = candidate;\n }\n\n return items;\n}\n\n/** Номера с `from` по `to` включительно. */\nfunction pagesBetween(from: number, to: number): number[] {\n return Array.from({ length: to - from + 1 }, (_value: unknown, index: number): number => from + index);\n}\n\n/**\n * Полоса номеров первого кита — семь мест: до шести страниц видны все, дальше края по три\n * (`1 2 3 … 11 12 13`) или первая, соседи открытой и последняя (`1 … 6 7 8 … 13`); у края разрыв\n * съезжает на одно место за открытой страницей. Одна страница — один номер.\n */\nexport function pageSlotsOf(page: IPageModel): ReadonlyArray<IRtPagination.PageItem> {\n const lastPage: number = lastPageOf(page);\n const current: number = page.pageNumber;\n\n if (lastPage <= 6) {\n return pagesBetween(1, lastPage);\n }\n if (current < 3 || current > lastPage - 2) {\n return [...pagesBetween(1, 3), 'gap', ...pagesBetween(lastPage - 2, lastPage)];\n }\n if (current === 3) {\n return [...pagesBetween(1, 4), 'gap', ...pagesBetween(lastPage - 1, lastPage)];\n }\n if (current === 4) {\n return [...pagesBetween(1, 5), 'gap', lastPage];\n }\n if (current <= lastPage - 4) {\n return [1, 'gap', current - 1, current, current + 1, 'gap', lastPage];\n }\n if (current === lastPage - 3) {\n return [1, 'gap', ...pagesBetween(lastPage - 4, lastPage)];\n }\n\n return [1, 2, 'gap', ...pagesBetween(lastPage - 3, lastPage)];\n}\n","import {\n booleanAttribute,\n computed,\n inject,\n input,\n output,\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\nimport { IPageModel } from '@rt-tools/utils';\n\nimport { RT_KIT_LABELS, TRtKitLabelMap, TRtKitLabelParams, rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { IRtIcon } from '@rt-tools/ui-kit-v2/core';\nimport { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { RtSelectComponent } from '@rt-tools/ui-kit-v2/select';\nimport { IRtSelect } from '@rt-tools/ui-kit-v2/select';\nimport { lastPageOf, pageItemsOf, pageSlotsOf, rangeFromOf, rangeToOf } from './rt-pagination.logic';\nimport { IRtPagination } from './rt-pagination.model';\n\nconst BEM_BLOCK: string = 'rt-pagination';\nconst NEIGHBOURS: number = 1; // соседей вокруг открытой страницы\n\n@Component({\n selector: 'rt-pagination',\n templateUrl: './rt-pagination.component.html',\n styleUrl: './rt-pagination.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n FormsModule,\n\n // standalone components / directives\n RtIconButtonComponent,\n RtSelectComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n '[style.display]': \"isVisible() ? null : 'none'\",\n },\n})\nexport class RtPaginationComponent {\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n protected readonly perPageSelectOptions: Signal<ReadonlyArray<IRtSelect.Option<number>>> = computed(\n (): ReadonlyArray<IRtSelect.Option<number>> =>\n this.perPageOptions().map((n: number): IRtSelect.Option<number> => ({ label: String(n), value: n }))\n );\n\n /**\n * Диапазон записей и номер страницы — с подстановками, поэтому карте подписей\n * они не годятся: числа приходят из модели страницы.\n */\n protected readonly rangeLabel: Signal<string> = rtKitLabel(\n 'uiRangeOf',\n computed((): TRtKitLabelParams => ({ from: this.rangeFrom(), to: this.rangeTo(), total: this.pageModel().totalCount }))\n );\n\n protected readonly pageLabel: Signal<string> = rtKitLabel(\n 'uiPageOf',\n computed((): TRtKitLabelParams => ({ page: this.pageModel().pageNumber, last: this.lastPage() }))\n );\n\n protected readonly isFirst: Signal<boolean> = computed((): boolean => this.pageModel().pageNumber <= 1);\n\n protected readonly isLast: Signal<boolean> = computed((): boolean => this.pageModel().pageNumber >= this.lastPage());\n\n public readonly pageModel: InputSignal<IPageModel> = input.required<IPageModel>();\n\n public readonly perPageOptions: InputSignal<ReadonlyArray<number>> = input<ReadonlyArray<number>>([20, 50, 100]);\n\n /** Значок стрелки «назад»: вид первого кита рисует стрелку, а не шеврон. */\n public readonly prevIcon: InputSignal<IRtIcon.Name> = input<IRtIcon.Name>('chevron-left');\n\n /** Значок стрелки «вперёд». */\n public readonly nextIcon: InputSignal<IRtIcon.Name> = input<IRtIcon.Name>('chevron-right');\n\n /** Счёт номеров: список под материальным набором просит семь мест первого кита. */\n public readonly numbering: InputSignal<IRtPagination.Numbering> = input<IRtPagination.Numbering>('neighbours');\n\n public readonly loading: InputSignalWithTransform<boolean, unknown> = input(false, {\n transform: booleanAttribute,\n });\n\n public readonly pageChange: OutputEmitterRef<number> = output<number>();\n\n public readonly perPageChange: OutputEmitterRef<number> = output<number>();\n\n /**\n * Пагинацию показываем, только когда есть что листать/менять: всё не влезает\n * на одну страницу даже при минимальной опции размера (`total > наименьший\n * perPageOption`). Иначе и навигация, и селектор размера бесполезны — прячем\n * весь бар (включая пустой и пустой-по-фильтру список).\n */\n public readonly isVisible: Signal<boolean> = computed((): boolean => {\n const options: ReadonlyArray<number> = this.perPageOptions();\n const smallest: number = options.length > 0 ? Math.min(...options) : 0;\n return this.pageModel().totalCount > smallest;\n });\n\n /** Сколько всего страниц при нынешнем размере страницы. */\n public readonly lastPage: Signal<number> = computed((): number => lastPageOf(this.pageModel()));\n\n /**\n * Границы диапазона записей открытой страницы. Собираются числами, а сама\n * подпись — в шаблоне: только там подстановка проходит через словарь и\n * переживает смену языка.\n */\n public readonly rangeFrom: Signal<number> = computed((): number => rangeFromOf(this.pageModel()));\n\n public readonly rangeTo: Signal<number> = computed((): number => rangeToOf(this.pageModel()));\n\n /** Полоса номеров страниц с разрывами «…». По соседям пуста при единственной странице. */\n public readonly pageItems: Signal<ReadonlyArray<IRtPagination.PageItem>> = computed((): ReadonlyArray<IRtPagination.PageItem> =>\n this.numbering() === 'seven' ? pageSlotsOf(this.pageModel()) : pageItemsOf(this.pageModel(), NEIGHBOURS)\n );\n\n public goTo(pageNumber: number): void {\n if (this.loading() || pageNumber === this.pageModel().pageNumber || pageNumber < 1 || pageNumber > this.lastPage()) {\n return;\n }\n this.pageChange.emit(pageNumber);\n }\n\n protected onPerPage(value: number | null): void {\n if (value === null || this.loading() || value === this.pageModel().pageSize) {\n return;\n }\n this.perPageChange.emit(value);\n }\n}\n","<ng-container rtBlock=\"rt-pagination\">\n <!--\n Ветки «ничего не найдено» здесь нет намеренно: пустой набор прячет весь\n бар целиком (`isVisible`), так что до этой строки дело не доходит. Пока\n такая ветка тут висела, она читалась как рабочее состояние, а показать\n её было нельзя ни при каких входах.\n -->\n <span rtElem=\"range\" qa-dataid=\"pagination-range\">\n {{ rangeLabel() }}\n </span>\n\n @if (pageItems().length) {\n <nav rtElem=\"compact\" qa-dataid=\"pagination-compact\" [attr.aria-label]=\"t().uiPagination\">\n <rt-icon-button\n qa-dataid=\"pagination-compact-prev\"\n variant=\"ghost\"\n size=\"sm\"\n [icon]=\"prevIcon()\"\n [ariaLabel]=\"t().uiPrevPage\"\n [tooltip]=\"t().uiBack\"\n [disabled]=\"isFirst() || loading()\"\n (clicked)=\"goTo(pageModel().pageNumber - 1)\" />\n\n <span rtElem=\"compact-label\" qa-dataid=\"pagination-compact-label\">\n {{ pageLabel() }}\n </span>\n\n <rt-icon-button\n qa-dataid=\"pagination-compact-next\"\n variant=\"ghost\"\n size=\"sm\"\n [icon]=\"nextIcon()\"\n [ariaLabel]=\"t().uiNextPage\"\n [tooltip]=\"t().uiForward\"\n [disabled]=\"isLast() || loading()\"\n (clicked)=\"goTo(pageModel().pageNumber + 1)\" />\n </nav>\n\n <nav rtElem=\"nav\" qa-dataid=\"pagination-nav\" [attr.aria-label]=\"t().uiPagination\">\n <rt-icon-button\n qa-dataid=\"pagination-prev\"\n variant=\"ghost\"\n size=\"sm\"\n [icon]=\"prevIcon()\"\n [ariaLabel]=\"t().uiPrevPage\"\n [tooltip]=\"t().uiBack\"\n [disabled]=\"isFirst() || loading()\"\n (clicked)=\"goTo(pageModel().pageNumber - 1)\" />\n\n @for (item of pageItems(); track $index) {\n @if (item === 'gap') {\n <span rtElem=\"gap\" aria-hidden=\"true\">…</span>\n } @else {\n <button\n rtElem=\"page\"\n qa-dataid=\"pagination-page\"\n type=\"button\"\n [attr.data-page]=\"item\"\n [rtMod]=\"{ current: item === pageModel().pageNumber }\"\n [attr.aria-current]=\"item === pageModel().pageNumber ? 'page' : null\"\n [disabled]=\"loading()\"\n (click)=\"goTo(item)\">\n {{ item }}\n </button>\n }\n }\n\n <rt-icon-button\n qa-dataid=\"pagination-next\"\n variant=\"ghost\"\n size=\"sm\"\n [icon]=\"nextIcon()\"\n [ariaLabel]=\"t().uiNextPage\"\n [tooltip]=\"t().uiForward\"\n [disabled]=\"isLast() || loading()\"\n (clicked)=\"goTo(pageModel().pageNumber + 1)\" />\n </nav>\n }\n\n <div rtElem=\"per-page\">\n <span rtElem=\"per-page-label\">{{ t().uiPerPage }}</span>\n <rt-select\n qa-dataid=\"pagination-per-page\"\n [ariaLabel]=\"t().uiItemsPerPage\"\n [options]=\"perPageSelectOptions()\"\n [clearable]=\"false\"\n [ngModel]=\"pageModel().pageSize\"\n [ngModelOptions]=\"{ standalone: true }\"\n (selectionChange)=\"onPerPage($event)\" />\n </div>\n</ng-container>\n"],"mappings":"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"}
|
|
@@ -111,7 +111,7 @@ var RtProfileMenuComponent = class RtProfileMenuComponent {
|
|
|
111
111
|
},
|
|
112
112
|
host: { classAttribute: "rt-profile-menu" },
|
|
113
113
|
ngImport: i0,
|
|
114
|
-
template: "<ng-container rtBlock=\"rt-profile-menu\">\n <div rtElem=\"user\">\n <span rtElem=\"avatar\" aria-hidden=\"true\">{{ avatar() }}</span>\n <span rtElem=\"name\" qa-dataid=\"profile-user-name\">{{ userName() }}</span>\n @if (organizationName()) {\n <span rtElem=\"organization\" qa-dataid=\"profile-organization\">\n {{ organizationName() }}\n <span rtElem=\"organization-label\">{{ t().profileMenuOrganization }}</span>\n </span>\n }\n </div>\n\n <div rtElem=\"nav\" role=\"menu\">\n @switch (organizationChange()) {\n @case ('allowed') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n [label]=\"t().profileMenuChangeOrganization\"\n (selected)=\"changeOrganization.emit()\" />\n }\n @case ('denied') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n disabled\n [label]=\"t().profileMenuChangeOrganization\"\n [tooltip]=\"t().profileMenuChangeOrganizationDenied\" />\n }\n }\n\n @if (passwordChange()) {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-password-change\"\n icon=\"ico-lock\"\n [label]=\"t().profileMenuChangePassword\"\n (selected)=\"changePassword.emit()\" />\n }\n\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-logout\"\n icon=\"ico-exit\"\n [disabled]=\"signOutDisabled()\"\n [label]=\"t().profileMenuSignOut\"\n (selected)=\"signOut.emit()\" />\n </div>\n\n <!-- Своего правила у переключателя языка нет: ширину ему задаёт колонка блока. -->\n @if (locales().length) {\n <rt-select\n qa-dataid=\"profile-locale-select\"\n name=\"rtProfileMenuLocale\"\n [options]=\"locales()\"\n [ngModel]=\"locale()\"\n (ngModelChange)=\"localeChange.emit($event)\" />\n }\n\n <rt-menu-item\n rtElem=\"theme\"\n qa-dataid=\"profile-theme-toggle\"\n [icon]=\"themeIcon()\"\n [label]=\"t().profileMenuSwitchTheme\"\n (selected)=\"onToggleTheme()\" />\n</ng-container>\n",
|
|
114
|
+
template: "<ng-container rtBlock=\"rt-profile-menu\">\n <div rtElem=\"user\">\n <span rtElem=\"avatar\" aria-hidden=\"true\">{{ avatar() }}</span>\n <span rtElem=\"name\" qa-dataid=\"profile-user-name\">{{ userName() }}</span>\n @if (organizationName()) {\n <span rtElem=\"organization\" qa-dataid=\"profile-organization\">\n {{ organizationName() }}\n <span rtElem=\"organization-label\">{{ t().profileMenuOrganization }}</span>\n </span>\n }\n </div>\n\n <div rtElem=\"nav\" role=\"menu\">\n @switch (organizationChange()) {\n @case ('allowed') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n [label]=\"t().profileMenuChangeOrganization\"\n (selected)=\"changeOrganization.emit()\" />\n }\n @case ('denied') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n disabled\n [label]=\"t().profileMenuChangeOrganization\"\n [tooltip]=\"t().profileMenuChangeOrganizationDenied\" />\n }\n }\n\n @if (passwordChange()) {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-password-change\"\n icon=\"ico-lock\"\n [label]=\"t().profileMenuChangePassword\"\n (selected)=\"changePassword.emit()\" />\n }\n\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-logout\"\n icon=\"ico-exit\"\n [disabled]=\"signOutDisabled()\"\n [label]=\"t().profileMenuSignOut\"\n (selected)=\"signOut.emit()\" />\n </div>\n\n <!-- Своего правила у переключателя языка нет: ширину ему задаёт колонка блока. -->\n @if (locales().length) {\n <rt-select\n qa-dataid=\"profile-locale-select\"\n name=\"rtProfileMenuLocale\"\n [options]=\"locales()\"\n [ngModel]=\"locale()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"localeChange.emit($event)\" />\n }\n\n <rt-menu-item\n rtElem=\"theme\"\n qa-dataid=\"profile-theme-toggle\"\n [icon]=\"themeIcon()\"\n [label]=\"t().profileMenuSwitchTheme\"\n (selected)=\"onToggleTheme()\" />\n</ng-container>\n",
|
|
115
115
|
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-profile-menu{display:flex;min-width:var(--rt-profile-menu-min-width);box-sizing:border-box;flex-direction:column;padding:var(--rt-profile-menu-padding);border:var(--rt-profile-menu-border-width) solid var(--rt-nav-panel-color-border);border-radius:var(--rt-profile-menu-radius);background-color:var(--rt-nav-panel-color-bg);box-shadow:var(--rt-profile-menu-shadow);gap:var(--rt-space-2)}.rt-profile-menu__user{display:flex;flex-direction:column;padding-bottom:var(--rt-space-2);gap:var(--rt-space-2)}.rt-profile-menu__avatar{display:inline-flex;width:var(--rt-profile-avatar-size);height:var(--rt-profile-avatar-size);align-items:center;justify-content:center;border:var(--rt-profile-avatar-border-width) solid var(--rt-nav-header-color-bg);border-radius:var(--rt-profile-avatar-radius);color:var(--rt-color-text-primary);font-size:var(--rt-profile-avatar-font-size);font-weight:var(--rt-font-weight-semibold);line-height:var(--rt-leading-none)}.rt-profile-menu__name{color:var(--rt-color-text-primary);font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-semibold);line-height:var(--rt-leading-tight)}.rt-profile-menu__organization{color:var(--rt-nav-panel-item-color);font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-regular);line-height:var(--rt-leading-tight)}.rt-profile-menu__organization-label{color:var(--rt-nav-panel-group-color)}.rt-profile-menu__nav{display:flex;width:calc(100% + var(--rt-profile-row-inset) + var(--rt-profile-row-inset));flex-direction:column;margin-left:calc(-1 * var(--rt-profile-row-inset))}.rt-profile-menu .rt-profile-menu__item,.rt-profile-menu .rt-profile-menu__theme{border-radius:var(--rt-profile-item-radius);color:var(--rt-nav-panel-item-color);font-size:var(--rt-profile-item-font-size);font-weight:var(--rt-profile-item-font-weight);gap:var(--rt-profile-item-content-gap)}.rt-profile-menu .rt-profile-menu__item{padding:var(--rt-profile-item-padding-y) var(--rt-profile-row-inset)}.rt-profile-menu .rt-profile-menu__theme{width:calc(100% + var(--rt-profile-row-inset) + var(--rt-profile-row-inset));padding:var(--rt-profile-row-inset);margin-left:calc(-1 * var(--rt-profile-row-inset));color:var(--rt-color-action-primary)}.rt-profile-menu .rt-profile-menu__theme .rt-menu-item__icon{box-sizing:content-box;padding:var(--rt-profile-theme-icon-padding);border-radius:var(--rt-profile-theme-icon-radius);background-color:var(--rt-color-action-primary-subtle)}}\n"],
|
|
116
116
|
dependencies: [
|
|
117
117
|
{
|
|
@@ -179,6 +179,7 @@ var RtProfileMenuComponent = class RtProfileMenuComponent {
|
|
|
179
179
|
"options",
|
|
180
180
|
"placeholder",
|
|
181
181
|
"iconLeft",
|
|
182
|
+
"floatingLabel",
|
|
182
183
|
"filter",
|
|
183
184
|
"filterPlaceholder",
|
|
184
185
|
"panelWidth",
|
|
@@ -211,7 +212,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
211
212
|
RtSelectComponent
|
|
212
213
|
],
|
|
213
214
|
host: { class: BEM_BLOCK },
|
|
214
|
-
template: "<ng-container rtBlock=\"rt-profile-menu\">\n <div rtElem=\"user\">\n <span rtElem=\"avatar\" aria-hidden=\"true\">{{ avatar() }}</span>\n <span rtElem=\"name\" qa-dataid=\"profile-user-name\">{{ userName() }}</span>\n @if (organizationName()) {\n <span rtElem=\"organization\" qa-dataid=\"profile-organization\">\n {{ organizationName() }}\n <span rtElem=\"organization-label\">{{ t().profileMenuOrganization }}</span>\n </span>\n }\n </div>\n\n <div rtElem=\"nav\" role=\"menu\">\n @switch (organizationChange()) {\n @case ('allowed') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n [label]=\"t().profileMenuChangeOrganization\"\n (selected)=\"changeOrganization.emit()\" />\n }\n @case ('denied') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n disabled\n [label]=\"t().profileMenuChangeOrganization\"\n [tooltip]=\"t().profileMenuChangeOrganizationDenied\" />\n }\n }\n\n @if (passwordChange()) {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-password-change\"\n icon=\"ico-lock\"\n [label]=\"t().profileMenuChangePassword\"\n (selected)=\"changePassword.emit()\" />\n }\n\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-logout\"\n icon=\"ico-exit\"\n [disabled]=\"signOutDisabled()\"\n [label]=\"t().profileMenuSignOut\"\n (selected)=\"signOut.emit()\" />\n </div>\n\n <!-- Своего правила у переключателя языка нет: ширину ему задаёт колонка блока. -->\n @if (locales().length) {\n <rt-select\n qa-dataid=\"profile-locale-select\"\n name=\"rtProfileMenuLocale\"\n [options]=\"locales()\"\n [ngModel]=\"locale()\"\n (ngModelChange)=\"localeChange.emit($event)\" />\n }\n\n <rt-menu-item\n rtElem=\"theme\"\n qa-dataid=\"profile-theme-toggle\"\n [icon]=\"themeIcon()\"\n [label]=\"t().profileMenuSwitchTheme\"\n (selected)=\"onToggleTheme()\" />\n</ng-container>\n",
|
|
215
|
+
template: "<ng-container rtBlock=\"rt-profile-menu\">\n <div rtElem=\"user\">\n <span rtElem=\"avatar\" aria-hidden=\"true\">{{ avatar() }}</span>\n <span rtElem=\"name\" qa-dataid=\"profile-user-name\">{{ userName() }}</span>\n @if (organizationName()) {\n <span rtElem=\"organization\" qa-dataid=\"profile-organization\">\n {{ organizationName() }}\n <span rtElem=\"organization-label\">{{ t().profileMenuOrganization }}</span>\n </span>\n }\n </div>\n\n <div rtElem=\"nav\" role=\"menu\">\n @switch (organizationChange()) {\n @case ('allowed') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n [label]=\"t().profileMenuChangeOrganization\"\n (selected)=\"changeOrganization.emit()\" />\n }\n @case ('denied') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n disabled\n [label]=\"t().profileMenuChangeOrganization\"\n [tooltip]=\"t().profileMenuChangeOrganizationDenied\" />\n }\n }\n\n @if (passwordChange()) {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-password-change\"\n icon=\"ico-lock\"\n [label]=\"t().profileMenuChangePassword\"\n (selected)=\"changePassword.emit()\" />\n }\n\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-logout\"\n icon=\"ico-exit\"\n [disabled]=\"signOutDisabled()\"\n [label]=\"t().profileMenuSignOut\"\n (selected)=\"signOut.emit()\" />\n </div>\n\n <!-- Своего правила у переключателя языка нет: ширину ему задаёт колонка блока. -->\n @if (locales().length) {\n <rt-select\n qa-dataid=\"profile-locale-select\"\n name=\"rtProfileMenuLocale\"\n [options]=\"locales()\"\n [ngModel]=\"locale()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"localeChange.emit($event)\" />\n }\n\n <rt-menu-item\n rtElem=\"theme\"\n qa-dataid=\"profile-theme-toggle\"\n [icon]=\"themeIcon()\"\n [label]=\"t().profileMenuSwitchTheme\"\n (selected)=\"onToggleTheme()\" />\n</ng-container>\n",
|
|
215
216
|
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-profile-menu{display:flex;min-width:var(--rt-profile-menu-min-width);box-sizing:border-box;flex-direction:column;padding:var(--rt-profile-menu-padding);border:var(--rt-profile-menu-border-width) solid var(--rt-nav-panel-color-border);border-radius:var(--rt-profile-menu-radius);background-color:var(--rt-nav-panel-color-bg);box-shadow:var(--rt-profile-menu-shadow);gap:var(--rt-space-2)}.rt-profile-menu__user{display:flex;flex-direction:column;padding-bottom:var(--rt-space-2);gap:var(--rt-space-2)}.rt-profile-menu__avatar{display:inline-flex;width:var(--rt-profile-avatar-size);height:var(--rt-profile-avatar-size);align-items:center;justify-content:center;border:var(--rt-profile-avatar-border-width) solid var(--rt-nav-header-color-bg);border-radius:var(--rt-profile-avatar-radius);color:var(--rt-color-text-primary);font-size:var(--rt-profile-avatar-font-size);font-weight:var(--rt-font-weight-semibold);line-height:var(--rt-leading-none)}.rt-profile-menu__name{color:var(--rt-color-text-primary);font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-semibold);line-height:var(--rt-leading-tight)}.rt-profile-menu__organization{color:var(--rt-nav-panel-item-color);font-size:var(--rt-text-md);font-weight:var(--rt-font-weight-regular);line-height:var(--rt-leading-tight)}.rt-profile-menu__organization-label{color:var(--rt-nav-panel-group-color)}.rt-profile-menu__nav{display:flex;width:calc(100% + var(--rt-profile-row-inset) + var(--rt-profile-row-inset));flex-direction:column;margin-left:calc(-1 * var(--rt-profile-row-inset))}.rt-profile-menu .rt-profile-menu__item,.rt-profile-menu .rt-profile-menu__theme{border-radius:var(--rt-profile-item-radius);color:var(--rt-nav-panel-item-color);font-size:var(--rt-profile-item-font-size);font-weight:var(--rt-profile-item-font-weight);gap:var(--rt-profile-item-content-gap)}.rt-profile-menu .rt-profile-menu__item{padding:var(--rt-profile-item-padding-y) var(--rt-profile-row-inset)}.rt-profile-menu .rt-profile-menu__theme{width:calc(100% + var(--rt-profile-row-inset) + var(--rt-profile-row-inset));padding:var(--rt-profile-row-inset);margin-left:calc(-1 * var(--rt-profile-row-inset));color:var(--rt-color-action-primary)}.rt-profile-menu .rt-profile-menu__theme .rt-menu-item__icon{box-sizing:content-box;padding:var(--rt-profile-theme-icon-padding);border-radius:var(--rt-profile-theme-icon-radius);background-color:var(--rt-color-action-primary-subtle)}}\n"]
|
|
216
217
|
}]
|
|
217
218
|
}],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rt-tools-ui-kit-v2-profile-menu.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/profile-menu/rt-profile-menu.component.ts","../../../projects/ui-kit-v2/src/lib/components/profile-menu/rt-profile-menu.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n computed,\n inject,\n input,\n output,\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { BlockDirective, ElemDirective } from '@rt-tools/core';\n\nimport { IRtIcon, RT_KIT_LABELS, ThemeService, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\n\nimport { RtMenuItemComponent } from '@rt-tools/ui-kit-v2/menu';\nimport { RtSelectComponent } from '@rt-tools/ui-kit-v2/select';\nimport { IRtProfileMenu } from './rt-profile-menu.model';\n\nconst BEM_BLOCK: string = 'rt-profile-menu';\n\n/**\n * Содержимое попапа профиля в шапке `rt-page-header`: кто вошёл и в какой организации, действия с\n * учётной записью, язык и тема.\n *\n * Свою панель меню рисует само — фон, рамку, скругление и тень: поповер кита оформления не даёт,\n * и голые пункты в нём легли бы прямо поверх страницы.\n *\n * Тему переключает `ThemeService`, как у `rt-theme-toggle`: служба одна на страницу, и вход\n * только повторял бы её. Куда ведут остальные действия, решает приложение — они уходят выходами.\n *\n * Стили без инкапсуляции: попап рисуется в перекрытии, у конца `<body>`, и правило по классу блока\n * достаёт до него, а до разметки `rt-menu-item` — тоже.\n */\n@Component({\n selector: 'rt-profile-menu',\n templateUrl: './rt-profile-menu.component.html',\n styleUrls: ['./rt-profile-menu.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // angular\n FormsModule,\n\n // rt-tools\n BlockDirective,\n ElemDirective,\n\n // standalone components / directives\n RtMenuItemComponent,\n RtSelectComponent,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtProfileMenuComponent {\n readonly #theme: ThemeService = inject(ThemeService);\n\n /** Подписи кита: сигнал, потому что язык может смениться без перезагрузки. */\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n /** Показан значок противоположной темы: нажатие переводит к ней. */\n protected readonly themeIcon: Signal<IRtIcon.Name> = computed((): IRtIcon.Name => (this.#theme.isDark() ? 'ico-sun' : 'moon'));\n\n /** Круг над именем несёт его первую букву: картинки профиля у кита нет. */\n protected readonly avatar: Signal<string> = computed((): string => this.userName().trim().charAt(0).toUpperCase());\n\n public readonly userName: InputSignal<string> = input<string>('');\n\n /** Пустое название — строки организации нет. */\n public readonly organizationName: InputSignal<string> = input<string>('');\n\n public readonly organizationChange: InputSignal<IRtProfileMenu.OrganizationChange> = input<IRtProfileMenu.OrganizationChange>('hidden');\n\n public readonly passwordChange: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Пустой список — переключателя языка нет. */\n public readonly locales: InputSignal<ReadonlyArray<IRtProfileMenu.Locale>> = input<ReadonlyArray<IRtProfileMenu.Locale>>([]);\n\n public readonly locale: InputSignal<string> = input<string>('');\n\n /** Выход недоступен, пока приложение его уже ведёт. */\n public readonly signOutDisabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly changeOrganization: OutputEmitterRef<void> = output<void>();\n\n public readonly changePassword: OutputEmitterRef<void> = output<void>();\n\n public readonly localeChange: OutputEmitterRef<string> = output<string>();\n\n public readonly signOut: OutputEmitterRef<void> = output<void>();\n\n public onToggleTheme(): void {\n this.#theme.toggle();\n }\n}\n","<ng-container rtBlock=\"rt-profile-menu\">\n <div rtElem=\"user\">\n <span rtElem=\"avatar\" aria-hidden=\"true\">{{ avatar() }}</span>\n <span rtElem=\"name\" qa-dataid=\"profile-user-name\">{{ userName() }}</span>\n @if (organizationName()) {\n <span rtElem=\"organization\" qa-dataid=\"profile-organization\">\n {{ organizationName() }}\n <span rtElem=\"organization-label\">{{ t().profileMenuOrganization }}</span>\n </span>\n }\n </div>\n\n <div rtElem=\"nav\" role=\"menu\">\n @switch (organizationChange()) {\n @case ('allowed') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n [label]=\"t().profileMenuChangeOrganization\"\n (selected)=\"changeOrganization.emit()\" />\n }\n @case ('denied') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n disabled\n [label]=\"t().profileMenuChangeOrganization\"\n [tooltip]=\"t().profileMenuChangeOrganizationDenied\" />\n }\n }\n\n @if (passwordChange()) {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-password-change\"\n icon=\"ico-lock\"\n [label]=\"t().profileMenuChangePassword\"\n (selected)=\"changePassword.emit()\" />\n }\n\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-logout\"\n icon=\"ico-exit\"\n [disabled]=\"signOutDisabled()\"\n [label]=\"t().profileMenuSignOut\"\n (selected)=\"signOut.emit()\" />\n </div>\n\n <!-- Своего правила у переключателя языка нет: ширину ему задаёт колонка блока. -->\n @if (locales().length) {\n <rt-select\n qa-dataid=\"profile-locale-select\"\n name=\"rtProfileMenuLocale\"\n [options]=\"locales()\"\n [ngModel]=\"locale()\"\n (ngModelChange)=\"localeChange.emit($event)\" />\n }\n\n <rt-menu-item\n rtElem=\"theme\"\n qa-dataid=\"profile-theme-toggle\"\n [icon]=\"themeIcon()\"\n [label]=\"t().profileMenuSwitchTheme\"\n (selected)=\"onToggleTheme()\" />\n</ng-container>\n"],"mappings":";;;;;;;;AAyBA,MAAM,YAAoB;AAqC1B,IAAa,yBAAb,MAAa,uBAAsB;CAtBnC,cAAA;EAuBa,KAAA,SAAuB,OAAO,YAAY;EAGhC,KAAA,IAA4B,OAAO,aAAa;EAGhD,KAAA,YAAkC,eAA8B,KAAK,OAAO,OAAM,IAAK,YAAY,QAAQ,GAAA,YAAA,CAAA,EAAA,WAAA,YAAA,CAAA,+BAAA,CAAA,CAAA;EAG3G,KAAA,SAAyB,eAAuB,KAAK,SAAQ,CAAE,CAAC,KAAI,CAAE,CAAC,OAAO,CAAC,CAAC,CAAC,YAAW,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;EAElG,KAAA,WAAgC,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;EAGjD,KAAA,mBAAwC,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,mBAAA,CAAA,+BAAA,CAAA,CAAA;EAEzD,KAAA,qBAAqE,MAAyC,UAAS,GAAA,YAAA,CAAA,EAAA,WAAA,qBAAA,CAAA,+BAAA,CAAA,CAAA;EAEvH,KAAA,iBAAkE,MAA6B,OAAK;GAAA,GAAA,YAAA,EAAA,WAAA,iBAAA,+BAAA,CAAA;GAChH,WAAW;EAAgB,CAAA;EAIf,KAAA,UAA6D,MAA4C,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;EAE5G,KAAA,SAA8B,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;EAG/C,KAAA,kBAAmE,MAA6B,OAAK;GAAA,GAAA,YAAA,EAAA,WAAA,kBAAA,+BAAA,CAAA;GACjH,WAAW;EAAgB,CAAA;EAGf,KAAA,qBAA6C,OAAM;EAEnD,KAAA,iBAAyC,OAAM;EAE/C,KAAA,eAAyC,OAAM;EAE/C,KAAA,UAAkC,OAAM;CAK3D;CA3CY;CAwCF,gBAAa;EAChB,KAAK,OAAO,OAAM;CACtB;CA3CS;EAAA,KAAA,OAAA,GAAA,mBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,UAAA;GAAA,MAAA;GAAsB,MAAA,CAAA;GAAA,QAAA,GAAA,gBAAA;EAAA,CAAA;CAAA;CAAtB;EAAA,KAAA,OAAA,GAAA,qBAAA;GAAA,YAAA;GAAA,SAAA;GAAA,MAAA;GAAsB,cAAA;GAAA,UAAA;GAAA,QAAA;IAAA,UAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,kBAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,oBAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,gBAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,SAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,QAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;IAAA,iBAAA;KAAA,mBAAA;KAAA,YAAA;KAAA,UAAA;KAAA,YAAA;KAAA,mBAAA;IAAA;GAAA;GAAA,SAAA;IAAA,oBAAA;IAAA,gBAAA;IAAA,cAAA;IAAA,SAAA;GAAA;GAAA,MAAA,EAAA,gBAAA,kBAAA;GAAA,UAAA;GAAA,UC9DnC;
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-profile-menu.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/profile-menu/rt-profile-menu.component.ts","../../../projects/ui-kit-v2/src/lib/components/profile-menu/rt-profile-menu.component.html"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n computed,\n inject,\n input,\n output,\n ChangeDetectionStrategy,\n Component,\n InputSignal,\n InputSignalWithTransform,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { BlockDirective, ElemDirective } from '@rt-tools/core';\n\nimport { IRtIcon, RT_KIT_LABELS, ThemeService, TRtKitLabelMap } from '@rt-tools/ui-kit-v2/core';\n\nimport { RtMenuItemComponent } from '@rt-tools/ui-kit-v2/menu';\nimport { RtSelectComponent } from '@rt-tools/ui-kit-v2/select';\nimport { IRtProfileMenu } from './rt-profile-menu.model';\n\nconst BEM_BLOCK: string = 'rt-profile-menu';\n\n/**\n * Содержимое попапа профиля в шапке `rt-page-header`: кто вошёл и в какой организации, действия с\n * учётной записью, язык и тема.\n *\n * Свою панель меню рисует само — фон, рамку, скругление и тень: поповер кита оформления не даёт,\n * и голые пункты в нём легли бы прямо поверх страницы.\n *\n * Тему переключает `ThemeService`, как у `rt-theme-toggle`: служба одна на страницу, и вход\n * только повторял бы её. Куда ведут остальные действия, решает приложение — они уходят выходами.\n *\n * Стили без инкапсуляции: попап рисуется в перекрытии, у конца `<body>`, и правило по классу блока\n * достаёт до него, а до разметки `rt-menu-item` — тоже.\n */\n@Component({\n selector: 'rt-profile-menu',\n templateUrl: './rt-profile-menu.component.html',\n styleUrls: ['./rt-profile-menu.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // angular\n FormsModule,\n\n // rt-tools\n BlockDirective,\n ElemDirective,\n\n // standalone components / directives\n RtMenuItemComponent,\n RtSelectComponent,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtProfileMenuComponent {\n readonly #theme: ThemeService = inject(ThemeService);\n\n /** Подписи кита: сигнал, потому что язык может смениться без перезагрузки. */\n protected readonly t: Signal<TRtKitLabelMap> = inject(RT_KIT_LABELS);\n\n /** Показан значок противоположной темы: нажатие переводит к ней. */\n protected readonly themeIcon: Signal<IRtIcon.Name> = computed((): IRtIcon.Name => (this.#theme.isDark() ? 'ico-sun' : 'moon'));\n\n /** Круг над именем несёт его первую букву: картинки профиля у кита нет. */\n protected readonly avatar: Signal<string> = computed((): string => this.userName().trim().charAt(0).toUpperCase());\n\n public readonly userName: InputSignal<string> = input<string>('');\n\n /** Пустое название — строки организации нет. */\n public readonly organizationName: InputSignal<string> = input<string>('');\n\n public readonly organizationChange: InputSignal<IRtProfileMenu.OrganizationChange> = input<IRtProfileMenu.OrganizationChange>('hidden');\n\n public readonly passwordChange: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Пустой список — переключателя языка нет. */\n public readonly locales: InputSignal<ReadonlyArray<IRtProfileMenu.Locale>> = input<ReadonlyArray<IRtProfileMenu.Locale>>([]);\n\n public readonly locale: InputSignal<string> = input<string>('');\n\n /** Выход недоступен, пока приложение его уже ведёт. */\n public readonly signOutDisabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly changeOrganization: OutputEmitterRef<void> = output<void>();\n\n public readonly changePassword: OutputEmitterRef<void> = output<void>();\n\n public readonly localeChange: OutputEmitterRef<string> = output<string>();\n\n public readonly signOut: OutputEmitterRef<void> = output<void>();\n\n public onToggleTheme(): void {\n this.#theme.toggle();\n }\n}\n","<ng-container rtBlock=\"rt-profile-menu\">\n <div rtElem=\"user\">\n <span rtElem=\"avatar\" aria-hidden=\"true\">{{ avatar() }}</span>\n <span rtElem=\"name\" qa-dataid=\"profile-user-name\">{{ userName() }}</span>\n @if (organizationName()) {\n <span rtElem=\"organization\" qa-dataid=\"profile-organization\">\n {{ organizationName() }}\n <span rtElem=\"organization-label\">{{ t().profileMenuOrganization }}</span>\n </span>\n }\n </div>\n\n <div rtElem=\"nav\" role=\"menu\">\n @switch (organizationChange()) {\n @case ('allowed') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n [label]=\"t().profileMenuChangeOrganization\"\n (selected)=\"changeOrganization.emit()\" />\n }\n @case ('denied') {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-change-organization\"\n icon=\"refresh\"\n disabled\n [label]=\"t().profileMenuChangeOrganization\"\n [tooltip]=\"t().profileMenuChangeOrganizationDenied\" />\n }\n }\n\n @if (passwordChange()) {\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-password-change\"\n icon=\"ico-lock\"\n [label]=\"t().profileMenuChangePassword\"\n (selected)=\"changePassword.emit()\" />\n }\n\n <rt-menu-item\n rtElem=\"item\"\n qa-dataid=\"profile-logout\"\n icon=\"ico-exit\"\n [disabled]=\"signOutDisabled()\"\n [label]=\"t().profileMenuSignOut\"\n (selected)=\"signOut.emit()\" />\n </div>\n\n <!-- Своего правила у переключателя языка нет: ширину ему задаёт колонка блока. -->\n @if (locales().length) {\n <rt-select\n qa-dataid=\"profile-locale-select\"\n name=\"rtProfileMenuLocale\"\n [options]=\"locales()\"\n [ngModel]=\"locale()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"localeChange.emit($event)\" />\n }\n\n <rt-menu-item\n rtElem=\"theme\"\n qa-dataid=\"profile-theme-toggle\"\n [icon]=\"themeIcon()\"\n [label]=\"t().profileMenuSwitchTheme\"\n (selected)=\"onToggleTheme()\" />\n</ng-container>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, ViewEncapsulation, computed, input, numberAttribute } from "@angular/core";
|
|
3
|
+
import { BlockDirective, ElemDirective, ModDirective } from "@rt-tools/core";
|
|
4
|
+
const BEM_BLOCK = "rt-progress-bar";
|
|
5
|
+
function clampProgress(value) {
|
|
6
|
+
if (Number.isNaN(value)) return 0;
|
|
7
|
+
return Math.min(100, Math.max(0, value));
|
|
8
|
+
}
|
|
9
|
+
var RtProgressBarComponent = class RtProgressBarComponent {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.determinate = computed(() => this.mode() === "determinate", ...ngDevMode ? [{ debugName: "determinate" }] : /* istanbul ignore next */ []);
|
|
12
|
+
this.percent = computed(() => Math.round(clampProgress(this.value())), ...ngDevMode ? [{ debugName: "percent" }] : /* istanbul ignore next */ []);
|
|
13
|
+
this.fillWidth = computed(() => this.determinate() ? clampProgress(this.value()) : null, ...ngDevMode ? [{ debugName: "fillWidth" }] : /* istanbul ignore next */ []);
|
|
14
|
+
this.mode = input("determinate", ...ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []);
|
|
15
|
+
this.value = input(0, {
|
|
16
|
+
...ngDevMode ? { debugName: "value" } : /* istanbul ignore next */ {},
|
|
17
|
+
transform: numberAttribute
|
|
18
|
+
});
|
|
19
|
+
this.color = input("primary", ...ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []);
|
|
20
|
+
this.ariaLabel = input(null, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
|
|
21
|
+
}
|
|
22
|
+
static {
|
|
23
|
+
this.ɵfac = i0.ɵɵngDeclareFactory({
|
|
24
|
+
minVersion: "12.0.0",
|
|
25
|
+
version: "22.2.2",
|
|
26
|
+
ngImport: i0,
|
|
27
|
+
type: RtProgressBarComponent,
|
|
28
|
+
deps: [],
|
|
29
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
static {
|
|
33
|
+
this.ɵcmp = i0.ɵɵngDeclareComponent({
|
|
34
|
+
minVersion: "17.1.0",
|
|
35
|
+
version: "22.2.2",
|
|
36
|
+
type: RtProgressBarComponent,
|
|
37
|
+
isStandalone: true,
|
|
38
|
+
selector: "rt-progress-bar",
|
|
39
|
+
inputs: {
|
|
40
|
+
mode: {
|
|
41
|
+
classPropertyName: "mode",
|
|
42
|
+
publicName: "mode",
|
|
43
|
+
isSignal: true,
|
|
44
|
+
isRequired: false,
|
|
45
|
+
transformFunction: null
|
|
46
|
+
},
|
|
47
|
+
value: {
|
|
48
|
+
classPropertyName: "value",
|
|
49
|
+
publicName: "value",
|
|
50
|
+
isSignal: true,
|
|
51
|
+
isRequired: false,
|
|
52
|
+
transformFunction: null
|
|
53
|
+
},
|
|
54
|
+
color: {
|
|
55
|
+
classPropertyName: "color",
|
|
56
|
+
publicName: "color",
|
|
57
|
+
isSignal: true,
|
|
58
|
+
isRequired: false,
|
|
59
|
+
transformFunction: null
|
|
60
|
+
},
|
|
61
|
+
ariaLabel: {
|
|
62
|
+
classPropertyName: "ariaLabel",
|
|
63
|
+
publicName: "ariaLabel",
|
|
64
|
+
isSignal: true,
|
|
65
|
+
isRequired: false,
|
|
66
|
+
transformFunction: null
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
host: {
|
|
70
|
+
attributes: {
|
|
71
|
+
"role": "progressbar",
|
|
72
|
+
"qa-dataid": "progress-bar",
|
|
73
|
+
"aria-valuemin": "0",
|
|
74
|
+
"aria-valuemax": "100"
|
|
75
|
+
},
|
|
76
|
+
properties: {
|
|
77
|
+
"attr.aria-valuenow": "determinate() ? percent() : null",
|
|
78
|
+
"attr.aria-label": "ariaLabel()",
|
|
79
|
+
"class.rt-progress-bar--indeterminate": "!determinate()",
|
|
80
|
+
"class": "\"rt-progress-bar--color--\" + color()"
|
|
81
|
+
},
|
|
82
|
+
classAttribute: "rt-progress-bar"
|
|
83
|
+
},
|
|
84
|
+
ngImport: i0,
|
|
85
|
+
template: "<ng-container rtBlock=\"rt-progress-bar\">\n <span rtElem=\"fill\" qa-dataid=\"progress-bar-fill\" aria-hidden=\"true\" [style.width.%]=\"fillWidth()\"></span>\n</ng-container>\n",
|
|
86
|
+
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-progress-bar{--rt-progress-bar-height: var(--rt-size-1);--rt-progress-bar-radius: var(--rt-radius-full);--rt-progress-bar-track: var(--rt-color-border-default);--rt-progress-bar-fill: var(--rt-color-action-primary);--rt-progress-bar-duration: var(--rt-duration-base);--rt-progress-bar-sweep-duration: var(--rt-duration-slower);position:relative;display:block;overflow:hidden;width:100%;height:var(--rt-progress-bar-height);border-radius:var(--rt-progress-bar-radius);background:var(--rt-progress-bar-track)}.rt-progress-bar__fill{position:absolute;display:block;border-radius:inherit;background:var(--rt-progress-bar-fill);inset-block:0;inset-inline-start:0;transition:width var(--rt-progress-bar-duration) ease-out}.rt-progress-bar--indeterminate .rt-progress-bar__fill{width:35%;animation:rt-progress-bar-sweep calc(var(--rt-progress-bar-sweep-duration) * 3) ease-in-out infinite}.rt-progress-bar--color--secondary{--rt-progress-bar-fill: var(--rt-color-action-secondary)}.rt-progress-bar--color--info{--rt-progress-bar-fill: var(--rt-color-action-info)}.rt-progress-bar--color--success{--rt-progress-bar-fill: var(--rt-color-action-success)}.rt-progress-bar--color--warning{--rt-progress-bar-fill: var(--rt-color-action-warning)}.rt-progress-bar--color--danger{--rt-progress-bar-fill: var(--rt-color-action-danger)}@media(prefers-reduced-motion:reduce){.rt-progress-bar__fill{transition:none}.rt-progress-bar--indeterminate .rt-progress-bar__fill{width:100%;animation:none}}@keyframes rt-progress-bar-sweep{0%{inset-inline-start:-35%}to{inset-inline-start:100%}}}\n"],
|
|
87
|
+
dependencies: [{
|
|
88
|
+
kind: "directive",
|
|
89
|
+
type: BlockDirective,
|
|
90
|
+
selector: "[rtBlock]",
|
|
91
|
+
inputs: ["rtMod"]
|
|
92
|
+
}, {
|
|
93
|
+
kind: "directive",
|
|
94
|
+
type: ElemDirective,
|
|
95
|
+
selector: "[rtElem]",
|
|
96
|
+
inputs: ["rtMod"]
|
|
97
|
+
}],
|
|
98
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
99
|
+
encapsulation: i0.ViewEncapsulation.None
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
104
|
+
minVersion: "12.0.0",
|
|
105
|
+
version: "22.2.2",
|
|
106
|
+
ngImport: i0,
|
|
107
|
+
type: RtProgressBarComponent,
|
|
108
|
+
decorators: [{
|
|
109
|
+
type: Component,
|
|
110
|
+
args: [{
|
|
111
|
+
selector: "rt-progress-bar",
|
|
112
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
113
|
+
encapsulation: ViewEncapsulation.None,
|
|
114
|
+
imports: [
|
|
115
|
+
BlockDirective,
|
|
116
|
+
ElemDirective,
|
|
117
|
+
ModDirective
|
|
118
|
+
],
|
|
119
|
+
host: {
|
|
120
|
+
class: BEM_BLOCK,
|
|
121
|
+
role: "progressbar",
|
|
122
|
+
"qa-dataid": "progress-bar",
|
|
123
|
+
"aria-valuemin": "0",
|
|
124
|
+
"aria-valuemax": "100",
|
|
125
|
+
"[attr.aria-valuenow]": "determinate() ? percent() : null",
|
|
126
|
+
"[attr.aria-label]": "ariaLabel()",
|
|
127
|
+
"[class.rt-progress-bar--indeterminate]": "!determinate()",
|
|
128
|
+
"[class]": "\"rt-progress-bar--color--\" + color()"
|
|
129
|
+
},
|
|
130
|
+
template: "<ng-container rtBlock=\"rt-progress-bar\">\n <span rtElem=\"fill\" qa-dataid=\"progress-bar-fill\" aria-hidden=\"true\" [style.width.%]=\"fillWidth()\"></span>\n</ng-container>\n",
|
|
131
|
+
styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-progress-bar{--rt-progress-bar-height: var(--rt-size-1);--rt-progress-bar-radius: var(--rt-radius-full);--rt-progress-bar-track: var(--rt-color-border-default);--rt-progress-bar-fill: var(--rt-color-action-primary);--rt-progress-bar-duration: var(--rt-duration-base);--rt-progress-bar-sweep-duration: var(--rt-duration-slower);position:relative;display:block;overflow:hidden;width:100%;height:var(--rt-progress-bar-height);border-radius:var(--rt-progress-bar-radius);background:var(--rt-progress-bar-track)}.rt-progress-bar__fill{position:absolute;display:block;border-radius:inherit;background:var(--rt-progress-bar-fill);inset-block:0;inset-inline-start:0;transition:width var(--rt-progress-bar-duration) ease-out}.rt-progress-bar--indeterminate .rt-progress-bar__fill{width:35%;animation:rt-progress-bar-sweep calc(var(--rt-progress-bar-sweep-duration) * 3) ease-in-out infinite}.rt-progress-bar--color--secondary{--rt-progress-bar-fill: var(--rt-color-action-secondary)}.rt-progress-bar--color--info{--rt-progress-bar-fill: var(--rt-color-action-info)}.rt-progress-bar--color--success{--rt-progress-bar-fill: var(--rt-color-action-success)}.rt-progress-bar--color--warning{--rt-progress-bar-fill: var(--rt-color-action-warning)}.rt-progress-bar--color--danger{--rt-progress-bar-fill: var(--rt-color-action-danger)}@media(prefers-reduced-motion:reduce){.rt-progress-bar__fill{transition:none}.rt-progress-bar--indeterminate .rt-progress-bar__fill{width:100%;animation:none}}@keyframes rt-progress-bar-sweep{0%{inset-inline-start:-35%}to{inset-inline-start:100%}}}\n"]
|
|
132
|
+
}]
|
|
133
|
+
}],
|
|
134
|
+
propDecorators: {
|
|
135
|
+
mode: [{
|
|
136
|
+
type: i0.Input,
|
|
137
|
+
args: [{
|
|
138
|
+
isSignal: true,
|
|
139
|
+
alias: "mode",
|
|
140
|
+
required: false
|
|
141
|
+
}]
|
|
142
|
+
}],
|
|
143
|
+
value: [{
|
|
144
|
+
type: i0.Input,
|
|
145
|
+
args: [{
|
|
146
|
+
isSignal: true,
|
|
147
|
+
alias: "value",
|
|
148
|
+
required: false
|
|
149
|
+
}]
|
|
150
|
+
}],
|
|
151
|
+
color: [{
|
|
152
|
+
type: i0.Input,
|
|
153
|
+
args: [{
|
|
154
|
+
isSignal: true,
|
|
155
|
+
alias: "color",
|
|
156
|
+
required: false
|
|
157
|
+
}]
|
|
158
|
+
}],
|
|
159
|
+
ariaLabel: [{
|
|
160
|
+
type: i0.Input,
|
|
161
|
+
args: [{
|
|
162
|
+
isSignal: true,
|
|
163
|
+
alias: "ariaLabel",
|
|
164
|
+
required: false
|
|
165
|
+
}]
|
|
166
|
+
}]
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
export { RtProgressBarComponent, clampProgress };
|
|
170
|
+
|
|
171
|
+
//# sourceMappingURL=rt-tools-ui-kit-v2-progress-bar.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rt-tools-ui-kit-v2-progress-bar.mjs","names":[],"sources":["../../../projects/ui-kit-v2/src/lib/components/progress-bar/rt-progress-bar.component.ts","../../../projects/ui-kit-v2/src/lib/components/progress-bar/rt-progress-bar.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n input,\n InputSignal,\n InputSignalWithTransform,\n numberAttribute,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { IRtProgressBar } from './rt-progress-bar.model';\n\nconst BEM_BLOCK: string = 'rt-progress-bar';\n\n/** Доля, зажатая в 0–100: значение из потока может выйти за края, полоса и объявление — нет. */\nexport function clampProgress(value: number): number {\n if (Number.isNaN(value)) {\n return 0;\n }\n\n return Math.min(100, Math.max(0, value));\n}\n\n/**\n * Полоса прогресса: дорожка во всю ширину и заполнение поверх. В режиме `determinate` заполнение\n * равно `value` процентов и плавно идёт за ним — так полоса показывает живой прогресс задачи из\n * потока. В режиме `indeterminate` по дорожке бежит отрезок: доля неизвестна, известно, что\n * работа идёт.\n *\n * Для чтения с экрана полоса — `progressbar` с долей; без доли значение не объявляется.\n */\n@Component({\n selector: 'rt-progress-bar',\n templateUrl: './rt-progress-bar.component.html',\n styleUrl: './rt-progress-bar.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // directives\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n host: {\n class: BEM_BLOCK,\n role: 'progressbar',\n 'qa-dataid': 'progress-bar',\n 'aria-valuemin': '0',\n 'aria-valuemax': '100',\n '[attr.aria-valuenow]': 'determinate() ? percent() : null',\n '[attr.aria-label]': 'ariaLabel()',\n '[class.rt-progress-bar--indeterminate]': '!determinate()',\n '[class]': '\"rt-progress-bar--color--\" + color()',\n },\n})\nexport class RtProgressBarComponent {\n protected readonly determinate: Signal<boolean> = computed((): boolean => this.mode() === 'determinate');\n\n protected readonly percent: Signal<number> = computed((): number => Math.round(clampProgress(this.value())));\n\n /** Ширина заполнения: в режиме без доли её задаёт движение, а не вход. */\n protected readonly fillWidth: Signal<number | null> = computed((): number | null =>\n this.determinate() ? clampProgress(this.value()) : null\n );\n\n public readonly mode: InputSignal<IRtProgressBar.Mode> = input<IRtProgressBar.Mode>('determinate');\n\n /** Доля в процентах, 0–100; что выходит за края, прижимается к ним. */\n public readonly value: InputSignalWithTransform<number, unknown> = input(0, { transform: numberAttribute });\n\n public readonly color: InputSignal<IRtProgressBar.Color> = input<IRtProgressBar.Color>('primary');\n\n /** Что за прогресс — для чтения с экрана, когда рядом нет видимой подписи. */\n public readonly ariaLabel: InputSignal<string | null> = input<string | null>(null);\n}\n","<ng-container rtBlock=\"rt-progress-bar\">\n <span rtElem=\"fill\" qa-dataid=\"progress-bar-fill\" aria-hidden=\"true\" [style.width.%]=\"fillWidth()\"></span>\n</ng-container>\n"],"mappings":"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"}
|