ngx-register-base 1.2.2 → 1.2.3

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, computed, signal, ChangeDetectionStrategy, Component, inject, Injectable, InjectionToken, Optional, DestroyRef, NgZone, afterNextRender, Input, viewChild, TemplateRef, effect, untracked, output, ɵRuntimeError as _RuntimeError, ChangeDetectorRef, forwardRef, Self, Directive, EventEmitter, Output, ViewChild, HostBinding, contentChildren, runInInjectionContext, Injector, NgModule, Pipe, Inject, HostListener, ElementRef, Renderer2, model, viewChildren } from '@angular/core';
2
+ import { input, computed, signal, ChangeDetectionStrategy, Component, inject, Injectable, InjectionToken, Optional, DestroyRef, NgZone, afterNextRender, Input, viewChild, TemplateRef, effect, untracked, output, HostBinding, ɵRuntimeError as _RuntimeError, ChangeDetectorRef, forwardRef, Self, Directive, EventEmitter, Output, ViewChild, contentChildren, runInInjectionContext, Injector, NgModule, Pipe, Inject, HostListener, ElementRef, Renderer2, model, viewChildren } from '@angular/core';
3
3
  import * as i1 from '@angular/router';
4
4
  import { Router, NavigationStart, RouterLink } from '@angular/router';
5
5
  import { BehaviorSubject, Subject, distinctUntilChanged, asyncScheduler, of, filter, map, takeUntil, ReplaySubject, take, skip, fromEvent, debounceTime, tap, switchMap, combineLatest, catchError, throwError, pairwise, delay, mergeMap, iif, expand, from, EMPTY, Observable, animationFrameScheduler } from 'rxjs';
@@ -11,7 +11,7 @@ import { moveItemInArray, transferArrayItem, CdkDrag, CdkDragPlaceholder, CdkDro
11
11
  import { takeUntilDestroyed, toObservable, toSignal, outputFromObservable } from '@angular/core/rxjs-interop';
12
12
  import { WaResizeObserver } from '@ng-web-apis/resize-observer';
13
13
  import * as i1$2 from '@angular/common';
14
- import { NgOptimizedImage, CommonModule, NgIf, NgTemplateOutlet, NgSwitch, NgSwitchCase, NgSwitchDefault, DOCUMENT, AsyncPipe, NgClass, NgForOf, NgStyle, DecimalPipe } from '@angular/common';
14
+ import { NgOptimizedImage, NgTemplateOutlet, NgClass, AsyncPipe, CommonModule, NgIf, NgSwitch, NgSwitchCase, NgSwitchDefault, DOCUMENT, NgForOf, NgStyle, DecimalPipe } from '@angular/common';
15
15
  import { TuiExpand } from '@taiga-ui/experimental';
16
16
  import * as i3 from '@prizm-ui/components';
17
17
  import { PrizmDialogService, PrizmOverlayInsidePlacement, PrizmDateTimeRange, PrizmDayRange, PrizmTimeRange, PrizmTime, PrizmDay, PrizmTableModule, PrizmScrollbarModule, PrizmCheckboxComponent, PrizmStickyModule, PrizmButtonComponent, PrizmInputTextModule, PrizmPaginatorComponent, PrizmInputSelectModule, PrizmPanelComponent, PrizmToggleComponent, PrizmTabsModule, PrizmDropdownHostModule, PrizmLoaderComponent, PrizmSelectInputComponent, PrizmInputMultiSelectModule, PrizmInputLayoutDateModule, PrizmInputLayoutDateRangeModule, PrizmDialogComponent, PrizmInputLayoutDateComponent, PrizmColumnSettingsComponent, PrizmSwitcherComponent, PrizmTooltipModule, PrizmInputMultiSelectComponent, PrizmInputLayoutDateRangeComponent, PrizmSidebarComponent, PrizmToastModule, PrizmInputLayoutDateTimeModule, PrizmInputCommonModule, PrizmInputIconButtonComponent, PrizmInputLayoutMonthModule, PrizmHintDirective, PrizmTreeModule, PrizmInputNumberModule, PrizmInputLayoutDateTimeRangeModule, PrizmProgressModule, PrizmInputLayoutTimeModule, PrizmInputLayoutMonthRangeComponent, PrizmInputLayoutDateTimeRangeComponent, PrizmSplitterModule, PrizmCardComponent, PrizmDropdownControllerDirective, PrizmRadioButtonComponent, PrizmBreadcrumbDirective, PrizmBreadcrumbsComponent, PrizmStepperModule, PrizmIndicatorComponent, PrizmScrollbarComponent, PrizmDateTime, PrizmMonth, PrizmMonthRange, PolymorphModule } from '@prizm-ui/components';
@@ -23,6 +23,7 @@ import * as i2 from '@angular/forms';
23
23
  import { FormControl, FormGroup, FormArray, Validators, NgControl, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
24
24
  import { observeOn, startWith, shareReplay, map as map$1, filter as filter$1, switchMap as switchMap$1, tap as tap$1, takeUntil as takeUntil$1 } from 'rxjs/operators';
25
25
  import _, { isEqual } from 'lodash';
26
+ import { trigger, transition, style, animate } from '@angular/animations';
26
27
  import { Apollo } from 'apollo-angular';
27
28
  import gql from 'graphql-tag';
28
29
  import { ComponentStore } from '@ngrx/component-store';
@@ -38,7 +39,6 @@ import * as i3$3 from '@taiga-ui/core/components/data-list';
38
39
  import * as i4 from '@taiga-ui/kit/components/data-list-wrapper';
39
40
  import { MaskitoDirective } from '@maskito/angular';
40
41
  import { TuiInputSearch } from '@taiga-ui/layout';
41
- import { trigger, transition, style, animate } from '@angular/animations';
42
42
  import * as i1$5 from '@taiga-ui/addon-table';
43
43
  import { TuiTable } from '@taiga-ui/addon-table';
44
44
  import { coerceNumberProperty } from '@angular/cdk/coercion';
@@ -1526,140 +1526,420 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
1526
1526
  args: [{ selector: 'sproc-filter-button', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TuiButton, TuiHint, NgOptimizedImage], template: "<button\n tuiButton\n size=\"m\"\n appearance=\"outline-grayscale\"\n tuiHint\n tuiHintDirection=\"bottom\"\n [class.--indicator]=\"filterApplied()\"\n [disabled]=\"disabled()\"\n (click)=\"filterToggle.emit()\"\n>\n <img ngSrc=\"assets/ngx-register-base/icons/filter.svg\" alt=\"\" height=\"16\" width=\"16\" />\n\n <tui-hint\n *tuiHint\n class=\"filter-button__tooltip\"\n [class.filter-button__tooltip--showed]=\"filterApplied()\"\n >\n <span>\u041A \u0440\u0435\u0435\u0441\u0442\u0440\u0443 \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u044B \u0444\u0438\u043B\u044C\u0442\u0440\u044B</span>\n </tui-hint>\n</button>\n", styles: [":host button{width:var(--top-bar-button-width);height:var(--top-bar-button-height);border-radius:2px;padding:10px;position:relative}:host button:disabled{filter:grayscale(100%)!important;cursor:not-allowed}:host button.--indicator:after{content:\"\";display:block;width:8px;height:8px;border-radius:50%;background-color:var(--brand-danger);position:absolute;top:10px;right:6px}.filter-button__tooltip{background-color:var(--brand-danger-light)!important;padding:16px;border:1px solid var(--brand-danger);border-left-width:4px;display:none}.filter-button__tooltip span{font:var(--input-text-12px);color:var(--main-black)}.filter-button__tooltip--showed{display:unset}\n"] }]
1527
1527
  }] });
1528
1528
 
1529
- const MENU_STATE_SERVICE = new InjectionToken('MENU_STATE_SERVICE');
1529
+ const SIDE_MENU_OPENED_WIDTH = 350;
1530
+ const SIDE_MENU_CLOSED_WIDTH = 48;
1531
+ var EPageMenuIconsSrc;
1532
+ (function (EPageMenuIconsSrc) {
1533
+ EPageMenuIconsSrc["CHEVRON_RIGHT"] = "assets/ngx-register-base/icons/chevron-right.svg";
1534
+ EPageMenuIconsSrc["CHEVRON_UP"] = "assets/ngx-register-base/icons/chevron-up.svg";
1535
+ EPageMenuIconsSrc["MENU_CHEVRON"] = "assets/ngx-register-base/icons/chevron-menu.svg";
1536
+ })(EPageMenuIconsSrc || (EPageMenuIconsSrc = {}));
1530
1537
 
1531
- var ERuntimeErrorCode;
1532
- (function (ERuntimeErrorCode) {
1533
- // Structure validation errors
1534
- ERuntimeErrorCode[ERuntimeErrorCode["NO_CONTROLS"] = 1000] = "NO_CONTROLS";
1535
- ERuntimeErrorCode[ERuntimeErrorCode["MISSING_CONTROL"] = 1001] = "MISSING_CONTROL";
1536
- ERuntimeErrorCode[ERuntimeErrorCode["MISSING_CONTROL_VALUE"] = 1002] = "MISSING_CONTROL_VALUE";
1537
- })(ERuntimeErrorCode || (ERuntimeErrorCode = {}));
1538
+ const PAGE_MENU_STATE = new InjectionToken('PAGE_MENU_STATE');
1539
+ // export const PAGE_MENU_STORE = new InjectionToken<AbstractMenuStateService>('PAGE_MENU_STATE');
1538
1540
 
1539
- function assertAllValuesPresent(control, isGroup, value) {
1540
- control._forEachChild((_, key) => {
1541
- if (value[key] === undefined) {
1542
- throw new _RuntimeError(ERuntimeErrorCode.MISSING_CONTROL_VALUE, '');
1543
- }
1544
- });
1545
- }
1546
- function assertControlPresent(parent, isGroup, key) {
1547
- const controls = parent.controls;
1548
- const collection = isGroup ? Object.keys(controls) : controls;
1549
- if (collection.length === 0) {
1550
- throw new _RuntimeError(ERuntimeErrorCode.NO_CONTROLS, '');
1551
- }
1552
- if (!controls[key]) {
1553
- throw new _RuntimeError(ERuntimeErrorCode.MISSING_CONTROL, '');
1541
+ class SprocPageMenuComponent {
1542
+ constructor() {
1543
+ this.menuItems = input.required();
1544
+ this.menuIconsSrc = input('');
1545
+ this.openLogoSrc = input('');
1546
+ this.closedLogoSrc = input('');
1547
+ this.findActiveSection = input.required();
1548
+ // TODO Добавить кастомную ширину меню
1549
+ this.menuOpenedWidth = `${SIDE_MENU_OPENED_WIDTH}px`;
1550
+ this.menuClosedWidth = `${SIDE_MENU_CLOSED_WIDTH}px`;
1551
+ this._router = inject(Router);
1552
+ this._state = inject(PAGE_MENU_STATE);
1553
+ this._dr = inject(DestroyRef);
1554
+ this.toggleDisabled$ = this._state.toggleDisabled$;
1555
+ this.menuState = toSignal(this._state.isOpen$);
1556
+ this.selectedSection = signal('register');
1557
+ this.expandedIds = signal(new Set());
1558
+ this.selectedItem = computed(() => this.selectedSection() ? this.codeToItem[this.selectedSection()] : null);
1559
+ // Хранит parent элементы выбранного пункта меню
1560
+ this.parentItems = computed(() => {
1561
+ const item = this.selectedItem();
1562
+ if (!item) {
1563
+ return [];
1564
+ }
1565
+ const parents = [];
1566
+ let current = item.parent;
1567
+ while (current) {
1568
+ parents.push(current);
1569
+ current = current.parent;
1570
+ }
1571
+ return parents;
1572
+ });
1573
+ this.parentItemCodes = computed(() => {
1574
+ const parentItems = this.parentItems();
1575
+ return new Set(parentItems.map((val) => val.code ?? ''));
1576
+ });
1577
+ this.navigationHierarchy = signal([]);
1578
+ this.codeToItem = {};
1579
+ this.isOpenServiceVersionInfo = false;
1580
+ this.ICONS_SRC = EPageMenuIconsSrc;
1581
+ // Построить меню и найти активную секцию
1582
+ effect(() => {
1583
+ const menuItems = this.menuItems();
1584
+ this.buildMenu(menuItems);
1585
+ this._findActiveSection();
1586
+ }, { allowSignalWrites: true });
1554
1587
  }
1555
- }
1556
- /** @deprecated заменить на FormGroup */
1557
- class FormGroupWrapper extends FormGroup {
1558
- setValue(value, options) {
1559
- assertAllValuesPresent(this, true, value);
1560
- for (const name of Object.keys(value)) {
1561
- assertControlPresent(this, true, name);
1562
- const control = this.controls[name];
1563
- const currentValue = value[name];
1564
- if (control instanceof FormArray && Array.isArray(currentValue)) {
1565
- control.clear();
1566
- for (const item of currentValue) {
1567
- item.setParent(control);
1568
- control.push(item, { emitEvent: options?.emitEvent });
1588
+ addMenuScrollbar(id) {
1589
+ setTimeout(() => {
1590
+ // TODO Меню второго уровня есть скролл,третьего нет
1591
+ const collapsedMenu = document.querySelector(`[id="${id}"]`);
1592
+ const sideMenu = collapsedMenu?.querySelector('#side-menu__subitems');
1593
+ const sideMenuLevelTwo = sideMenu?.querySelector('#side-menu__subitems');
1594
+ const subitem = sideMenuLevelTwo
1595
+ ? sideMenuLevelTwo.querySelectorAll('.side-menu__subitem')
1596
+ : sideMenu?.querySelectorAll('.side-menu__subitem');
1597
+ if (subitem) {
1598
+ const lastSubitem = subitem[subitem.length - 1];
1599
+ const rect = lastSubitem?.getBoundingClientRect();
1600
+ if (sideMenu && window.innerHeight - rect.bottom < 0) {
1601
+ // 40 тк высота плашки меню
1602
+ sideMenu.style.height = `${subitem.length * 40 + (window.innerHeight - rect.bottom - 1)}px`;
1603
+ sideMenu.style.overflowY = 'scroll';
1604
+ sideMenu.style.overflowX = 'hidden';
1605
+ }
1606
+ if (window.innerHeight - rect.bottom < 0 && sideMenuLevelTwo) {
1607
+ // 40 тк высота плашки меню
1608
+ sideMenuLevelTwo.style.height = `${subitem.length * 40 + (window.innerHeight - rect.bottom - 1)}px`;
1609
+ sideMenuLevelTwo.style.overflowY = 'scroll';
1610
+ sideMenuLevelTwo.style.overflowX = 'hidden';
1569
1611
  }
1570
1612
  }
1613
+ }, 0);
1614
+ }
1615
+ ngOnInit() {
1616
+ this._state.isOpen$.subscribe((menuState) => {
1617
+ if (menuState) {
1618
+ this.findRoute(this.selectedSection());
1619
+ }
1571
1620
  else {
1572
- control.setValue(currentValue, {
1573
- onlySelf: true,
1574
- emitEvent: options?.emitEvent,
1575
- });
1621
+ this.collapseMenu();
1576
1622
  }
1577
- }
1578
- this.updateValueAndValidity(options);
1623
+ });
1579
1624
  }
1580
- patchValue(value, options) {
1581
- if (value === null) {
1582
- return;
1583
- }
1584
- for (const name of Object.keys(value)) {
1585
- const control = this.controls[name];
1586
- const currentValue = value[name];
1587
- if (control) {
1588
- if (control instanceof FormArray && Array.isArray(currentValue)) {
1589
- control.clear();
1590
- for (const item of currentValue) {
1591
- item.setParent(control);
1592
- control.push(item, { emitEvent: options?.emitEvent });
1593
- }
1594
- }
1595
- else {
1596
- control.patchValue(currentValue, {
1597
- onlySelf: true,
1598
- emitEvent: options?.emitEvent,
1599
- });
1625
+ toggleNavigation() {
1626
+ this._state.toggle();
1627
+ }
1628
+ toggleItem(item) {
1629
+ this.addMenuScrollbar(item.id || '');
1630
+ this.expandedIds.update((currentExpand) => {
1631
+ const code = item.code;
1632
+ const copy = new Set(currentExpand);
1633
+ if (copy.has(code)) {
1634
+ copy.delete(code);
1635
+ }
1636
+ else {
1637
+ copy.clear();
1638
+ copy.add(code);
1639
+ const parents = this.getParents(item);
1640
+ for (const parent of parents) {
1641
+ copy.add(parent.code);
1600
1642
  }
1601
1643
  }
1602
- }
1603
- this.updateValueAndValidity(options);
1644
+ return copy;
1645
+ });
1604
1646
  }
1605
- getDirtyValues() {
1606
- const values = {};
1607
- for (const key of Object.keys(this.controls)) {
1608
- const control = this.get(key);
1609
- if (control?.dirty) {
1610
- values[key] = control.getRawValue();
1611
- }
1647
+ collapseMenu(exception) {
1648
+ let codes = [];
1649
+ if (exception) {
1650
+ const parents = this.getParents(exception);
1651
+ codes = [exception.code, ...parents.map((parent) => parent.code)];
1612
1652
  }
1613
- return values;
1653
+ this.expandedIds.set(new Set(codes));
1614
1654
  }
1615
- }
1616
-
1617
- /** Максимальное кол-во символов в текстовых полях */
1618
- const MAX_LENGTH_TEXT_PARAMS = new InjectionToken('MAX_LENGTH_TEXT_PARAMS');
1619
-
1620
- class ParamBase {
1621
- /** Метод для конвертации значения control при сохранении (используется при сохранении фильтров в БД) */
1622
- set formatSavedValue(formatter) {
1623
- if (formatter) {
1624
- this.formatterSavedValue = formatter;
1625
- }
1655
+ get isMenuOpened() {
1656
+ return this._state.isOpen;
1626
1657
  }
1627
- /** Метод для конвертации сохраненного значения в control (используется при установке сохраненных фильтров из БД) */
1628
- set parseSavedValue(parser) {
1629
- if (parser) {
1630
- this.parserSavedValue = parser;
1631
- }
1658
+ get isMenuClosed() {
1659
+ return !this._state.isOpen;
1632
1660
  }
1633
- /** Метод для конвертации значения control в GQL-значение (используется при вычислении gql_value control) */
1634
- set formatGqlValue(formatter) {
1635
- if (formatter) {
1636
- this.formatterGqlValue = formatter;
1661
+ isExternalLink(route) {
1662
+ if (!route) {
1663
+ return false;
1637
1664
  }
1665
+ return /^(https?:\/\/|www\.)/i.test(route);
1638
1666
  }
1639
- set required(required) {
1640
- this._required = required;
1641
- this._setControlRequired(required);
1642
- }
1643
- get required() {
1644
- return this.control?.hasValidator(Validators.required) ?? false;
1667
+ handleNavigation(item) {
1668
+ if (!item.route) {
1669
+ return;
1670
+ }
1671
+ if (this.isExternalLink(item.route)) {
1672
+ window.open(item.route, '_blank');
1673
+ }
1674
+ else {
1675
+ this._router.navigate([item.route]);
1676
+ this.selectedSection.set(item.code ?? '');
1677
+ if (this.isMenuClosed) {
1678
+ this.collapseMenu();
1679
+ }
1680
+ }
1645
1681
  }
1646
- set disabled(disabled) {
1647
- this._disabled = disabled;
1648
- this._setControlDisabled(disabled);
1682
+ serviceInfoOnActiveZone(active) {
1683
+ this.isOpenServiceVersionInfo = active && this.isOpenServiceVersionInfo;
1649
1684
  }
1650
- get disabled() {
1651
- return this.control?.disabled ?? false;
1685
+ serviceInfoOnObscured(obscured) {
1686
+ if (obscured) {
1687
+ this.isOpenServiceVersionInfo = false;
1688
+ }
1652
1689
  }
1653
- constructor(_injector) {
1654
- this._injector = _injector;
1655
- /** Название */
1656
- this.label = '';
1657
- /** Текст при пустом значении control (null) */
1658
- this.placeholder = input('');
1659
- /** Режим просмотра, по умолчанию выключен */
1660
- this.readmode = false;
1661
- /** Кнопка быстрой очистки поля, по умолчанию включена */
1662
- this.forceClear = true;
1690
+ buildMenu(menu) {
1691
+ const sortedMenuItems = [...menu].sort((a, b) => (a.order_num ?? 0) - (b.order_num ?? 0));
1692
+ const menuHash = {};
1693
+ for (const item of sortedMenuItems) {
1694
+ menuHash[item.id] = {
1695
+ title: item.title ?? '',
1696
+ route: item.route ?? '',
1697
+ id: item.id,
1698
+ children: [],
1699
+ code: item.code,
1700
+ icon: item.icon,
1701
+ accessedRoles: undefined,
1702
+ parent: undefined,
1703
+ };
1704
+ }
1705
+ const rootMenuItems = [];
1706
+ for (const item of sortedMenuItems) {
1707
+ if (item.id_parent && menuHash[item.id_parent]) {
1708
+ const parent = menuHash[item.id_parent];
1709
+ const child = menuHash[item.id];
1710
+ child.parent = parent;
1711
+ parent.children?.push(child);
1712
+ }
1713
+ else {
1714
+ rootMenuItems.push(menuHash[item.id]);
1715
+ }
1716
+ }
1717
+ this.navigationHierarchy.set(rootMenuItems);
1718
+ this.codeToItem = {};
1719
+ for (const id of Object.keys(menuHash)) {
1720
+ const item = menuHash[id];
1721
+ if (item.code) {
1722
+ this.codeToItem[item.code] = item;
1723
+ }
1724
+ }
1725
+ }
1726
+ findRoute(routeToFind) {
1727
+ const routeItem = this.codeToItem[routeToFind];
1728
+ if (!routeItem) {
1729
+ return;
1730
+ }
1731
+ if (this.isMenuOpened) {
1732
+ this.toggleItem(routeItem);
1733
+ }
1734
+ this.selectedSection.set(routeItem.code ?? '');
1735
+ }
1736
+ _findActiveSection() {
1737
+ this.findActiveSection()(this.resetSelection, this.findRoute);
1738
+ }
1739
+ getParents(item) {
1740
+ const parents = [];
1741
+ let current = item.parent;
1742
+ while (current) {
1743
+ parents.push(current);
1744
+ current = current.parent;
1745
+ }
1746
+ return parents;
1747
+ }
1748
+ resetSelection() {
1749
+ this.expandedIds.set(new Set());
1750
+ this.selectedSection.set('');
1751
+ }
1752
+ collectChildren(item) {
1753
+ const result = [];
1754
+ const queue = item.children?.slice() ?? [];
1755
+ let index = 0;
1756
+ while (index < queue.length) {
1757
+ const node = queue[index];
1758
+ result.push(node);
1759
+ if (node.children) {
1760
+ queue.push(...node.children);
1761
+ }
1762
+ index += 1;
1763
+ }
1764
+ return result;
1765
+ }
1766
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SprocPageMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1767
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SprocPageMenuComponent, isStandalone: true, selector: "sproc-page-menu", inputs: { menuItems: { classPropertyName: "menuItems", publicName: "menuItems", isSignal: true, isRequired: true, transformFunction: null }, menuIconsSrc: { classPropertyName: "menuIconsSrc", publicName: "menuIconsSrc", isSignal: true, isRequired: false, transformFunction: null }, openLogoSrc: { classPropertyName: "openLogoSrc", publicName: "openLogoSrc", isSignal: true, isRequired: false, transformFunction: null }, closedLogoSrc: { classPropertyName: "closedLogoSrc", publicName: "closedLogoSrc", isSignal: true, isRequired: false, transformFunction: null }, findActiveSection: { classPropertyName: "findActiveSection", publicName: "findActiveSection", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "style.--page-menu-opened-width": "this.menuOpenedWidth", "style.--page-menu-closed-width": "this.menuClosedWidth" } }, ngImport: i0, template: "<section [class]=\"menuState() ? 'side-menu side-menu_opened' : 'side-menu side-menu_closed'\">\n <div class=\"side-menu__header\">\n <img\n [src]=\"menuState() ? openLogoSrc() : closedLogoSrc()\"\n alt=\"Logo Icon\"\n class=\"side-menu__header__logo\"\n />\n <img\n (click)=\"toggleNavigation()\"\n [class.disabled]=\"toggleDisabled$ | async\"\n [height]=\"16\"\n [ngClass]=\"menuState() ? 'side-menu__header__chevron_opened' : 'side-menu__header__chevron_closed'\"\n [ngSrc]=\"ICONS_SRC.MENU_CHEVRON\" [width]=\"16\" alt=\"Menu Chevron\"/>\n </div>\n\n @if (menuState()) {\n <div class=\"expanded-menu-content\">\n @for (navigation_item of navigationHierarchy(); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n menuItemOpened;\n context: { navigation_item: navigation_item, level: 0 }\n \"\n ></ng-container>\n }\n </div>\n\n <ng-content></ng-content>\n } @else {\n @for (navigation_item of navigationHierarchy(); track $index) {\n <ng-container\n *ngTemplateOutlet=\"closedMenu; context: { navigation_item: navigation_item }\"\n ></ng-container>\n }\n }\n</section>\n\n<ng-template #menuItemOpened let-level=\"level\" let-navigation_item=\"navigation_item\">\n @let isExpanded = expandedIds().has(navigation_item.code);\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let icon = navigation_item.icon;\n @let isHighlighted = selectedSection() === code;\n\n <a\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [@fadeInOut]\n [class.menu-item_selected]=\"isHighlighted\"\n [class.padding-level-0]=\"level === 0\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n [style.padding-left.px]=\"level === 0 ? 0 : 44 + level * 20\"\n class=\"menu-item\"\n >\n @if (icon) {\n <span class=\"menu-item__icon\">\n <img [alt]=\"icon\" [width]=\"16\" [height]=\"16\" [ngSrc]=\"menuIconsSrc() + icon + '.svg'\">\n </span>\n }\n <span class=\"menu-item__title\"> {{ navigation_item.title }} </span>\n @if (childrenCount > 0) {\n <img\n class=\"menu-item__chevron\"\n [class.menu-item__chevron_rotated]=\"!isExpanded\"\n [alt]=\"icon\" [width]=\"16\" [height]=\"16\"\n [ngSrc]=\"ICONS_SRC.CHEVRON_UP\">\n }\n </a>\n @if (isExpanded && childrenCount > 0) {\n @for (children of navigation_item.children ?? []; track $index) {\n <ng-container\n *ngTemplateOutlet=\"menuItemOpened; context: { navigation_item: children, level: level + 1 }\"\n ></ng-container>\n }\n }\n</ng-template>\n\n<ng-template #closedMenu let-navigation_item=\"navigation_item\">\n @let isExpanded = expandedIds().has(navigation_item.code);\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let icon = navigation_item.icon;\n @let isHighlighted = selectedSection() === code || parentItemCodes().has(code);\n\n <div\n (mouseleave)=\"collapseMenu()\"\n [id]=\"navigation_item.id\"\n class=\"collapsed-menu-content\"\n >\n @if (icon) {\n <a\n class=\"menu-item__icon_closed\"\n [class.menu-item_selected]=\"isHighlighted\"\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n (mouseenter)=\"toggleItem(navigation_item)\">\n <img\n [height]=\"16\"\n [width]=\"16\"\n [ngSrc]=\"menuIconsSrc() + icon + '.svg'\" alt=\"Menu Chevron\"/>\n </a>\n }\n <ng-container\n *ngTemplateOutlet=\"\n menuClosedItem;\n context: { item: navigation_item, level: 1, topPadding: 1 }\n \"\n >\n </ng-container>\n @if (isExpanded && childrenCount > 0) {\n <div class=\"static-item\">\n <span class=\"static-item__element\">\n {{ navigation_item.title }}\n </span>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #menuClosedItem let-item=\"item\" let-level=\"level\" let-topPadding=\"topPadding\">\n @let isExpanded = expandedIds().has(item.code);\n <div [id]=\"item.id\">\n @if (isExpanded && item.children.length > 0) {\n <div\n class=\"side-menu__subitems\"\n [class.padding-level-1]=\"level === 1\"\n [style.top.px]=\"topPadding * 40\"\n id=\"side-menu__subitems\"\n >\n @for (navigation_item of item.children; track navigation_item; let index = $index) {\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let isHighlighted = selectedSection() === code || parentItemCodes().has(code);\n <a\n class=\"side-menu__subitem\"\n [class.menu-item_selected]=\"isHighlighted\"\n (mouseenter)=\"childrenCount > 0 ? toggleItem(navigation_item) : collapseMenu(navigation_item)\"\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n >\n <span\n [class.padding-level-1]=\"level === 1\">{{\n navigation_item.title\n }}</span>\n\n @if (childrenCount > 0) {\n <img\n class=\"chevron-right\"\n [height]=\"16\"\n [width]=\"16\"\n [ngSrc]=\"ICONS_SRC.CHEVRON_RIGHT\" alt=\"Menu Chevron\"/>\n }\n </a>\n <ng-container\n *ngTemplateOutlet=\"\n menuClosedItem;\n context: { item: navigation_item, level: level + 1, topPadding: index }\n \"\n ></ng-container>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{background:var(--page-menu-main);height:100vh;max-height:100vh;z-index:1000;display:flex}:host tui-icon{width:16px;height:16px}:host ::-webkit-scrollbar{width:6px;background:var(--page-menu-main)}:host ::-webkit-scrollbar-thumb{width:6px;background:#c3c7cf;border-radius:2px}:host .side-menu{transition:all var(--page-menu-transition-time);display:flex;color:var(--main-white);flex-direction:column;flex-shrink:0;font-size:14px}:host .side-menu__header{height:64px;width:100%;display:flex;align-items:center;justify-content:space-between}:host .side-menu__header__chevron{cursor:pointer;transition:rotate .15s linear}:host .side-menu__header__chevron_opened{margin:0 8px 0 0;rotate:0deg}:host .side-menu__header__chevron_closed{margin:0 0 0 -4px;rotate:180deg}:host .side-menu__header .disabled{pointer-events:none}:host .side-menu__header__logo{margin-left:8px}:host .side-menu_opened{width:var(--page-menu-opened-width)}:host .side-menu_closed{width:var(--page-menu-closed-width)}:host .side-menu__subitems,:host .side-menu .static-item{position:absolute;display:flex;z-index:3;right:0;top:0;flex-direction:column}:host .side-menu__subitems{width:294px;box-shadow:0 2px 6px #28282840;left:294px}:host .side-menu__subitems.padding-level-1{left:48px}:host .side-menu__subitems .chevron-right{margin-right:16px}:host .side-menu__subitems a span{height:40px;display:flex;align-items:center;padding-left:40px}:host .side-menu__subitems a span .padding-level-1{padding-left:64px}:host .side-menu .static-item{color:var(--main-black);left:48px;top:0}:host .side-menu__subitem,:host .side-menu .static-item__element{box-sizing:border-box;display:flex;align-items:center;color:var(--main-white);height:40px;width:294px;background:var(--page-menu-main);justify-content:space-between}:host .side-menu__subitem:hover{background:var(--page-menu-main-hovered);cursor:pointer}:host .side-menu .static-item__element{justify-content:unset;padding-left:16px}:host .side-menu .expanded-menu-content{height:calc(100vh - 103px);-ms-overflow-style:none;scrollbar-width:none;overflow-y:scroll}:host .side-menu .expanded-menu-content::-webkit-scrollbar{display:none}:host .side-menu .collapsed-menu-content{position:relative}:host .side-menu .menu-item{display:flex;flex-direction:row;cursor:pointer;justify-content:start;align-items:center;box-sizing:border-box;transition:background .9ms;height:40px}:host .side-menu .menu-item_selected{background:var(--page-menu-active)!important;box-shadow:inset 3px 0 var(--main-white)}:host .side-menu .menu-item_selected:hover{background:var(--page-menu-active)!important}:host .side-menu .menu-item__chevron{margin-left:auto;margin-right:8px;transition:rotate .15s linear}:host .side-menu .menu-item__chevron_rotated{rotate:180deg}:host .side-menu .menu-item__title{padding:10px 0 10px 8px;overflow:hidden;color:var(--main-white);font-variant-numeric:lining-nums tabular-nums;text-overflow:ellipsis;white-space:nowrap;font-family:Inter,serif;font-size:14px;font-weight:300}:host .side-menu .menu-item__title .page-menu-text-14px{font-family:Inter,serif;font-size:14px;font-weight:300}:host .side-menu .menu-item__icon{padding:0 8px 0 16px}:host .side-menu .menu-item__icon_closed{display:flex;height:40px;justify-content:center;align-items:center}:host .side-menu .menu-item__icon_closed:hover{background:var(--page-menu-main-hovered);cursor:pointer}:host .side-menu .menu-item:hover{background:var(--page-menu-main-hovered)}:host a{text-decoration:none;color:unset}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }], animations: [
1768
+ trigger('fadeInOut', [
1769
+ transition(':enter', [
1770
+ style({
1771
+ opacity: 0,
1772
+ transform: 'translateY(-10px)',
1773
+ transformOrigin: 'top',
1774
+ }),
1775
+ animate('0.15s ease-in', style({
1776
+ opacity: 1,
1777
+ transform: 'translateY(0)',
1778
+ })),
1779
+ ]),
1780
+ ]),
1781
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1782
+ }
1783
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SprocPageMenuComponent, decorators: [{
1784
+ type: Component,
1785
+ args: [{ selector: 'sproc-page-menu', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [RouterLink, NgTemplateOutlet, NgClass, AsyncPipe, NgOptimizedImage], animations: [
1786
+ trigger('fadeInOut', [
1787
+ transition(':enter', [
1788
+ style({
1789
+ opacity: 0,
1790
+ transform: 'translateY(-10px)',
1791
+ transformOrigin: 'top',
1792
+ }),
1793
+ animate('0.15s ease-in', style({
1794
+ opacity: 1,
1795
+ transform: 'translateY(0)',
1796
+ })),
1797
+ ]),
1798
+ ]),
1799
+ ], template: "<section [class]=\"menuState() ? 'side-menu side-menu_opened' : 'side-menu side-menu_closed'\">\n <div class=\"side-menu__header\">\n <img\n [src]=\"menuState() ? openLogoSrc() : closedLogoSrc()\"\n alt=\"Logo Icon\"\n class=\"side-menu__header__logo\"\n />\n <img\n (click)=\"toggleNavigation()\"\n [class.disabled]=\"toggleDisabled$ | async\"\n [height]=\"16\"\n [ngClass]=\"menuState() ? 'side-menu__header__chevron_opened' : 'side-menu__header__chevron_closed'\"\n [ngSrc]=\"ICONS_SRC.MENU_CHEVRON\" [width]=\"16\" alt=\"Menu Chevron\"/>\n </div>\n\n @if (menuState()) {\n <div class=\"expanded-menu-content\">\n @for (navigation_item of navigationHierarchy(); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n menuItemOpened;\n context: { navigation_item: navigation_item, level: 0 }\n \"\n ></ng-container>\n }\n </div>\n\n <ng-content></ng-content>\n } @else {\n @for (navigation_item of navigationHierarchy(); track $index) {\n <ng-container\n *ngTemplateOutlet=\"closedMenu; context: { navigation_item: navigation_item }\"\n ></ng-container>\n }\n }\n</section>\n\n<ng-template #menuItemOpened let-level=\"level\" let-navigation_item=\"navigation_item\">\n @let isExpanded = expandedIds().has(navigation_item.code);\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let icon = navigation_item.icon;\n @let isHighlighted = selectedSection() === code;\n\n <a\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [@fadeInOut]\n [class.menu-item_selected]=\"isHighlighted\"\n [class.padding-level-0]=\"level === 0\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n [style.padding-left.px]=\"level === 0 ? 0 : 44 + level * 20\"\n class=\"menu-item\"\n >\n @if (icon) {\n <span class=\"menu-item__icon\">\n <img [alt]=\"icon\" [width]=\"16\" [height]=\"16\" [ngSrc]=\"menuIconsSrc() + icon + '.svg'\">\n </span>\n }\n <span class=\"menu-item__title\"> {{ navigation_item.title }} </span>\n @if (childrenCount > 0) {\n <img\n class=\"menu-item__chevron\"\n [class.menu-item__chevron_rotated]=\"!isExpanded\"\n [alt]=\"icon\" [width]=\"16\" [height]=\"16\"\n [ngSrc]=\"ICONS_SRC.CHEVRON_UP\">\n }\n </a>\n @if (isExpanded && childrenCount > 0) {\n @for (children of navigation_item.children ?? []; track $index) {\n <ng-container\n *ngTemplateOutlet=\"menuItemOpened; context: { navigation_item: children, level: level + 1 }\"\n ></ng-container>\n }\n }\n</ng-template>\n\n<ng-template #closedMenu let-navigation_item=\"navigation_item\">\n @let isExpanded = expandedIds().has(navigation_item.code);\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let icon = navigation_item.icon;\n @let isHighlighted = selectedSection() === code || parentItemCodes().has(code);\n\n <div\n (mouseleave)=\"collapseMenu()\"\n [id]=\"navigation_item.id\"\n class=\"collapsed-menu-content\"\n >\n @if (icon) {\n <a\n class=\"menu-item__icon_closed\"\n [class.menu-item_selected]=\"isHighlighted\"\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n (mouseenter)=\"toggleItem(navigation_item)\">\n <img\n [height]=\"16\"\n [width]=\"16\"\n [ngSrc]=\"menuIconsSrc() + icon + '.svg'\" alt=\"Menu Chevron\"/>\n </a>\n }\n <ng-container\n *ngTemplateOutlet=\"\n menuClosedItem;\n context: { item: navigation_item, level: 1, topPadding: 1 }\n \"\n >\n </ng-container>\n @if (isExpanded && childrenCount > 0) {\n <div class=\"static-item\">\n <span class=\"static-item__element\">\n {{ navigation_item.title }}\n </span>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #menuClosedItem let-item=\"item\" let-level=\"level\" let-topPadding=\"topPadding\">\n @let isExpanded = expandedIds().has(item.code);\n <div [id]=\"item.id\">\n @if (isExpanded && item.children.length > 0) {\n <div\n class=\"side-menu__subitems\"\n [class.padding-level-1]=\"level === 1\"\n [style.top.px]=\"topPadding * 40\"\n id=\"side-menu__subitems\"\n >\n @for (navigation_item of item.children; track navigation_item; let index = $index) {\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let isHighlighted = selectedSection() === code || parentItemCodes().has(code);\n <a\n class=\"side-menu__subitem\"\n [class.menu-item_selected]=\"isHighlighted\"\n (mouseenter)=\"childrenCount > 0 ? toggleItem(navigation_item) : collapseMenu(navigation_item)\"\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n >\n <span\n [class.padding-level-1]=\"level === 1\">{{\n navigation_item.title\n }}</span>\n\n @if (childrenCount > 0) {\n <img\n class=\"chevron-right\"\n [height]=\"16\"\n [width]=\"16\"\n [ngSrc]=\"ICONS_SRC.CHEVRON_RIGHT\" alt=\"Menu Chevron\"/>\n }\n </a>\n <ng-container\n *ngTemplateOutlet=\"\n menuClosedItem;\n context: { item: navigation_item, level: level + 1, topPadding: index }\n \"\n ></ng-container>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{background:var(--page-menu-main);height:100vh;max-height:100vh;z-index:1000;display:flex}:host tui-icon{width:16px;height:16px}:host ::-webkit-scrollbar{width:6px;background:var(--page-menu-main)}:host ::-webkit-scrollbar-thumb{width:6px;background:#c3c7cf;border-radius:2px}:host .side-menu{transition:all var(--page-menu-transition-time);display:flex;color:var(--main-white);flex-direction:column;flex-shrink:0;font-size:14px}:host .side-menu__header{height:64px;width:100%;display:flex;align-items:center;justify-content:space-between}:host .side-menu__header__chevron{cursor:pointer;transition:rotate .15s linear}:host .side-menu__header__chevron_opened{margin:0 8px 0 0;rotate:0deg}:host .side-menu__header__chevron_closed{margin:0 0 0 -4px;rotate:180deg}:host .side-menu__header .disabled{pointer-events:none}:host .side-menu__header__logo{margin-left:8px}:host .side-menu_opened{width:var(--page-menu-opened-width)}:host .side-menu_closed{width:var(--page-menu-closed-width)}:host .side-menu__subitems,:host .side-menu .static-item{position:absolute;display:flex;z-index:3;right:0;top:0;flex-direction:column}:host .side-menu__subitems{width:294px;box-shadow:0 2px 6px #28282840;left:294px}:host .side-menu__subitems.padding-level-1{left:48px}:host .side-menu__subitems .chevron-right{margin-right:16px}:host .side-menu__subitems a span{height:40px;display:flex;align-items:center;padding-left:40px}:host .side-menu__subitems a span .padding-level-1{padding-left:64px}:host .side-menu .static-item{color:var(--main-black);left:48px;top:0}:host .side-menu__subitem,:host .side-menu .static-item__element{box-sizing:border-box;display:flex;align-items:center;color:var(--main-white);height:40px;width:294px;background:var(--page-menu-main);justify-content:space-between}:host .side-menu__subitem:hover{background:var(--page-menu-main-hovered);cursor:pointer}:host .side-menu .static-item__element{justify-content:unset;padding-left:16px}:host .side-menu .expanded-menu-content{height:calc(100vh - 103px);-ms-overflow-style:none;scrollbar-width:none;overflow-y:scroll}:host .side-menu .expanded-menu-content::-webkit-scrollbar{display:none}:host .side-menu .collapsed-menu-content{position:relative}:host .side-menu .menu-item{display:flex;flex-direction:row;cursor:pointer;justify-content:start;align-items:center;box-sizing:border-box;transition:background .9ms;height:40px}:host .side-menu .menu-item_selected{background:var(--page-menu-active)!important;box-shadow:inset 3px 0 var(--main-white)}:host .side-menu .menu-item_selected:hover{background:var(--page-menu-active)!important}:host .side-menu .menu-item__chevron{margin-left:auto;margin-right:8px;transition:rotate .15s linear}:host .side-menu .menu-item__chevron_rotated{rotate:180deg}:host .side-menu .menu-item__title{padding:10px 0 10px 8px;overflow:hidden;color:var(--main-white);font-variant-numeric:lining-nums tabular-nums;text-overflow:ellipsis;white-space:nowrap;font-family:Inter,serif;font-size:14px;font-weight:300}:host .side-menu .menu-item__title .page-menu-text-14px{font-family:Inter,serif;font-size:14px;font-weight:300}:host .side-menu .menu-item__icon{padding:0 8px 0 16px}:host .side-menu .menu-item__icon_closed{display:flex;height:40px;justify-content:center;align-items:center}:host .side-menu .menu-item__icon_closed:hover{background:var(--page-menu-main-hovered);cursor:pointer}:host .side-menu .menu-item:hover{background:var(--page-menu-main-hovered)}:host a{text-decoration:none;color:unset}\n"] }]
1800
+ }], ctorParameters: () => [], propDecorators: { menuOpenedWidth: [{
1801
+ type: HostBinding,
1802
+ args: ['style.--page-menu-opened-width']
1803
+ }], menuClosedWidth: [{
1804
+ type: HostBinding,
1805
+ args: ['style.--page-menu-closed-width']
1806
+ }] } });
1807
+
1808
+ class AbstractMenuStateService {
1809
+ }
1810
+
1811
+ var ERuntimeErrorCode;
1812
+ (function (ERuntimeErrorCode) {
1813
+ // Structure validation errors
1814
+ ERuntimeErrorCode[ERuntimeErrorCode["NO_CONTROLS"] = 1000] = "NO_CONTROLS";
1815
+ ERuntimeErrorCode[ERuntimeErrorCode["MISSING_CONTROL"] = 1001] = "MISSING_CONTROL";
1816
+ ERuntimeErrorCode[ERuntimeErrorCode["MISSING_CONTROL_VALUE"] = 1002] = "MISSING_CONTROL_VALUE";
1817
+ })(ERuntimeErrorCode || (ERuntimeErrorCode = {}));
1818
+
1819
+ function assertAllValuesPresent(control, isGroup, value) {
1820
+ control._forEachChild((_, key) => {
1821
+ if (value[key] === undefined) {
1822
+ throw new _RuntimeError(ERuntimeErrorCode.MISSING_CONTROL_VALUE, '');
1823
+ }
1824
+ });
1825
+ }
1826
+ function assertControlPresent(parent, isGroup, key) {
1827
+ const controls = parent.controls;
1828
+ const collection = isGroup ? Object.keys(controls) : controls;
1829
+ if (collection.length === 0) {
1830
+ throw new _RuntimeError(ERuntimeErrorCode.NO_CONTROLS, '');
1831
+ }
1832
+ if (!controls[key]) {
1833
+ throw new _RuntimeError(ERuntimeErrorCode.MISSING_CONTROL, '');
1834
+ }
1835
+ }
1836
+ /** @deprecated заменить на FormGroup */
1837
+ class FormGroupWrapper extends FormGroup {
1838
+ setValue(value, options) {
1839
+ assertAllValuesPresent(this, true, value);
1840
+ for (const name of Object.keys(value)) {
1841
+ assertControlPresent(this, true, name);
1842
+ const control = this.controls[name];
1843
+ const currentValue = value[name];
1844
+ if (control instanceof FormArray && Array.isArray(currentValue)) {
1845
+ control.clear();
1846
+ for (const item of currentValue) {
1847
+ item.setParent(control);
1848
+ control.push(item, { emitEvent: options?.emitEvent });
1849
+ }
1850
+ }
1851
+ else {
1852
+ control.setValue(currentValue, {
1853
+ onlySelf: true,
1854
+ emitEvent: options?.emitEvent,
1855
+ });
1856
+ }
1857
+ }
1858
+ this.updateValueAndValidity(options);
1859
+ }
1860
+ patchValue(value, options) {
1861
+ if (value === null) {
1862
+ return;
1863
+ }
1864
+ for (const name of Object.keys(value)) {
1865
+ const control = this.controls[name];
1866
+ const currentValue = value[name];
1867
+ if (control) {
1868
+ if (control instanceof FormArray && Array.isArray(currentValue)) {
1869
+ control.clear();
1870
+ for (const item of currentValue) {
1871
+ item.setParent(control);
1872
+ control.push(item, { emitEvent: options?.emitEvent });
1873
+ }
1874
+ }
1875
+ else {
1876
+ control.patchValue(currentValue, {
1877
+ onlySelf: true,
1878
+ emitEvent: options?.emitEvent,
1879
+ });
1880
+ }
1881
+ }
1882
+ }
1883
+ this.updateValueAndValidity(options);
1884
+ }
1885
+ getDirtyValues() {
1886
+ const values = {};
1887
+ for (const key of Object.keys(this.controls)) {
1888
+ const control = this.get(key);
1889
+ if (control?.dirty) {
1890
+ values[key] = control.getRawValue();
1891
+ }
1892
+ }
1893
+ return values;
1894
+ }
1895
+ }
1896
+
1897
+ /** Максимальное кол-во символов в текстовых полях */
1898
+ const MAX_LENGTH_TEXT_PARAMS = new InjectionToken('MAX_LENGTH_TEXT_PARAMS');
1899
+
1900
+ class ParamBase {
1901
+ /** Метод для конвертации значения control при сохранении (используется при сохранении фильтров в БД) */
1902
+ set formatSavedValue(formatter) {
1903
+ if (formatter) {
1904
+ this.formatterSavedValue = formatter;
1905
+ }
1906
+ }
1907
+ /** Метод для конвертации сохраненного значения в control (используется при установке сохраненных фильтров из БД) */
1908
+ set parseSavedValue(parser) {
1909
+ if (parser) {
1910
+ this.parserSavedValue = parser;
1911
+ }
1912
+ }
1913
+ /** Метод для конвертации значения control в GQL-значение (используется при вычислении gql_value control) */
1914
+ set formatGqlValue(formatter) {
1915
+ if (formatter) {
1916
+ this.formatterGqlValue = formatter;
1917
+ }
1918
+ }
1919
+ set required(required) {
1920
+ this._required = required;
1921
+ this._setControlRequired(required);
1922
+ }
1923
+ get required() {
1924
+ return this.control?.hasValidator(Validators.required) ?? false;
1925
+ }
1926
+ set disabled(disabled) {
1927
+ this._disabled = disabled;
1928
+ this._setControlDisabled(disabled);
1929
+ }
1930
+ get disabled() {
1931
+ return this.control?.disabled ?? false;
1932
+ }
1933
+ constructor(_injector) {
1934
+ this._injector = _injector;
1935
+ /** Название */
1936
+ this.label = '';
1937
+ /** Текст при пустом значении control (null) */
1938
+ this.placeholder = input('');
1939
+ /** Режим просмотра, по умолчанию выключен */
1940
+ this.readmode = false;
1941
+ /** Кнопка быстрой очистки поля, по умолчанию включена */
1942
+ this.forceClear = true;
1663
1943
  /** Текст при наведении на значение control */
1664
1944
  this.hint = null;
1665
1945
  /** Готовые стили для использования поля в панели фильтров/параметров или на карточке, по умолчанию стили для карточки */
@@ -3111,7 +3391,7 @@ class RegisterTableFilterComponent {
3111
3391
  this.filterListHeaderTitle = 'Фильтр';
3112
3392
  this.footerApplyButtonLabel = 'Применить';
3113
3393
  this.clickApplyButton = new EventEmitter();
3114
- this._menuState = inject(MENU_STATE_SERVICE);
3394
+ this._menuState = inject(PAGE_MENU_STATE);
3115
3395
  this._unsubscribe$ = new Subject();
3116
3396
  this.FilterState = EInputsState;
3117
3397
  this.filterState$ = this._filterStateService.state$.pipe(map((filterState) => filterState.state));
@@ -5428,288 +5708,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
5428
5708
  }]
5429
5709
  }] });
5430
5710
 
5431
- const SIDE_MENU_OPENED_WIDTH = 350;
5432
- const SIDE_MENU_CLOSED_WIDTH = 48;
5433
- var EPageMenuIconsSrc;
5434
- (function (EPageMenuIconsSrc) {
5435
- EPageMenuIconsSrc["CHEVRON_RIGHT"] = "assets/ngx-register-base/icons/chevron-right.svg";
5436
- EPageMenuIconsSrc["CHEVRON_UP"] = "assets/ngx-register-base/icons/chevron-up.svg";
5437
- EPageMenuIconsSrc["MENU_CHEVRON"] = "assets/ngx-register-base/icons/chevron-menu.svg";
5438
- })(EPageMenuIconsSrc || (EPageMenuIconsSrc = {}));
5439
-
5440
- const PAGE_MENU_STATE = new InjectionToken('PAGE_MENU_STATE');
5441
- // export const PAGE_MENU_STORE = new InjectionToken<AbstractMenuStateService>('PAGE_MENU_STATE');
5442
-
5443
- class SprocPageMenuComponent {
5444
- constructor() {
5445
- this.menuItems = input.required();
5446
- this.menuIconsSrc = input('');
5447
- this.openLogoSrc = input('');
5448
- this.closedLogoSrc = input('');
5449
- this.findActiveSection = input.required();
5450
- // TODO Добавить кастомную ширину меню
5451
- this.menuOpenedWidth = `${SIDE_MENU_OPENED_WIDTH}px`;
5452
- this.menuClosedWidth = `${SIDE_MENU_CLOSED_WIDTH}px`;
5453
- this._router = inject(Router);
5454
- this._state = inject(PAGE_MENU_STATE);
5455
- this._dr = inject(DestroyRef);
5456
- this.toggleDisabled$ = this._state.toggleDisabled$;
5457
- this.menuState = toSignal(this._state.isOpen$);
5458
- this.selectedSection = signal('register');
5459
- this.expandedIds = signal(new Set());
5460
- this.selectedItem = computed(() => this.selectedSection() ? this.codeToItem[this.selectedSection()] : null);
5461
- // Хранит parent элементы выбранного пункта меню
5462
- this.parentItems = computed(() => {
5463
- const item = this.selectedItem();
5464
- if (!item) {
5465
- return [];
5466
- }
5467
- const parents = [];
5468
- let current = item.parent;
5469
- while (current) {
5470
- parents.push(current);
5471
- current = current.parent;
5472
- }
5473
- return parents;
5474
- });
5475
- this.parentItemCodes = computed(() => {
5476
- const parentItems = this.parentItems();
5477
- return new Set(parentItems.map((val) => val.code ?? ''));
5478
- });
5479
- this.navigationHierarchy = signal([]);
5480
- this.codeToItem = {};
5481
- this.isOpenServiceVersionInfo = false;
5482
- this.ICONS_SRC = EPageMenuIconsSrc;
5483
- // Построить меню и найти активную секцию
5484
- effect(() => {
5485
- const menuItems = this.menuItems();
5486
- this.buildMenu(menuItems);
5487
- this._findActiveSection();
5488
- }, { allowSignalWrites: true });
5489
- }
5490
- addMenuScrollbar(id) {
5491
- setTimeout(() => {
5492
- // TODO Меню второго уровня есть скролл,третьего нет
5493
- const collapsedMenu = document.querySelector(`[id="${id}"]`);
5494
- const sideMenu = collapsedMenu?.querySelector('#side-menu__subitems');
5495
- const sideMenuLevelTwo = sideMenu?.querySelector('#side-menu__subitems');
5496
- const subitem = sideMenuLevelTwo
5497
- ? sideMenuLevelTwo.querySelectorAll('.side-menu__subitem')
5498
- : sideMenu?.querySelectorAll('.side-menu__subitem');
5499
- if (subitem) {
5500
- const lastSubitem = subitem[subitem.length - 1];
5501
- const rect = lastSubitem?.getBoundingClientRect();
5502
- if (sideMenu && window.innerHeight - rect.bottom < 0) {
5503
- // 40 тк высота плашки меню
5504
- sideMenu.style.height = `${subitem.length * 40 + (window.innerHeight - rect.bottom - 1)}px`;
5505
- sideMenu.style.overflowY = 'scroll';
5506
- sideMenu.style.overflowX = 'hidden';
5507
- }
5508
- if (window.innerHeight - rect.bottom < 0 && sideMenuLevelTwo) {
5509
- // 40 тк высота плашки меню
5510
- sideMenuLevelTwo.style.height = `${subitem.length * 40 + (window.innerHeight - rect.bottom - 1)}px`;
5511
- sideMenuLevelTwo.style.overflowY = 'scroll';
5512
- sideMenuLevelTwo.style.overflowX = 'hidden';
5513
- }
5514
- }
5515
- }, 0);
5516
- }
5517
- ngOnInit() {
5518
- this._state.isOpen$.subscribe((menuState) => {
5519
- if (menuState) {
5520
- this.findRoute(this.selectedSection());
5521
- }
5522
- else {
5523
- this.collapseMenu();
5524
- }
5525
- });
5526
- }
5527
- toggleNavigation() {
5528
- this._state.toggle();
5529
- }
5530
- toggleItem(item) {
5531
- this.addMenuScrollbar(item.id || '');
5532
- this.expandedIds.update((currentExpand) => {
5533
- const code = item.code;
5534
- const copy = new Set(currentExpand);
5535
- if (copy.has(code)) {
5536
- copy.delete(code);
5537
- }
5538
- else {
5539
- copy.clear();
5540
- copy.add(code);
5541
- const parents = this.getParents(item);
5542
- for (const parent of parents) {
5543
- copy.add(parent.code);
5544
- }
5545
- }
5546
- return copy;
5547
- });
5548
- }
5549
- collapseMenu(exception) {
5550
- let codes = [];
5551
- if (exception) {
5552
- const parents = this.getParents(exception);
5553
- codes = [exception.code, ...parents.map((parent) => parent.code)];
5554
- }
5555
- this.expandedIds.set(new Set(codes));
5556
- }
5557
- get isMenuOpened() {
5558
- return this._state.isOpen;
5559
- }
5560
- get isMenuClosed() {
5561
- return !this._state.isOpen;
5562
- }
5563
- isExternalLink(route) {
5564
- if (!route) {
5565
- return false;
5566
- }
5567
- return /^(https?:\/\/|www\.)/i.test(route);
5568
- }
5569
- handleNavigation(item) {
5570
- if (!item.route) {
5571
- return;
5572
- }
5573
- if (this.isExternalLink(item.route)) {
5574
- window.open(item.route, '_blank');
5575
- }
5576
- else {
5577
- this._router.navigate([item.route]);
5578
- this.selectedSection.set(item.code ?? '');
5579
- if (this.isMenuClosed) {
5580
- this.collapseMenu();
5581
- }
5582
- }
5583
- }
5584
- serviceInfoOnActiveZone(active) {
5585
- this.isOpenServiceVersionInfo = active && this.isOpenServiceVersionInfo;
5586
- }
5587
- serviceInfoOnObscured(obscured) {
5588
- if (obscured) {
5589
- this.isOpenServiceVersionInfo = false;
5590
- }
5591
- }
5592
- buildMenu(menu) {
5593
- const sortedMenuItems = [...menu].sort((a, b) => (a.order_num ?? 0) - (b.order_num ?? 0));
5594
- const menuHash = {};
5595
- for (const item of sortedMenuItems) {
5596
- menuHash[item.id] = {
5597
- title: item.title ?? '',
5598
- route: item.route ?? '',
5599
- id: item.id,
5600
- children: [],
5601
- code: item.code,
5602
- icon: item.icon,
5603
- accessedRoles: undefined,
5604
- parent: undefined,
5605
- };
5606
- }
5607
- const rootMenuItems = [];
5608
- for (const item of sortedMenuItems) {
5609
- if (item.id_parent && menuHash[item.id_parent]) {
5610
- const parent = menuHash[item.id_parent];
5611
- const child = menuHash[item.id];
5612
- child.parent = parent;
5613
- parent.children?.push(child);
5614
- }
5615
- else {
5616
- rootMenuItems.push(menuHash[item.id]);
5617
- }
5618
- }
5619
- this.navigationHierarchy.set(rootMenuItems);
5620
- this.codeToItem = {};
5621
- for (const id of Object.keys(menuHash)) {
5622
- const item = menuHash[id];
5623
- if (item.code) {
5624
- this.codeToItem[item.code] = item;
5625
- }
5626
- }
5627
- }
5628
- findRoute(routeToFind) {
5629
- const routeItem = this.codeToItem[routeToFind];
5630
- if (!routeItem) {
5631
- return;
5632
- }
5633
- if (this.isMenuOpened) {
5634
- this.toggleItem(routeItem);
5635
- }
5636
- this.selectedSection.set(routeItem.code ?? '');
5637
- }
5638
- _findActiveSection() {
5639
- this.findActiveSection()(this.resetSelection, this.findRoute);
5640
- }
5641
- getParents(item) {
5642
- const parents = [];
5643
- let current = item.parent;
5644
- while (current) {
5645
- parents.push(current);
5646
- current = current.parent;
5647
- }
5648
- return parents;
5649
- }
5650
- resetSelection() {
5651
- this.expandedIds.set(new Set());
5652
- this.selectedSection.set('');
5653
- }
5654
- collectChildren(item) {
5655
- const result = [];
5656
- const queue = item.children?.slice() ?? [];
5657
- let index = 0;
5658
- while (index < queue.length) {
5659
- const node = queue[index];
5660
- result.push(node);
5661
- if (node.children) {
5662
- queue.push(...node.children);
5663
- }
5664
- index += 1;
5665
- }
5666
- return result;
5667
- }
5668
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SprocPageMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5669
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SprocPageMenuComponent, isStandalone: true, selector: "sproc-page-menu", inputs: { menuItems: { classPropertyName: "menuItems", publicName: "menuItems", isSignal: true, isRequired: true, transformFunction: null }, menuIconsSrc: { classPropertyName: "menuIconsSrc", publicName: "menuIconsSrc", isSignal: true, isRequired: false, transformFunction: null }, openLogoSrc: { classPropertyName: "openLogoSrc", publicName: "openLogoSrc", isSignal: true, isRequired: false, transformFunction: null }, closedLogoSrc: { classPropertyName: "closedLogoSrc", publicName: "closedLogoSrc", isSignal: true, isRequired: false, transformFunction: null }, findActiveSection: { classPropertyName: "findActiveSection", publicName: "findActiveSection", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "style.--page-menu-opened-width": "this.menuOpenedWidth", "style.--page-menu-closed-width": "this.menuClosedWidth" } }, ngImport: i0, template: "<section [class]=\"menuState() ? 'side-menu side-menu_opened' : 'side-menu side-menu_closed'\">\n <div class=\"side-menu__header\">\n <img\n [src]=\"menuState() ? openLogoSrc() : closedLogoSrc()\"\n alt=\"Logo Icon\"\n class=\"side-menu__header__logo\"\n />\n <img\n (click)=\"toggleNavigation()\"\n [class.disabled]=\"toggleDisabled$ | async\"\n [height]=\"16\"\n [ngClass]=\"menuState() ? 'side-menu__header__chevron_opened' : 'side-menu__header__chevron_closed'\"\n [ngSrc]=\"ICONS_SRC.MENU_CHEVRON\" [width]=\"16\" alt=\"Menu Chevron\"/>\n </div>\n\n @if (menuState()) {\n <div class=\"expanded-menu-content\">\n @for (navigation_item of navigationHierarchy(); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n menuItemOpened;\n context: { navigation_item: navigation_item, level: 0 }\n \"\n ></ng-container>\n }\n </div>\n\n <ng-content></ng-content>\n } @else {\n @for (navigation_item of navigationHierarchy(); track $index) {\n <ng-container\n *ngTemplateOutlet=\"closedMenu; context: { navigation_item: navigation_item }\"\n ></ng-container>\n }\n }\n</section>\n\n<ng-template #menuItemOpened let-level=\"level\" let-navigation_item=\"navigation_item\">\n @let isExpanded = expandedIds().has(navigation_item.code);\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let icon = navigation_item.icon;\n @let isHighlighted = selectedSection() === code;\n\n <a\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [@fadeInOut]\n [class.menu-item_selected]=\"isHighlighted\"\n [class.padding-level-0]=\"level === 0\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n [style.padding-left.px]=\"level === 0 ? 0 : 44 + level * 20\"\n class=\"menu-item\"\n >\n @if (icon) {\n <span class=\"menu-item__icon\">\n <img [alt]=\"icon\" [width]=\"16\" [height]=\"16\" [ngSrc]=\"menuIconsSrc() + icon + '.svg'\">\n </span>\n }\n <span class=\"menu-item__title\"> {{ navigation_item.title }} </span>\n @if (childrenCount > 0) {\n <img\n class=\"menu-item__chevron\"\n [class.menu-item__chevron_rotated]=\"!isExpanded\"\n [alt]=\"icon\" [width]=\"16\" [height]=\"16\"\n [ngSrc]=\"ICONS_SRC.CHEVRON_UP\">\n }\n </a>\n @if (isExpanded && childrenCount > 0) {\n @for (children of navigation_item.children ?? []; track $index) {\n <ng-container\n *ngTemplateOutlet=\"menuItemOpened; context: { navigation_item: children, level: level + 1 }\"\n ></ng-container>\n }\n }\n</ng-template>\n\n<ng-template #closedMenu let-navigation_item=\"navigation_item\">\n @let isExpanded = expandedIds().has(navigation_item.code);\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let icon = navigation_item.icon;\n @let isHighlighted = selectedSection() === code || parentItemCodes().has(code);\n\n <div\n (mouseleave)=\"collapseMenu()\"\n [id]=\"navigation_item.id\"\n class=\"collapsed-menu-content\"\n >\n @if (icon) {\n <a\n class=\"menu-item__icon_closed\"\n [class.menu-item_selected]=\"isHighlighted\"\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n (mouseenter)=\"toggleItem(navigation_item)\">\n <img\n [height]=\"16\"\n [width]=\"16\"\n [ngSrc]=\"menuIconsSrc() + icon + '.svg'\" alt=\"Menu Chevron\"/>\n </a>\n }\n <ng-container\n *ngTemplateOutlet=\"\n menuClosedItem;\n context: { item: navigation_item, level: 1, topPadding: 1 }\n \"\n >\n </ng-container>\n @if (isExpanded && childrenCount > 0) {\n <div class=\"static-item\">\n <span class=\"static-item__element\">\n {{ navigation_item.title }}\n </span>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #menuClosedItem let-item=\"item\" let-level=\"level\" let-topPadding=\"topPadding\">\n @let isExpanded = expandedIds().has(item.code);\n <div [id]=\"item.id\">\n @if (isExpanded && item.children.length > 0) {\n <div\n class=\"side-menu__subitems\"\n [class.padding-level-1]=\"level === 1\"\n [style.top.px]=\"topPadding * 40\"\n id=\"side-menu__subitems\"\n >\n @for (navigation_item of item.children; track navigation_item; let index = $index) {\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let isHighlighted = selectedSection() === code || parentItemCodes().has(code);\n <a\n class=\"side-menu__subitem\"\n [class.menu-item_selected]=\"isHighlighted\"\n (mouseenter)=\"childrenCount > 0 ? toggleItem(navigation_item) : collapseMenu(navigation_item)\"\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n >\n <span\n [class.padding-level-1]=\"level === 1\">{{\n navigation_item.title\n }}</span>\n\n @if (childrenCount > 0) {\n <img\n class=\"chevron-right\"\n [height]=\"16\"\n [width]=\"16\"\n [ngSrc]=\"ICONS_SRC.CHEVRON_RIGHT\" alt=\"Menu Chevron\"/>\n }\n </a>\n <ng-container\n *ngTemplateOutlet=\"\n menuClosedItem;\n context: { item: navigation_item, level: level + 1, topPadding: index }\n \"\n ></ng-container>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{background:var(--page-menu-main);height:100vh;max-height:100vh;z-index:1000;display:flex}:host tui-icon{width:16px;height:16px}:host ::-webkit-scrollbar{width:6px;background:var(--page-menu-main)}:host ::-webkit-scrollbar-thumb{width:6px;background:#c3c7cf;border-radius:2px}:host .side-menu{transition:all var(--page-menu-transition-time);display:flex;color:var(--main-white);flex-direction:column;flex-shrink:0;font-size:14px}:host .side-menu__header{height:64px;width:100%;display:flex;align-items:center;justify-content:space-between}:host .side-menu__header__chevron{cursor:pointer;transition:rotate .15s linear}:host .side-menu__header__chevron_opened{margin:0 8px 0 0;rotate:0deg}:host .side-menu__header__chevron_closed{margin:0 0 0 -4px;rotate:180deg}:host .side-menu__header .disabled{pointer-events:none}:host .side-menu__header__logo{margin-left:8px}:host .side-menu_opened{width:var(--page-menu-opened-width)}:host .side-menu_closed{width:var(--page-menu-closed-width)}:host .side-menu__subitems,:host .side-menu .static-item{position:absolute;display:flex;z-index:3;right:0;top:0;flex-direction:column}:host .side-menu__subitems{width:294px;box-shadow:0 2px 6px #28282840;left:294px}:host .side-menu__subitems.padding-level-1{left:48px}:host .side-menu__subitems .chevron-right{margin-right:16px}:host .side-menu__subitems a span{height:40px;display:flex;align-items:center;padding-left:40px}:host .side-menu__subitems a span .padding-level-1{padding-left:64px}:host .side-menu .static-item{color:var(--main-black);left:48px;top:0}:host .side-menu__subitem,:host .side-menu .static-item__element{box-sizing:border-box;display:flex;align-items:center;color:var(--main-white);height:40px;width:294px;background:var(--page-menu-main);justify-content:space-between}:host .side-menu__subitem:hover{background:var(--page-menu-main-hovered);cursor:pointer}:host .side-menu .static-item__element{justify-content:unset;padding-left:16px}:host .side-menu .expanded-menu-content{height:calc(100vh - 103px);-ms-overflow-style:none;scrollbar-width:none;overflow-y:scroll}:host .side-menu .expanded-menu-content::-webkit-scrollbar{display:none}:host .side-menu .collapsed-menu-content{position:relative}:host .side-menu .menu-item{display:flex;flex-direction:row;cursor:pointer;justify-content:start;align-items:center;box-sizing:border-box;transition:background .9ms;height:40px}:host .side-menu .menu-item_selected{background:var(--page-menu-active)!important;box-shadow:inset 3px 0 var(--main-white)}:host .side-menu .menu-item_selected:hover{background:var(--page-menu-active)!important}:host .side-menu .menu-item__chevron{margin-left:auto;margin-right:8px;transition:rotate .15s linear}:host .side-menu .menu-item__chevron_rotated{rotate:180deg}:host .side-menu .menu-item__title{padding:10px 0 10px 8px;overflow:hidden;color:var(--main-white);font-variant-numeric:lining-nums tabular-nums;text-overflow:ellipsis;white-space:nowrap;font-family:Inter,serif;font-size:14px;font-weight:300}:host .side-menu .menu-item__title .page-menu-text-14px{font-family:Inter,serif;font-size:14px;font-weight:300}:host .side-menu .menu-item__icon{padding:0 8px 0 16px}:host .side-menu .menu-item__icon_closed{display:flex;height:40px;justify-content:center;align-items:center}:host .side-menu .menu-item__icon_closed:hover{background:var(--page-menu-main-hovered);cursor:pointer}:host .side-menu .menu-item:hover{background:var(--page-menu-main-hovered)}:host a{text-decoration:none;color:unset}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }], animations: [
5670
- trigger('fadeInOut', [
5671
- transition(':enter', [
5672
- style({
5673
- opacity: 0,
5674
- transform: 'translateY(-10px)',
5675
- transformOrigin: 'top',
5676
- }),
5677
- animate('0.15s ease-in', style({
5678
- opacity: 1,
5679
- transform: 'translateY(0)',
5680
- })),
5681
- ]),
5682
- ]),
5683
- ], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5684
- }
5685
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SprocPageMenuComponent, decorators: [{
5686
- type: Component,
5687
- args: [{ selector: 'sproc-page-menu', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [RouterLink, NgTemplateOutlet, NgClass, AsyncPipe, NgOptimizedImage], animations: [
5688
- trigger('fadeInOut', [
5689
- transition(':enter', [
5690
- style({
5691
- opacity: 0,
5692
- transform: 'translateY(-10px)',
5693
- transformOrigin: 'top',
5694
- }),
5695
- animate('0.15s ease-in', style({
5696
- opacity: 1,
5697
- transform: 'translateY(0)',
5698
- })),
5699
- ]),
5700
- ]),
5701
- ], template: "<section [class]=\"menuState() ? 'side-menu side-menu_opened' : 'side-menu side-menu_closed'\">\n <div class=\"side-menu__header\">\n <img\n [src]=\"menuState() ? openLogoSrc() : closedLogoSrc()\"\n alt=\"Logo Icon\"\n class=\"side-menu__header__logo\"\n />\n <img\n (click)=\"toggleNavigation()\"\n [class.disabled]=\"toggleDisabled$ | async\"\n [height]=\"16\"\n [ngClass]=\"menuState() ? 'side-menu__header__chevron_opened' : 'side-menu__header__chevron_closed'\"\n [ngSrc]=\"ICONS_SRC.MENU_CHEVRON\" [width]=\"16\" alt=\"Menu Chevron\"/>\n </div>\n\n @if (menuState()) {\n <div class=\"expanded-menu-content\">\n @for (navigation_item of navigationHierarchy(); track $index) {\n <ng-container\n *ngTemplateOutlet=\"\n menuItemOpened;\n context: { navigation_item: navigation_item, level: 0 }\n \"\n ></ng-container>\n }\n </div>\n\n <ng-content></ng-content>\n } @else {\n @for (navigation_item of navigationHierarchy(); track $index) {\n <ng-container\n *ngTemplateOutlet=\"closedMenu; context: { navigation_item: navigation_item }\"\n ></ng-container>\n }\n }\n</section>\n\n<ng-template #menuItemOpened let-level=\"level\" let-navigation_item=\"navigation_item\">\n @let isExpanded = expandedIds().has(navigation_item.code);\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let icon = navigation_item.icon;\n @let isHighlighted = selectedSection() === code;\n\n <a\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [@fadeInOut]\n [class.menu-item_selected]=\"isHighlighted\"\n [class.padding-level-0]=\"level === 0\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n [style.padding-left.px]=\"level === 0 ? 0 : 44 + level * 20\"\n class=\"menu-item\"\n >\n @if (icon) {\n <span class=\"menu-item__icon\">\n <img [alt]=\"icon\" [width]=\"16\" [height]=\"16\" [ngSrc]=\"menuIconsSrc() + icon + '.svg'\">\n </span>\n }\n <span class=\"menu-item__title\"> {{ navigation_item.title }} </span>\n @if (childrenCount > 0) {\n <img\n class=\"menu-item__chevron\"\n [class.menu-item__chevron_rotated]=\"!isExpanded\"\n [alt]=\"icon\" [width]=\"16\" [height]=\"16\"\n [ngSrc]=\"ICONS_SRC.CHEVRON_UP\">\n }\n </a>\n @if (isExpanded && childrenCount > 0) {\n @for (children of navigation_item.children ?? []; track $index) {\n <ng-container\n *ngTemplateOutlet=\"menuItemOpened; context: { navigation_item: children, level: level + 1 }\"\n ></ng-container>\n }\n }\n</ng-template>\n\n<ng-template #closedMenu let-navigation_item=\"navigation_item\">\n @let isExpanded = expandedIds().has(navigation_item.code);\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let icon = navigation_item.icon;\n @let isHighlighted = selectedSection() === code || parentItemCodes().has(code);\n\n <div\n (mouseleave)=\"collapseMenu()\"\n [id]=\"navigation_item.id\"\n class=\"collapsed-menu-content\"\n >\n @if (icon) {\n <a\n class=\"menu-item__icon_closed\"\n [class.menu-item_selected]=\"isHighlighted\"\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n (mouseenter)=\"toggleItem(navigation_item)\">\n <img\n [height]=\"16\"\n [width]=\"16\"\n [ngSrc]=\"menuIconsSrc() + icon + '.svg'\" alt=\"Menu Chevron\"/>\n </a>\n }\n <ng-container\n *ngTemplateOutlet=\"\n menuClosedItem;\n context: { item: navigation_item, level: 1, topPadding: 1 }\n \"\n >\n </ng-container>\n @if (isExpanded && childrenCount > 0) {\n <div class=\"static-item\">\n <span class=\"static-item__element\">\n {{ navigation_item.title }}\n </span>\n </div>\n }\n </div>\n</ng-template>\n\n<ng-template #menuClosedItem let-item=\"item\" let-level=\"level\" let-topPadding=\"topPadding\">\n @let isExpanded = expandedIds().has(item.code);\n <div [id]=\"item.id\">\n @if (isExpanded && item.children.length > 0) {\n <div\n class=\"side-menu__subitems\"\n [class.padding-level-1]=\"level === 1\"\n [style.top.px]=\"topPadding * 40\"\n id=\"side-menu__subitems\"\n >\n @for (navigation_item of item.children; track navigation_item; let index = $index) {\n @let childrenCount = navigation_item.children.length;\n @let code = navigation_item.code;\n @let route = navigation_item.code;\n @let isHighlighted = selectedSection() === code || parentItemCodes().has(code);\n <a\n class=\"side-menu__subitem\"\n [class.menu-item_selected]=\"isHighlighted\"\n (mouseenter)=\"childrenCount > 0 ? toggleItem(navigation_item) : collapseMenu(navigation_item)\"\n (click)=\"childrenCount === 0 ? handleNavigation(navigation_item) : toggleItem(navigation_item)\"\n [routerLink]=\"childrenCount > 0 || isExternalLink(route) ? undefined : route\"\n >\n <span\n [class.padding-level-1]=\"level === 1\">{{\n navigation_item.title\n }}</span>\n\n @if (childrenCount > 0) {\n <img\n class=\"chevron-right\"\n [height]=\"16\"\n [width]=\"16\"\n [ngSrc]=\"ICONS_SRC.CHEVRON_RIGHT\" alt=\"Menu Chevron\"/>\n }\n </a>\n <ng-container\n *ngTemplateOutlet=\"\n menuClosedItem;\n context: { item: navigation_item, level: level + 1, topPadding: index }\n \"\n ></ng-container>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{background:var(--page-menu-main);height:100vh;max-height:100vh;z-index:1000;display:flex}:host tui-icon{width:16px;height:16px}:host ::-webkit-scrollbar{width:6px;background:var(--page-menu-main)}:host ::-webkit-scrollbar-thumb{width:6px;background:#c3c7cf;border-radius:2px}:host .side-menu{transition:all var(--page-menu-transition-time);display:flex;color:var(--main-white);flex-direction:column;flex-shrink:0;font-size:14px}:host .side-menu__header{height:64px;width:100%;display:flex;align-items:center;justify-content:space-between}:host .side-menu__header__chevron{cursor:pointer;transition:rotate .15s linear}:host .side-menu__header__chevron_opened{margin:0 8px 0 0;rotate:0deg}:host .side-menu__header__chevron_closed{margin:0 0 0 -4px;rotate:180deg}:host .side-menu__header .disabled{pointer-events:none}:host .side-menu__header__logo{margin-left:8px}:host .side-menu_opened{width:var(--page-menu-opened-width)}:host .side-menu_closed{width:var(--page-menu-closed-width)}:host .side-menu__subitems,:host .side-menu .static-item{position:absolute;display:flex;z-index:3;right:0;top:0;flex-direction:column}:host .side-menu__subitems{width:294px;box-shadow:0 2px 6px #28282840;left:294px}:host .side-menu__subitems.padding-level-1{left:48px}:host .side-menu__subitems .chevron-right{margin-right:16px}:host .side-menu__subitems a span{height:40px;display:flex;align-items:center;padding-left:40px}:host .side-menu__subitems a span .padding-level-1{padding-left:64px}:host .side-menu .static-item{color:var(--main-black);left:48px;top:0}:host .side-menu__subitem,:host .side-menu .static-item__element{box-sizing:border-box;display:flex;align-items:center;color:var(--main-white);height:40px;width:294px;background:var(--page-menu-main);justify-content:space-between}:host .side-menu__subitem:hover{background:var(--page-menu-main-hovered);cursor:pointer}:host .side-menu .static-item__element{justify-content:unset;padding-left:16px}:host .side-menu .expanded-menu-content{height:calc(100vh - 103px);-ms-overflow-style:none;scrollbar-width:none;overflow-y:scroll}:host .side-menu .expanded-menu-content::-webkit-scrollbar{display:none}:host .side-menu .collapsed-menu-content{position:relative}:host .side-menu .menu-item{display:flex;flex-direction:row;cursor:pointer;justify-content:start;align-items:center;box-sizing:border-box;transition:background .9ms;height:40px}:host .side-menu .menu-item_selected{background:var(--page-menu-active)!important;box-shadow:inset 3px 0 var(--main-white)}:host .side-menu .menu-item_selected:hover{background:var(--page-menu-active)!important}:host .side-menu .menu-item__chevron{margin-left:auto;margin-right:8px;transition:rotate .15s linear}:host .side-menu .menu-item__chevron_rotated{rotate:180deg}:host .side-menu .menu-item__title{padding:10px 0 10px 8px;overflow:hidden;color:var(--main-white);font-variant-numeric:lining-nums tabular-nums;text-overflow:ellipsis;white-space:nowrap;font-family:Inter,serif;font-size:14px;font-weight:300}:host .side-menu .menu-item__title .page-menu-text-14px{font-family:Inter,serif;font-size:14px;font-weight:300}:host .side-menu .menu-item__icon{padding:0 8px 0 16px}:host .side-menu .menu-item__icon_closed{display:flex;height:40px;justify-content:center;align-items:center}:host .side-menu .menu-item__icon_closed:hover{background:var(--page-menu-main-hovered);cursor:pointer}:host .side-menu .menu-item:hover{background:var(--page-menu-main-hovered)}:host a{text-decoration:none;color:unset}\n"] }]
5702
- }], ctorParameters: () => [], propDecorators: { menuOpenedWidth: [{
5703
- type: HostBinding,
5704
- args: ['style.--page-menu-opened-width']
5705
- }], menuClosedWidth: [{
5706
- type: HostBinding,
5707
- args: ['style.--page-menu-closed-width']
5708
- }] } });
5709
-
5710
- class AbstractMenuStateService {
5711
- }
5712
-
5713
5711
  const ROOT_TITLE = 'root';
5714
5712
  const NEW_ITEM_PREFIX = 'NEW_';
5715
5713
  const MIGRATION_HINT = 'Генерирует SQL код для миграции таблицы cls_menu_item. Генерация кода происходит на основе последней версии сохраненного меню.';
@@ -7463,5 +7461,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
7463
7461
  * Generated bundle index. Do not edit.
7464
7462
  */
7465
7463
 
7466
- export { AbstractMenuStateService, CARD, CellTemplateDirective, ColumnSettingsComponent, DateTimeService, DialogService, EColumnDataType, EColumnStatus, EInputsAction, EInputsState, EMPTY_UUID, EMonth, EOrder, EPageMenuIconsSrc, ERegisterObjectState, ESwitcherValue, FastQueryStore, FilterButtonComponent, FiltersService, FiltersStateService, FiltersTransmitService, FormGroupWrapper, INPUTS_STATE_CONFIG_KEY, InputControl, InputsModule, MAX_LENGTH_TEXT_PARAMS, MENU_CONSTRUCTOR_STORE_TOKEN, MENU_STATE_SERVICE, MIGRATION_HINT, MonthMapper, MonthsName, MonthsNumber, NEW_ITEM_PREFIX, NumberOnlyDirective, PAGE_MENU_STATE, ParamBase, ParamCalendarYearComponent, ParamCustomComponent, ParamDateBase, ParamDateComponent, ParamDateRangeComponent, ParamDateTimeComponent, ParamDateTimeRangeComponent, ParamMonthComponent, ParamMonthRangeComponent, ParamMultiSelectComponent, ParamSelectBase, ParamSelectComponent, ParamSwitcherComponent, ParamSwitcherDateTimeRangeComponent, ParamTextBase, ParamTextComponent, ParamTextareaComponent, ParamToggleComponent, ParamTreeComponent, ParamTreeMultiSelectComponent, ParamTreeSelectComponent, ParamTreeService, ROOT_TITLE, RegisterBase, RegisterBaseStore, RegisterTableComponent, RegisterTableFilterComponent, RegisterTableFilterModule, ResizeWindowObserverService, SELECT_ALL_ID, SELECT_ALL_NAME, SETTINGS_TYPE, SIDE_MENU_CLOSED_WIDTH, SIDE_MENU_OPENED_WIDTH, SearchInputComponent, SelectedObjectsStateService, SlidingPanelComponent, SlidingPanelModule, SprocAbstractMenuConstructorStore, SprocMenuConstructorComponent, SprocPageMenuComponent, StickyDirective, StickyRelativeDirective, SyncTreeLoaderService, TIME_ZONES, TIME_ZONE_HINTS, TREE_LOADER, TREE_LOADING_NODE, USER_PROFILE_LOADER, USER_SETTINGS_LOADER, distinctUntilChangedJSONs, getFirstSegmentOfPathName, getLastSegmentOfPathName, isDefined, isNonNull, just, moveInEventLoopIteration, removeSelectAll, selectAllItem, timezoneSelectItems, toPx, transformItemToNode };
7464
+ export { AbstractMenuStateService, CARD, CellTemplateDirective, ColumnSettingsComponent, DateTimeService, DialogService, EColumnDataType, EColumnStatus, EInputsAction, EInputsState, EMPTY_UUID, EMonth, EOrder, EPageMenuIconsSrc, ERegisterObjectState, ESwitcherValue, FastQueryStore, FilterButtonComponent, FiltersService, FiltersStateService, FiltersTransmitService, FormGroupWrapper, INPUTS_STATE_CONFIG_KEY, InputControl, InputsModule, MAX_LENGTH_TEXT_PARAMS, MENU_CONSTRUCTOR_STORE_TOKEN, MIGRATION_HINT, MonthMapper, MonthsName, MonthsNumber, NEW_ITEM_PREFIX, NumberOnlyDirective, PAGE_MENU_STATE, ParamBase, ParamCalendarYearComponent, ParamCustomComponent, ParamDateBase, ParamDateComponent, ParamDateRangeComponent, ParamDateTimeComponent, ParamDateTimeRangeComponent, ParamMonthComponent, ParamMonthRangeComponent, ParamMultiSelectComponent, ParamSelectBase, ParamSelectComponent, ParamSwitcherComponent, ParamSwitcherDateTimeRangeComponent, ParamTextBase, ParamTextComponent, ParamTextareaComponent, ParamToggleComponent, ParamTreeComponent, ParamTreeMultiSelectComponent, ParamTreeSelectComponent, ParamTreeService, ROOT_TITLE, RegisterBase, RegisterBaseStore, RegisterTableComponent, RegisterTableFilterComponent, RegisterTableFilterModule, ResizeWindowObserverService, SELECT_ALL_ID, SELECT_ALL_NAME, SETTINGS_TYPE, SIDE_MENU_CLOSED_WIDTH, SIDE_MENU_OPENED_WIDTH, SearchInputComponent, SelectedObjectsStateService, SlidingPanelComponent, SlidingPanelModule, SprocAbstractMenuConstructorStore, SprocMenuConstructorComponent, SprocPageMenuComponent, StickyDirective, StickyRelativeDirective, SyncTreeLoaderService, TIME_ZONES, TIME_ZONE_HINTS, TREE_LOADER, TREE_LOADING_NODE, USER_PROFILE_LOADER, USER_SETTINGS_LOADER, distinctUntilChangedJSONs, getFirstSegmentOfPathName, getLastSegmentOfPathName, isDefined, isNonNull, just, moveInEventLoopIteration, removeSelectAll, selectAllItem, timezoneSelectItems, toPx, transformItemToNode };
7467
7465
  //# sourceMappingURL=ngx-register-base.mjs.map