@cuby-ui/core 0.0.227 → 0.0.231
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/button/button.component.d.ts +1 -1
- package/components/content-wrapper/content-wrapper.component.d.ts +11 -0
- package/components/content-wrapper/index.d.ts +1 -0
- package/components/empty-state/empty-state.component.d.ts +7 -0
- package/components/empty-state/index.d.ts +1 -0
- package/components/ghost-input/ghost-input.component.d.ts +6 -0
- package/components/ghost-input/index.d.ts +1 -0
- package/components/index.d.ts +3 -0
- package/components/sidebar/sidebar-header/sidebar-header.component.d.ts +1 -1
- package/components/sidebar/sidebar-navigation-item/sidebar-navigation-item.component.d.ts +1 -1
- package/editor/components/editor-attaches-tool/editor-attaches-tool.component.d.ts +44 -0
- package/editor/components/editor-attaches-tool/editor-attaches-tool.options.d.ts +17 -0
- package/editor/components/editor-attaches-tool/index.d.ts +2 -0
- package/editor/components/editor-image-tool/editor-image-tool.component.d.ts +14 -0
- package/editor/components/editor-image-tool/editor-image-tool.options.d.ts +26 -0
- package/editor/components/editor-image-tool/index.d.ts +2 -0
- package/editor/components/editor-tool/editor-tool.component.d.ts +22 -0
- package/editor/components/editor-tool-modal/editor-tool-modal.component.d.ts +24 -0
- package/editor/components/editor-tool-modal/editor-tool-modal.options.d.ts +8 -0
- package/editor/components/editor-tool-modal/index.d.ts +2 -0
- package/editor/components/editor-tooltip/editor-tooltip.component.d.ts +16 -0
- package/editor/components/editor-tooltip/editor-tooltip.options.d.ts +9 -0
- package/editor/components/editor-tooltip/index.d.ts +2 -0
- package/editor/components/editor-video-tool/editor-video-tool.component.d.ts +12 -0
- package/editor/components/editor-video-tool/editor-video-tool.options.d.ts +26 -0
- package/editor/components/editor-video-tool/index.d.ts +2 -0
- package/editor/components/index.d.ts +7 -0
- package/editor/components/marker-modal/index.d.ts +3 -0
- package/editor/components/marker-modal/marker-modal.component.d.ts +62 -0
- package/editor/components/marker-modal/marker-modal.interfaces.d.ts +7 -0
- package/editor/components/marker-modal/marker-modal.options.d.ts +1 -0
- package/editor/components/marker-select/component/select-item/select-option.component.d.ts +7 -0
- package/editor/components/marker-select/index.d.ts +2 -0
- package/editor/components/marker-select/marker-select.component.d.ts +40 -0
- package/editor/components/marker-select/marker-select.options.d.ts +1 -0
- package/editor/config/custom-elements.d.ts +2 -0
- package/editor/config/editor.config.d.ts +3 -0
- package/editor/config/editor.provider.d.ts +2 -0
- package/editor/config/index.d.ts +2 -0
- package/editor/constants/editor.constants.d.ts +15 -0
- package/editor/constants/index.d.ts +1 -0
- package/editor/editor.component.d.ts +71 -0
- package/editor/events/editor-drag.event.d.ts +2 -0
- package/editor/events/editor-keyboard.event.d.ts +2 -0
- package/editor/events/editor-modal.event.d.ts +3 -0
- package/editor/events/editor-tooltip.event.d.ts +2 -0
- package/editor/events/set-editor-events.d.ts +1 -0
- package/editor/index.d.ts +9 -0
- package/editor/interfaces/angular-element.d.ts +2 -0
- package/editor/interfaces/blocks-request-data.d.ts +6 -0
- package/editor/interfaces/combined-block-adding-event.d.ts +7 -0
- package/editor/interfaces/combined-block-data.d.ts +5 -0
- package/editor/interfaces/combined-part-block-data.d.ts +7 -0
- package/editor/interfaces/custom-element.d.ts +5 -0
- package/editor/interfaces/event-action-data.d.ts +5 -0
- package/editor/interfaces/file-response-data.d.ts +10 -0
- package/editor/interfaces/full-block-data.d.ts +8 -0
- package/editor/interfaces/index.d.ts +14 -0
- package/editor/interfaces/main-editor-config.d.ts +15 -0
- package/editor/interfaces/mutation-actions.d.ts +5 -0
- package/editor/interfaces/parent.d.ts +4 -0
- package/editor/interfaces/tools.d.ts +4 -0
- package/editor/interfaces/tune.d.ts +6 -0
- package/editor/pipes/file-size.pipe.d.ts +9 -0
- package/editor/services/editor-service.options.d.ts +8 -0
- package/editor/services/editor.service.d.ts +23 -0
- package/editor/services/index.d.ts +6 -0
- package/editor/services/jtext-api.options.d.ts +20 -0
- package/editor/services/jtext-api.service.d.ts +23 -0
- package/editor/services/markers-service.options.d.ts +4 -0
- package/editor/services/markers.service.d.ts +11 -0
- package/editor/tools/attaches.tool.d.ts +28 -0
- package/editor/tools/bold.tool.d.ts +11 -0
- package/editor/tools/combined-text-block.tool.d.ts +49 -0
- package/editor/tools/custom-marker.tool.d.ts +16 -0
- package/editor/tools/header.tool.d.ts +8 -0
- package/editor/tools/image.tool.d.ts +37 -0
- package/editor/tools/index.d.ts +11 -0
- package/editor/tools/italic.tool.d.ts +12 -0
- package/editor/tools/link-marker.tool.d.ts +15 -0
- package/editor/tools/list.tool.d.ts +5 -0
- package/editor/tools/marker.tool.d.ts +36 -0
- package/editor/tools/role-marker.tool.d.ts +7 -0
- package/editor/tools/selection-base.tool.d.ts +24 -0
- package/editor/tools/tool-marker.tool.d.ts +7 -0
- package/editor/tools/video.tool.d.ts +32 -0
- package/editor/utils/create-link-modal.d.ts +3 -0
- package/editor/utils/create-tool-modal.d.ts +4 -0
- package/editor/utils/create-tooltip.d.ts +8 -0
- package/editor/utils/file-uploader.d.ts +26 -0
- package/editor/utils/generate-id.d.ts +1 -0
- package/editor/utils/index.d.ts +9 -0
- package/editor/utils/recalculate-indexes.d.ts +2 -0
- package/editor/utils/remove-element-tag-wrapper.d.ts +1 -0
- package/editor/utils/split-html.d.ts +1 -0
- package/editor/utils/url.validator.d.ts +2 -0
- package/editor/widgets/editor-block/editor-block.component.d.ts +22 -0
- package/editor/widgets/editor-block/index.d.ts +1 -0
- package/editor/widgets/editor-modal/editor-modal.component.d.ts +19 -0
- package/editor/widgets/editor-modal/index.d.ts +1 -0
- package/editor/widgets/editor-readonly/editor-readonly.component.d.ts +28 -0
- package/editor/widgets/editor-readonly/editor-readonly.options.d.ts +5 -0
- package/editor/widgets/editor-readonly/index.d.ts +2 -0
- package/editor/widgets/index.d.ts +3 -0
- package/esm2022/components/breadcrumbs/breadcrumbs.component.mjs +2 -2
- package/esm2022/components/content-wrapper/content-wrapper.component.mjs +29 -0
- package/esm2022/components/content-wrapper/index.mjs +2 -0
- package/esm2022/components/empty-state/empty-state.component.mjs +17 -0
- package/esm2022/components/empty-state/index.mjs +2 -0
- package/esm2022/components/ghost-input/ghost-input.component.mjs +16 -0
- package/esm2022/components/ghost-input/index.mjs +2 -0
- package/esm2022/components/index.mjs +4 -1
- package/esm2022/directives/tooltip/tooltip-describe.directive.mjs +5 -3
- package/esm2022/directives/tooltip/tooltip-position.directive.mjs +6 -3
- package/esm2022/directives/tooltip/tooltip.component.mjs +6 -3
- package/esm2022/editor/components/editor-attaches-tool/editor-attaches-tool.component.mjs +76 -0
- package/esm2022/editor/components/editor-attaches-tool/editor-attaches-tool.options.mjs +2 -0
- package/esm2022/editor/components/editor-attaches-tool/index.mjs +3 -0
- package/esm2022/editor/components/editor-image-tool/editor-image-tool.component.mjs +43 -0
- package/esm2022/editor/components/editor-image-tool/editor-image-tool.options.mjs +2 -0
- package/esm2022/editor/components/editor-image-tool/index.mjs +3 -0
- package/esm2022/editor/components/editor-tool/editor-tool.component.mjs +74 -0
- package/esm2022/editor/components/editor-tool-modal/editor-tool-modal.component.mjs +69 -0
- package/esm2022/editor/components/editor-tool-modal/editor-tool-modal.options.mjs +2 -0
- package/esm2022/editor/components/editor-tool-modal/index.mjs +3 -0
- package/esm2022/editor/components/editor-tooltip/editor-tooltip.component.mjs +45 -0
- package/esm2022/editor/components/editor-tooltip/editor-tooltip.options.mjs +2 -0
- package/esm2022/editor/components/editor-tooltip/index.mjs +3 -0
- package/esm2022/editor/components/editor-video-tool/editor-video-tool.component.mjs +41 -0
- package/esm2022/editor/components/editor-video-tool/editor-video-tool.options.mjs +2 -0
- package/esm2022/editor/components/editor-video-tool/index.mjs +3 -0
- package/esm2022/editor/components/index.mjs +8 -0
- package/esm2022/editor/components/marker-modal/index.mjs +3 -0
- package/esm2022/editor/components/marker-modal/marker-modal.component.mjs +261 -0
- package/esm2022/editor/components/marker-modal/marker-modal.interfaces.mjs +2 -0
- package/esm2022/editor/components/marker-modal/marker-modal.options.mjs +2 -0
- package/esm2022/editor/components/marker-select/component/select-item/select-option.component.mjs +15 -0
- package/esm2022/editor/components/marker-select/index.mjs +3 -0
- package/esm2022/editor/components/marker-select/marker-select.component.mjs +155 -0
- package/esm2022/editor/components/marker-select/marker-select.options.mjs +2 -0
- package/esm2022/editor/config/custom-elements.mjs +32 -0
- package/esm2022/editor/config/editor.config.mjs +30 -0
- package/esm2022/editor/config/editor.provider.mjs +19 -0
- package/esm2022/editor/config/index.mjs +3 -0
- package/esm2022/editor/constants/editor.constants.mjs +20 -0
- package/esm2022/editor/constants/index.mjs +2 -0
- package/esm2022/editor/editor.component.mjs +380 -0
- package/esm2022/editor/events/editor-drag.event.mjs +7 -0
- package/esm2022/editor/events/editor-keyboard.event.mjs +33 -0
- package/esm2022/editor/events/editor-modal.event.mjs +31 -0
- package/esm2022/editor/events/editor-tooltip.event.mjs +63 -0
- package/esm2022/editor/events/set-editor-events.mjs +11 -0
- package/esm2022/editor/i18n/en.json +14 -0
- package/esm2022/editor/index.mjs +8 -0
- package/esm2022/editor/interfaces/angular-element.mjs +2 -0
- package/esm2022/editor/interfaces/blocks-request-data.mjs +2 -0
- package/esm2022/editor/interfaces/combined-block-adding-event.mjs +2 -0
- package/esm2022/editor/interfaces/combined-block-data.mjs +2 -0
- package/esm2022/editor/interfaces/combined-part-block-data.mjs +2 -0
- package/esm2022/editor/interfaces/custom-element.mjs +2 -0
- package/esm2022/editor/interfaces/event-action-data.mjs +2 -0
- package/esm2022/editor/interfaces/file-response-data.mjs +2 -0
- package/esm2022/editor/interfaces/full-block-data.mjs +2 -0
- package/esm2022/editor/interfaces/index.mjs +14 -0
- package/esm2022/editor/interfaces/main-editor-config.mjs +2 -0
- package/esm2022/editor/interfaces/mutation-actions.mjs +2 -0
- package/esm2022/editor/interfaces/parent.mjs +2 -0
- package/esm2022/editor/interfaces/tools.mjs +2 -0
- package/esm2022/editor/interfaces/tune.mjs +2 -0
- package/esm2022/editor/pipes/file-size.pipe.mjs +25 -0
- package/esm2022/editor/services/editor-service.options.mjs +4 -0
- package/esm2022/editor/services/editor.service.mjs +138 -0
- package/esm2022/editor/services/index.mjs +7 -0
- package/esm2022/editor/services/jtext-api.options.mjs +2 -0
- package/esm2022/editor/services/jtext-api.service.mjs +50 -0
- package/esm2022/editor/services/markers-service.options.mjs +2 -0
- package/esm2022/editor/services/markers.service.mjs +79 -0
- package/esm2022/editor/tools/attaches.tool.mjs +96 -0
- package/esm2022/editor/tools/bold.tool.mjs +33 -0
- package/esm2022/editor/tools/combined-text-block.tool.mjs +380 -0
- package/esm2022/editor/tools/custom-marker.tool.mjs +88 -0
- package/esm2022/editor/tools/header.tool.mjs +16 -0
- package/esm2022/editor/tools/image.tool.mjs +157 -0
- package/esm2022/editor/tools/index.mjs +12 -0
- package/esm2022/editor/tools/italic.tool.mjs +35 -0
- package/esm2022/editor/tools/link-marker.tool.mjs +80 -0
- package/esm2022/editor/tools/list.tool.mjs +10 -0
- package/esm2022/editor/tools/marker.tool.mjs +144 -0
- package/esm2022/editor/tools/role-marker.tool.mjs +17 -0
- package/esm2022/editor/tools/selection-base.tool.mjs +92 -0
- package/esm2022/editor/tools/tool-marker.tool.mjs +14 -0
- package/esm2022/editor/tools/video.tool.mjs +132 -0
- package/esm2022/editor/utils/create-link-modal.mjs +22 -0
- package/esm2022/editor/utils/create-tool-modal.mjs +45 -0
- package/esm2022/editor/utils/create-tooltip.mjs +44 -0
- package/esm2022/editor/utils/file-uploader.mjs +57 -0
- package/esm2022/editor/utils/generate-id.mjs +4 -0
- package/esm2022/editor/utils/index.mjs +10 -0
- package/esm2022/editor/utils/recalculate-indexes.mjs +32 -0
- package/esm2022/editor/utils/remove-element-tag-wrapper.mjs +11 -0
- package/esm2022/editor/utils/split-html.mjs +128 -0
- package/esm2022/editor/utils/url.validator.mjs +12 -0
- package/esm2022/editor/widgets/editor-block/editor-block.component.mjs +63 -0
- package/esm2022/editor/widgets/editor-block/index.mjs +2 -0
- package/esm2022/editor/widgets/editor-modal/editor-modal.component.mjs +47 -0
- package/esm2022/editor/widgets/editor-modal/index.mjs +2 -0
- package/esm2022/editor/widgets/editor-readonly/editor-readonly.component.mjs +40 -0
- package/esm2022/editor/widgets/editor-readonly/editor-readonly.options.mjs +2 -0
- package/esm2022/editor/widgets/editor-readonly/index.mjs +2 -0
- package/esm2022/editor/widgets/index.mjs +4 -0
- package/esm2022/index.mjs +3 -1
- package/esm2022/interceptors/loader.interceptor.mjs +3 -3
- package/esm2022/services/loader.options.mjs +2 -2
- package/esm2022/services/loader.service.mjs +11 -11
- package/esm2022/utils/default-validators/create-default-validators.mjs +12 -0
- package/esm2022/utils/default-validators/extra-spaces.options.mjs +11 -0
- package/esm2022/utils/default-validators/extra-spaces.validators.mjs +16 -0
- package/esm2022/utils/default-validators/index.mjs +2 -0
- package/esm2022/utils/index.mjs +2 -1
- package/esm2022/widgets/categories/categories.component.mjs +75 -0
- package/esm2022/widgets/categories/components/categories-list/categories-list.component.mjs +16 -0
- package/esm2022/widgets/categories/components/categories-list/index.mjs +2 -0
- package/esm2022/widgets/categories/components/category-form/category-form.component.mjs +79 -0
- package/esm2022/widgets/categories/components/category-form/index.mjs +2 -0
- package/esm2022/widgets/categories/components/category-item/category-item.component.mjs +123 -0
- package/esm2022/widgets/categories/components/category-item/index.mjs +2 -0
- package/esm2022/widgets/categories/components/create-category-item/create-category-item.component.mjs +25 -0
- package/esm2022/widgets/categories/components/create-category-item/index.mjs +2 -0
- package/esm2022/widgets/categories/components/index.mjs +3 -0
- package/esm2022/widgets/categories/index.mjs +3 -0
- package/esm2022/widgets/categories/services/index.mjs +2 -0
- package/esm2022/widgets/categories/services/selected-category.service.mjs +38 -0
- package/esm2022/widgets/general-control-error-hint/general-control-error-hint.component.mjs +21 -0
- package/esm2022/widgets/general-control-error-hint/index.mjs +2 -0
- package/esm2022/widgets/index.mjs +3 -0
- package/esm2022/widgets/utility-info/index.mjs +2 -0
- package/esm2022/widgets/utility-info/utility-info.component.mjs +246 -0
- package/esm2022/widgets/utility-info/utility-info.options.mjs +2 -0
- package/fesm2022/cuby-ui-core-en-D3DnyYmu.mjs +29 -0
- package/fesm2022/cuby-ui-core-en-D3DnyYmu.mjs.map +1 -0
- package/fesm2022/cuby-ui-core.mjs +4069 -67
- package/fesm2022/cuby-ui-core.mjs.map +1 -1
- package/index.d.ts +2 -0
- package/package.json +11 -4
- package/services/loader.options.d.ts +2 -2
- package/services/loader.service.d.ts +7 -7
- package/utils/default-validators/create-default-validators.d.ts +5 -0
- package/utils/default-validators/extra-spaces.options.d.ts +2 -0
- package/utils/default-validators/extra-spaces.validators.d.ts +3 -0
- package/utils/default-validators/index.d.ts +1 -0
- package/utils/index.d.ts +1 -0
- package/widgets/categories/categories.component.d.ts +24 -0
- package/widgets/categories/components/categories-list/categories-list.component.d.ts +7 -0
- package/widgets/categories/components/categories-list/index.d.ts +1 -0
- package/widgets/categories/components/category-form/category-form.component.d.ts +28 -0
- package/widgets/categories/components/category-form/index.d.ts +1 -0
- package/widgets/categories/components/category-item/category-item.component.d.ts +40 -0
- package/widgets/categories/components/category-item/index.d.ts +1 -0
- package/widgets/categories/components/create-category-item/create-category-item.component.d.ts +10 -0
- package/widgets/categories/components/create-category-item/index.d.ts +1 -0
- package/widgets/categories/components/index.d.ts +2 -0
- package/widgets/categories/index.d.ts +2 -0
- package/widgets/categories/services/index.d.ts +1 -0
- package/widgets/categories/services/selected-category.service.d.ts +18 -0
- package/widgets/general-control-error-hint/general-control-error-hint.component.d.ts +9 -0
- package/widgets/general-control-error-hint/index.d.ts +1 -0
- package/widgets/index.d.ts +2 -0
- package/widgets/utility-info/index.d.ts +1 -0
- package/widgets/utility-info/utility-info.component.d.ts +53 -0
- package/widgets/utility-info/utility-info.options.d.ts +9 -0
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Component, ChangeDetectionStrategy, inject, Renderer2, input, model, effect, Directive, InjectionToken, Input, HostBinding, ChangeDetectorRef, ElementRef, ViewChild, EventEmitter, Output, NgModule, Injector, Injectable, SkipSelf, Optional, DestroyRef, NgZone, signal, TemplateRef, ContentChildren, HostListener, Self, INJECTOR, forwardRef, ViewContainerRef, computed } from '@angular/core';
|
|
2
|
+
import { Component, ChangeDetectionStrategy, inject, Renderer2, input, model, effect, Directive, InjectionToken, Input, HostBinding, ChangeDetectorRef, ElementRef, ViewChild, EventEmitter, Output, NgModule, Injector, Injectable, SkipSelf, Optional, DestroyRef, NgZone, signal, TemplateRef, ContentChildren, HostListener, Self, INJECTOR, forwardRef, ViewContainerRef, booleanAttribute, computed, Pipe, APP_INITIALIZER, viewChild, afterRender, output } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
|
-
import { CommonModule, DOCUMENT, NgForOf, NgIf, NgComponentOutlet, NgTemplateOutlet } from '@angular/common';
|
|
4
|
+
import { CommonModule, DOCUMENT, NgForOf, NgIf, NgComponentOutlet, NgTemplateOutlet, NgFor, UpperCasePipe, NgClass } from '@angular/common';
|
|
5
5
|
import * as i1$1 from '@cuby-ui/cdk';
|
|
6
|
-
import { CUI_WINDOW, cuiCreateToken, cuiCreateTokenFromFactory, CuiDestroyService, CuiFilterPipe, CuiLetDirective, CuiPopoverService, cuiProvide, CUI_ANIMATION_FRAME, cuiZonefree, EMPTY_CLIENT_RECT, cuiInjectElement, CUI_LOCAL_STORAGE, CUI_IS_WEBKIT, CuiItemDirective, CuiActiveZone, CuiFocusTrapDirective, cuiGetElementObscures, CUI_IS_MOBILE, CuiHoveredService, cuiPure, cuiPointToClientRect, cuiClamp, cuiPx, cuiIfMap, cuiIsPresent, cuiTypedFromEvent, cuiZonefreeScheduler, cuiZoneOptimized, cuiIsNativeFocused, CuiClickOutsideDirective, CuiTargetDirective, cuiGetClosestFocusable, CuiTime, CuiDimensionsObserverDirective, CuiAutoResizingDirective } from '@cuby-ui/cdk';
|
|
6
|
+
import { CUI_WINDOW, cuiCreateToken, cuiCreateTokenFromFactory, CuiDestroyService, CuiFilterPipe, CuiLetDirective, CuiPopoverService, cuiProvide, CUI_ANIMATION_FRAME, cuiZonefree, EMPTY_CLIENT_RECT, cuiInjectElement, CUI_LOCAL_STORAGE, CUI_IS_WEBKIT, CuiItemDirective, CuiActiveZone, CuiFocusTrapDirective, cuiGetElementObscures, CUI_IS_MOBILE, CuiHoveredService, cuiPure, cuiPointToClientRect, cuiClamp, cuiPx, cuiIfMap, cuiIsPresent, cuiTypedFromEvent, cuiZonefreeScheduler, cuiZoneOptimized, cuiIsNativeFocused, CuiClickOutsideDirective, CuiTargetDirective, cuiGetClosestFocusable, CuiTime, CuiDimensionsObserverDirective, CuiAutoResizingDirective, CuiIdService, CuiElementDirective } from '@cuby-ui/cdk';
|
|
7
7
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
8
8
|
import { cuiIsIcon, CUI_ICONS } from '@cuby-ui/icons';
|
|
9
|
-
import { BehaviorSubject, takeUntil, Observable, merge, distinctUntilChanged, startWith, map, finalize, Subject, switchMap, of, delay, repeat, filter, tap, takeWhile, fromEvent, debounce,
|
|
9
|
+
import { BehaviorSubject, takeUntil, Observable, merge, distinctUntilChanged, startWith, map, finalize, timer, Subject, switchMap, of, delay, repeat, filter, tap, takeWhile, fromEvent, debounce, skip, take, forkJoin, throttleTime, concatMap, toArray, catchError, throwError, pairwise, debounceTime } from 'rxjs';
|
|
10
10
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
11
11
|
import { trigger, transition, query, animateChild, style, animate, stagger } from '@angular/animations';
|
|
12
12
|
import * as i2 from '@taiga-ui/polymorpheus';
|
|
13
13
|
import { PolymorpheusOutlet, PolymorpheusTemplate, PolymorpheusComponent, injectContext } from '@taiga-ui/polymorpheus';
|
|
14
|
-
import { __decorate } from 'tslib';
|
|
14
|
+
import { __decorate, __metadata } from 'tslib';
|
|
15
15
|
import * as i2$1 from '@angular/forms';
|
|
16
|
-
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
|
|
16
|
+
import { Validators, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule, FormControl, NonNullableFormBuilder } from '@angular/forms';
|
|
17
17
|
import { maskitoParseNumber, maskitoNumberOptionsGenerator, maskitoTimeOptionsGenerator } from '@maskito/kit';
|
|
18
18
|
import * as i3 from '@maskito/angular';
|
|
19
19
|
import { MaskitoDirective } from '@maskito/angular';
|
|
20
|
-
import
|
|
20
|
+
import EditorJS from '@editorjs/editorjs';
|
|
21
|
+
import Header from '@editorjs/header';
|
|
22
|
+
import List from '@editorjs/list';
|
|
23
|
+
import { TranslocoDirective, TranslocoService } from '@jsverse/transloco';
|
|
24
|
+
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
|
25
|
+
import { createCustomElement } from '@angular/elements';
|
|
26
|
+
import { CuiFrameApiService, CuiTreeStructNavigatorApiService } from '@cuby-ui/api';
|
|
21
27
|
|
|
22
28
|
class CuiAccordionComponent {
|
|
23
29
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiAccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
@@ -761,16 +767,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
761
767
|
}]
|
|
762
768
|
}], ctorParameters: () => [] });
|
|
763
769
|
|
|
764
|
-
const
|
|
770
|
+
const CuiLoadingState = {
|
|
765
771
|
LOADING: 'loading',
|
|
766
772
|
COMPLETED: 'completed',
|
|
767
773
|
INITIAL: 'initial'
|
|
768
774
|
};
|
|
769
775
|
|
|
770
|
-
class
|
|
776
|
+
class CuiLoaderService {
|
|
771
777
|
constructor() {
|
|
772
778
|
this.RESET_TO_INITIAL_TIME = 1000;
|
|
773
|
-
this.loaderStateSignal = signal(
|
|
779
|
+
this.loaderStateSignal = signal(CuiLoadingState.INITIAL);
|
|
774
780
|
this.requestCount = 0;
|
|
775
781
|
this.loaderState = this.loaderStateSignal.asReadonly();
|
|
776
782
|
AngularOutsideLoaderService.setInstance(this);
|
|
@@ -778,14 +784,14 @@ class LoaderService {
|
|
|
778
784
|
setLoading() {
|
|
779
785
|
this.requestCount++;
|
|
780
786
|
// need to use without queueMicrotask (error)
|
|
781
|
-
queueMicrotask(() => this.loaderStateSignal.set(
|
|
787
|
+
queueMicrotask(() => this.loaderStateSignal.set(CuiLoadingState.LOADING));
|
|
782
788
|
}
|
|
783
789
|
setCompleted() {
|
|
784
790
|
this.requestCount = this.requestCount && this.requestCount - 1;
|
|
785
791
|
if (this.requestCount) {
|
|
786
792
|
return;
|
|
787
793
|
}
|
|
788
|
-
return this.loaderStateSignal.set(
|
|
794
|
+
return this.loaderStateSignal.set(CuiLoadingState.COMPLETED);
|
|
789
795
|
}
|
|
790
796
|
handleCompletedRequest() {
|
|
791
797
|
this.setCompleted();
|
|
@@ -794,18 +800,18 @@ class LoaderService {
|
|
|
794
800
|
if (this.requestCount) {
|
|
795
801
|
return;
|
|
796
802
|
}
|
|
797
|
-
this.loaderStateSignal.set(
|
|
803
|
+
this.loaderStateSignal.set(CuiLoadingState.INITIAL);
|
|
798
804
|
}, this.RESET_TO_INITIAL_TIME);
|
|
799
805
|
}
|
|
800
806
|
reset() {
|
|
801
807
|
this.requestCount = 0;
|
|
802
808
|
this.resetLoadingStateTimerId = undefined;
|
|
803
|
-
this.loaderStateSignal.set(
|
|
809
|
+
this.loaderStateSignal.set(CuiLoadingState.INITIAL);
|
|
804
810
|
}
|
|
805
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
806
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
811
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
812
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiLoaderService, providedIn: 'root' }); }
|
|
807
813
|
}
|
|
808
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type:
|
|
814
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiLoaderService, decorators: [{
|
|
809
815
|
type: Injectable,
|
|
810
816
|
args: [{
|
|
811
817
|
providedIn: 'root'
|
|
@@ -1647,6 +1653,41 @@ function cuiGetDuration(speed) {
|
|
|
1647
1653
|
return speed && CUI_ANIMATIONS_DEFAULT_DURATION / speed;
|
|
1648
1654
|
}
|
|
1649
1655
|
|
|
1656
|
+
const LEADING_TRAILING_SPACES_REGEX = /^\s|\s$/;
|
|
1657
|
+
const MULTIPLE_SPACES_REGEX = /\s{2,}/;
|
|
1658
|
+
function hasExtraSpaces(value) {
|
|
1659
|
+
const hasLeadingOrTrailingSpaces = LEADING_TRAILING_SPACES_REGEX.test(value);
|
|
1660
|
+
const hasMultipleSpaces = MULTIPLE_SPACES_REGEX.test(value);
|
|
1661
|
+
if (hasLeadingOrTrailingSpaces || hasMultipleSpaces) {
|
|
1662
|
+
return { extraSpaces: true };
|
|
1663
|
+
}
|
|
1664
|
+
return null;
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
function asyncExtraSpacesValidators(delay) {
|
|
1668
|
+
return ({ value }) => {
|
|
1669
|
+
return timer(delay).pipe(map(() => hasExtraSpaces(value)));
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
function syncExtraSpacesValidator() {
|
|
1673
|
+
return ({ errors, value }) => {
|
|
1674
|
+
if (!errors?.['extraSpaces']) {
|
|
1675
|
+
return null;
|
|
1676
|
+
}
|
|
1677
|
+
return hasExtraSpaces(value);
|
|
1678
|
+
};
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
function createDefaultValidators({ maxLength = 100, asyncDelay = 700 } = {}) {
|
|
1682
|
+
// Need to offset because this delay must be before changing value
|
|
1683
|
+
const OFFSET = 1;
|
|
1684
|
+
const adjustedAsyncDelay = asyncDelay - OFFSET;
|
|
1685
|
+
return {
|
|
1686
|
+
validators: [Validators.required, Validators.maxLength(maxLength), syncExtraSpacesValidator()],
|
|
1687
|
+
asyncValidators: [asyncExtraSpacesValidators(adjustedAsyncDelay)]
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1650
1691
|
/**
|
|
1651
1692
|
* A component to display a tooltip
|
|
1652
1693
|
*/
|
|
@@ -1864,7 +1905,10 @@ class CuiTooltipPosition extends CuiPositionAccessor {
|
|
|
1864
1905
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: CuiTooltipPosition, isStandalone: true, inputs: { direction: ["cuiTooltipDirection", "direction"] }, outputs: { directionChange: "cuiTooltipDirectionChange" }, usesInheritance: true, ngImport: i0 }); }
|
|
1865
1906
|
}
|
|
1866
1907
|
__decorate([
|
|
1867
|
-
cuiPure
|
|
1908
|
+
cuiPure,
|
|
1909
|
+
__metadata("design:type", Function),
|
|
1910
|
+
__metadata("design:paramtypes", [String]),
|
|
1911
|
+
__metadata("design:returntype", void 0)
|
|
1868
1912
|
], CuiTooltipPosition.prototype, "emitDirection", null);
|
|
1869
1913
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiTooltipPosition, decorators: [{
|
|
1870
1914
|
type: Directive,
|
|
@@ -2089,7 +2133,10 @@ class CuiTooltipComponent {
|
|
|
2089
2133
|
`, isInline: true, styles: [":host{padding:4px 8px;font-weight:400;font-size:14px;line-height:20px;overflow-y:auto;position:absolute;max-inline-size:375px;max-block-size:375px;background:var(--cui-gray-900);border-radius:6px;color:var(--cui-gray-0);box-sizing:border-box;font-family:var(--cui-main-font);white-space:pre-line;overflow-wrap:break-word;transform-origin:var(--left) var(--top)}:host:not([style*=top]){visibility:hidden}:host._untouchable{pointer-events:none}\n"], dependencies: [{ kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }], animations: [cuiFadeIn, cuiScaleIn], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2090
2134
|
}
|
|
2091
2135
|
__decorate([
|
|
2092
|
-
cuiPure
|
|
2136
|
+
cuiPure,
|
|
2137
|
+
__metadata("design:type", Function),
|
|
2138
|
+
__metadata("design:paramtypes", [String, String, Number, Number]),
|
|
2139
|
+
__metadata("design:returntype", void 0)
|
|
2093
2140
|
], CuiTooltipComponent.prototype, "apply", null);
|
|
2094
2141
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiTooltipComponent, decorators: [{
|
|
2095
2142
|
type: Component,
|
|
@@ -2135,7 +2182,9 @@ class CuiTooltipDescribe extends CuiDriver {
|
|
|
2135
2182
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: CuiTooltipDescribe, isStandalone: true, selector: "[cuiTooltipDescribe]", inputs: { cuiTooltipDescribe: "cuiTooltipDescribe" }, providers: [cuiAsDriver(CuiTooltipDescribe)], usesInheritance: true, ngImport: i0 }); }
|
|
2136
2183
|
}
|
|
2137
2184
|
__decorate([
|
|
2138
|
-
cuiPure
|
|
2185
|
+
cuiPure,
|
|
2186
|
+
__metadata("design:type", HTMLElement),
|
|
2187
|
+
__metadata("design:paramtypes", [])
|
|
2139
2188
|
], CuiTooltipDescribe.prototype, "element", null);
|
|
2140
2189
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiTooltipDescribe, decorators: [{
|
|
2141
2190
|
type: Directive,
|
|
@@ -3008,6 +3057,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
3008
3057
|
}]
|
|
3009
3058
|
}] });
|
|
3010
3059
|
|
|
3060
|
+
class CuiContentWrapperComponent {
|
|
3061
|
+
constructor() {
|
|
3062
|
+
this.DEFAULT_BACKGROUND_COLOR = 'var(--cui-base-0)';
|
|
3063
|
+
this.DEFAULT_GAP = 8;
|
|
3064
|
+
this.backgroundColor = input(this.DEFAULT_BACKGROUND_COLOR);
|
|
3065
|
+
this.gap = input(this.DEFAULT_GAP);
|
|
3066
|
+
}
|
|
3067
|
+
get _backgroundColor() {
|
|
3068
|
+
return this.backgroundColor();
|
|
3069
|
+
}
|
|
3070
|
+
get _gap() {
|
|
3071
|
+
return this.gap();
|
|
3072
|
+
}
|
|
3073
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiContentWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3074
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: CuiContentWrapperComponent, isStandalone: true, selector: "cui-content-wrapper, [cuiContentWrapper]", inputs: { backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.background": "this._backgroundColor", "style.gap.px": "this._gap" } }, ngImport: i0, template: "<ng-content />\r\n", styles: [":host{padding:16px;display:flex;flex-direction:column;gap:16px;border-radius:8px}:host:empty{display:contents}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3075
|
+
}
|
|
3076
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiContentWrapperComponent, decorators: [{
|
|
3077
|
+
type: Component,
|
|
3078
|
+
args: [{ selector: 'cui-content-wrapper, [cuiContentWrapper]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content />\r\n", styles: [":host{padding:16px;display:flex;flex-direction:column;gap:16px;border-radius:8px}:host:empty{display:contents}\n"] }]
|
|
3079
|
+
}], propDecorators: { _backgroundColor: [{
|
|
3080
|
+
type: HostBinding,
|
|
3081
|
+
args: ['style.background']
|
|
3082
|
+
}], _gap: [{
|
|
3083
|
+
type: HostBinding,
|
|
3084
|
+
args: ['style.gap.px']
|
|
3085
|
+
}] } });
|
|
3086
|
+
|
|
3087
|
+
class CuiGhostInputComponent {
|
|
3088
|
+
constructor() {
|
|
3089
|
+
this.isError = input(false, { transform: booleanAttribute });
|
|
3090
|
+
}
|
|
3091
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiGhostInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3092
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: CuiGhostInputComponent, isStandalone: true, selector: "input [cuiGhostInput]", inputs: { isError: { classPropertyName: "isError", publicName: "isError", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class._with-error": "isError()" } }, ngImport: i0, template: '', isInline: true, styles: [":host{padding-right:3px;padding-left:3px;width:100%;border:1px solid transparent;border-radius:8px;outline:none;background:none}:host:focus-visible{box-shadow:0 0 0 2px var(--cui-focus);border-color:var(--cui-info)}:host:disabled{opacity:.5}:host::placeholder{color:var(--cui-base-400)}:host._with-error{border-color:var(--cui-danger)}:host._with-error:focus-visible{box-shadow:0 0 0 2px #d92d2040}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3093
|
+
}
|
|
3094
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiGhostInputComponent, decorators: [{
|
|
3095
|
+
type: Component,
|
|
3096
|
+
args: [{ selector: 'input [cuiGhostInput]', standalone: true, template: '', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
3097
|
+
'[class._with-error]': 'isError()'
|
|
3098
|
+
}, styles: [":host{padding-right:3px;padding-left:3px;width:100%;border:1px solid transparent;border-radius:8px;outline:none;background:none}:host:focus-visible{box-shadow:0 0 0 2px var(--cui-focus);border-color:var(--cui-info)}:host:disabled{opacity:.5}:host::placeholder{color:var(--cui-base-400)}:host._with-error{border-color:var(--cui-danger)}:host._with-error:focus-visible{box-shadow:0 0 0 2px #d92d2040}\n"] }]
|
|
3099
|
+
}] });
|
|
3100
|
+
|
|
3011
3101
|
class CuiInputPasswordComponent {
|
|
3012
3102
|
constructor() {
|
|
3013
3103
|
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
@@ -3620,6 +3710,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
3620
3710
|
}]
|
|
3621
3711
|
}] });
|
|
3622
3712
|
|
|
3713
|
+
class CuiEmptyStateComponent {
|
|
3714
|
+
constructor() {
|
|
3715
|
+
this.title = input();
|
|
3716
|
+
this.subtitle = input();
|
|
3717
|
+
}
|
|
3718
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3719
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CuiEmptyStateComponent, isStandalone: true, selector: "cui-empty-state, [cuiEmptyState]", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class._with-title": "!!this.title()" } }, ngImport: i0, template: "@if (title(); as title) {\r\n <p class=\"title\">{{ title }}</p>\r\n}\r\n@if (subtitle(); as subtitle) {\r\n <p class=\"subtitle\">{{ subtitle }}</p>\r\n}\r\n<ng-content />\r\n", styles: [":host{--padding-vertical: 24px;--padding-horizontal: 0;display:flex;flex-direction:column;gap:16px;align-items:center;justify-content:center;padding:16px;margin:auto;height:100%;text-align:center}:host._with-title{padding:var(--padding-vertical) var(--padding-horizontal)}.title,.subtitle{margin:0}.title{font-weight:500;font-size:16px;line-height:24px}.subtitle{font-weight:400;font-size:14px;line-height:20px;color:var(--cui-base-500)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3720
|
+
}
|
|
3721
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEmptyStateComponent, decorators: [{
|
|
3722
|
+
type: Component,
|
|
3723
|
+
args: [{ selector: 'cui-empty-state, [cuiEmptyState]', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
3724
|
+
'[class._with-title]': '!!this.title()'
|
|
3725
|
+
}, template: "@if (title(); as title) {\r\n <p class=\"title\">{{ title }}</p>\r\n}\r\n@if (subtitle(); as subtitle) {\r\n <p class=\"subtitle\">{{ subtitle }}</p>\r\n}\r\n<ng-content />\r\n", styles: [":host{--padding-vertical: 24px;--padding-horizontal: 0;display:flex;flex-direction:column;gap:16px;align-items:center;justify-content:center;padding:16px;margin:auto;height:100%;text-align:center}:host._with-title{padding:var(--padding-vertical) var(--padding-horizontal)}.title,.subtitle{margin:0}.title{font-weight:500;font-size:16px;line-height:24px}.subtitle{font-weight:400;font-size:14px;line-height:20px;color:var(--cui-base-500)}\n"] }]
|
|
3726
|
+
}] });
|
|
3727
|
+
|
|
3623
3728
|
const IS_SIDEBAR_OPENED_STORAGE_KEY = 'is-sidebar-opened';
|
|
3624
3729
|
|
|
3625
3730
|
class CuiRenderDynamicComponentsService {
|
|
@@ -3948,64 +4053,3961 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
3948
4053
|
}]
|
|
3949
4054
|
}] });
|
|
3950
4055
|
|
|
3951
|
-
const
|
|
3952
|
-
|
|
3953
|
-
|
|
4056
|
+
const COMBINED_TEXT_BLOCK_PART = 'combined-text-block-part';
|
|
4057
|
+
const COMBINED_TEXT_BLOCK = 'combined-text-block';
|
|
4058
|
+
const COMBINED_TEXT_BLOCK_NAME = 'paragraph';
|
|
4059
|
+
const COMBINED_TEXT_BLOCK_ADDED = 'combinedTextBlockAdded';
|
|
4060
|
+
const COMBINED_TEXT_BLOCK_UPDATED = 'combinedTextBlockUpdated';
|
|
4061
|
+
const COMBINED_TEXT_BLOCK_REMOVED = 'combinedTextBlockRemoved';
|
|
4062
|
+
const SPLIT_MAX_LENGTH = 1000;
|
|
4063
|
+
const SPLIT_LENGTH = 500;
|
|
4064
|
+
const EDITOR_SELECTOR = '[data-editor]';
|
|
4065
|
+
const DEFAULT_PLACEHOLDER = "Type text or '/' for commands...";
|
|
4066
|
+
const DEFAULT_READONLY_PLACEHOLDER = "No 'Description' was provided";
|
|
4067
|
+
const DEFAULT_CONFIG = {
|
|
4068
|
+
tools: {},
|
|
4069
|
+
readOnly: false,
|
|
4070
|
+
autofocus: false
|
|
4071
|
+
};
|
|
4072
|
+
const CuiEditorTranslations = {
|
|
4073
|
+
en: import('./cuby-ui-core-en-D3DnyYmu.mjs'),
|
|
4074
|
+
};
|
|
4075
|
+
|
|
4076
|
+
class CuiHeaderTool extends Header {
|
|
4077
|
+
constructor(data) {
|
|
4078
|
+
super(data);
|
|
3954
4079
|
}
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
4080
|
+
validate() {
|
|
4081
|
+
return true;
|
|
4082
|
+
}
|
|
4083
|
+
render() {
|
|
4084
|
+
return super.render();
|
|
4085
|
+
}
|
|
4086
|
+
save(block) {
|
|
4087
|
+
return super.save(block);
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
|
|
4091
|
+
class CuiListTool extends List {
|
|
4092
|
+
constructor(data) {
|
|
4093
|
+
super(data);
|
|
4094
|
+
}
|
|
4095
|
+
render() {
|
|
4096
|
+
return super.render();
|
|
4097
|
+
}
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4100
|
+
class CuiSelectionBase {
|
|
4101
|
+
static get isInline() {
|
|
4102
|
+
return true;
|
|
4103
|
+
}
|
|
4104
|
+
get state() {
|
|
4105
|
+
return this._state;
|
|
4106
|
+
}
|
|
4107
|
+
set state(state) {
|
|
4108
|
+
this._state = state;
|
|
4109
|
+
this.button?.classList.toggle(this.api.styles.inlineToolButtonActive, state);
|
|
4110
|
+
}
|
|
4111
|
+
constructor(data) {
|
|
4112
|
+
this.LIST_CLASS = 'cdx-list__item';
|
|
4113
|
+
this.SELECTED_TEXT_CLASS = '_selected';
|
|
4114
|
+
this.TAG = 'B';
|
|
4115
|
+
this.COMMAND = 'bold';
|
|
4116
|
+
this._state = false;
|
|
4117
|
+
this.api = data.api;
|
|
4118
|
+
}
|
|
4119
|
+
wrap(range) {
|
|
4120
|
+
const { startContainer, endContainer } = range;
|
|
4121
|
+
this.addSelectionToDOM(range, startContainer, endContainer);
|
|
4122
|
+
}
|
|
4123
|
+
unwrap() {
|
|
4124
|
+
document.execCommand(this.COMMAND);
|
|
4125
|
+
}
|
|
4126
|
+
checkState() {
|
|
4127
|
+
this.state = document.queryCommandState(this.COMMAND);
|
|
4128
|
+
return this.state;
|
|
4129
|
+
}
|
|
4130
|
+
surround(range) {
|
|
4131
|
+
if (this.state) {
|
|
4132
|
+
this.unwrap();
|
|
4133
|
+
return;
|
|
4134
|
+
}
|
|
4135
|
+
this.wrap(range);
|
|
4136
|
+
}
|
|
4137
|
+
createElement(text = '') {
|
|
4138
|
+
const element = document.createElement(this.TAG);
|
|
4139
|
+
element.textContent = text;
|
|
4140
|
+
return element;
|
|
4141
|
+
}
|
|
4142
|
+
addSelectionToDOM(range, startBlock, endBlock) {
|
|
4143
|
+
const classes = [this.LIST_CLASS, COMBINED_TEXT_BLOCK_PART];
|
|
4144
|
+
const { className, parent: startParent } = this.getClosestParentWithClass(startBlock, classes);
|
|
4145
|
+
const { parent: endParent } = this.getClosestParentWithClass(endBlock, classes);
|
|
4146
|
+
if (!className || startParent === endParent) {
|
|
4147
|
+
this.addSelectionForOnlyChild(range);
|
|
4148
|
+
return;
|
|
4149
|
+
}
|
|
4150
|
+
this.addSelectionForChildren(startParent, endParent);
|
|
4151
|
+
}
|
|
4152
|
+
addSelectionForOnlyChild(range) {
|
|
4153
|
+
const selectedText = range.extractContents();
|
|
4154
|
+
const selection = this.createElement();
|
|
4155
|
+
selection.appendChild(selectedText);
|
|
4156
|
+
range.insertNode(selection);
|
|
4157
|
+
}
|
|
4158
|
+
addSelectionForChildren(startParent, endParent) {
|
|
4159
|
+
const nodes = this.getSelectedNodesFromDOM(startParent, endParent);
|
|
4160
|
+
nodes.forEach((node) => node.classList.add(this.SELECTED_TEXT_CLASS));
|
|
4161
|
+
document.execCommand(this.COMMAND);
|
|
4162
|
+
nodes.forEach((node) => node.classList.remove(this.SELECTED_TEXT_CLASS));
|
|
4163
|
+
}
|
|
4164
|
+
getSelectedNodesFromDOM(startParent, endParent) {
|
|
4165
|
+
const nodes = [startParent];
|
|
4166
|
+
let next = startParent.nextSibling;
|
|
4167
|
+
while (next && next !== endParent) {
|
|
4168
|
+
nodes.push(next);
|
|
4169
|
+
next = next?.nextSibling || null;
|
|
4170
|
+
}
|
|
4171
|
+
nodes.push(endParent);
|
|
4172
|
+
return nodes;
|
|
4173
|
+
}
|
|
4174
|
+
getClosestParentWithClass(node, classes) {
|
|
4175
|
+
const nodeParent = node.parentElement;
|
|
4176
|
+
let parent = nodeParent;
|
|
4177
|
+
let resultClassName = '';
|
|
4178
|
+
for (const className of classes) {
|
|
4179
|
+
const parentWithClass = parent.closest('.' + className);
|
|
4180
|
+
if (!parentWithClass) {
|
|
4181
|
+
continue;
|
|
4182
|
+
}
|
|
4183
|
+
parent = parentWithClass;
|
|
4184
|
+
resultClassName = className;
|
|
4185
|
+
break;
|
|
4186
|
+
}
|
|
4187
|
+
return { className: resultClassName, parent };
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
|
|
4191
|
+
class CuiBoldInlineTool extends CuiSelectionBase {
|
|
4192
|
+
static { this.title = 'Bold'; }
|
|
4193
|
+
static get sanitize() {
|
|
4194
|
+
return {
|
|
4195
|
+
b: {}
|
|
4196
|
+
};
|
|
4197
|
+
}
|
|
4198
|
+
constructor(data) {
|
|
4199
|
+
super(data);
|
|
4200
|
+
this.COMMAND = 'bold';
|
|
4201
|
+
this.CSS = {
|
|
4202
|
+
button: 'ce-inline-tool',
|
|
4203
|
+
buttonActive: 'ce-inline-tool--active',
|
|
4204
|
+
buttonModifier: 'ce-inline-tool--bold'
|
|
4205
|
+
};
|
|
4206
|
+
}
|
|
4207
|
+
render() {
|
|
4208
|
+
this.button = document.createElement('button');
|
|
4209
|
+
this.button.type = 'button';
|
|
4210
|
+
this.button.classList.add(this.CSS.button, this.CSS.buttonModifier);
|
|
4211
|
+
/* eslint-disable */
|
|
4212
|
+
this.button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
4213
|
+
<path d="M7.5 10.0002V5.91683C7.5 5.8708 7.53731 5.8335 7.58333 5.8335H8.66667C9.58333 5.8335 11.6667 5.91683 11.6667 7.91683C11.6667 7.91683 11.6667 10.0002 9.16667 10.0002M7.5 10.0002V14.0002C7.5 14.0922 7.57462 14.1668 7.66667 14.1668H10.4167C11.6667 14.1668 12.5 13.3335 12.5 12.0835C12.5 9.754 9.16667 10.0002 9.16667 10.0002M7.5 10.0002H9.16667" stroke="#121315" stroke-width="1.66667" stroke-linecap="round"/>
|
|
4214
|
+
</svg>`;
|
|
4215
|
+
/* eslint-enable */
|
|
4216
|
+
return this.button;
|
|
4217
|
+
}
|
|
4218
|
+
get shortcut() {
|
|
4219
|
+
return 'CMD+B';
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
|
|
4223
|
+
class CuiItalicInlineTool extends CuiSelectionBase {
|
|
4224
|
+
static { this.title = 'Italic'; }
|
|
4225
|
+
static get sanitize() {
|
|
4226
|
+
return {
|
|
4227
|
+
i: {}
|
|
4228
|
+
};
|
|
4229
|
+
}
|
|
4230
|
+
constructor(data) {
|
|
4231
|
+
super(data);
|
|
4232
|
+
this.COMMAND = 'italic';
|
|
4233
|
+
this.TAG = 'I';
|
|
4234
|
+
this.CSS = {
|
|
4235
|
+
button: 'ce-inline-tool',
|
|
4236
|
+
buttonActive: 'ce-inline-tool--active',
|
|
4237
|
+
buttonModifier: 'ce-inline-tool--italic'
|
|
4238
|
+
};
|
|
4239
|
+
}
|
|
4240
|
+
render() {
|
|
4241
|
+
this.button = document.createElement('button');
|
|
4242
|
+
this.button.type = 'button';
|
|
4243
|
+
this.button.classList.add(this.CSS.button, this.CSS.buttonModifier);
|
|
4244
|
+
/* eslint-disable */
|
|
4245
|
+
this.button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
4246
|
+
<path d="M11.118 8.3335C10.3532 10.6116 9.16797 14.1668 9.16797 14.1668" stroke="#121315" stroke-width="1.66667" stroke-linecap="round"/>
|
|
4247
|
+
<path d="M11.8404 5.8335H11.832" stroke="#121315" stroke-width="1.66667" stroke-linecap="round"/>
|
|
4248
|
+
</svg>`;
|
|
4249
|
+
/* eslint-enable */
|
|
4250
|
+
return this.button;
|
|
4251
|
+
}
|
|
4252
|
+
get shortcut() {
|
|
4253
|
+
return 'CMD+I';
|
|
4254
|
+
}
|
|
4255
|
+
}
|
|
4256
|
+
|
|
4257
|
+
function urlValidator() {
|
|
4258
|
+
return ({ value }) => {
|
|
4259
|
+
try {
|
|
4260
|
+
new URL(value);
|
|
4261
|
+
return null;
|
|
4262
|
+
}
|
|
4263
|
+
catch {
|
|
4264
|
+
return { url: true };
|
|
4265
|
+
}
|
|
4266
|
+
};
|
|
4267
|
+
}
|
|
4268
|
+
|
|
4269
|
+
const BlockConversionToCombined = {
|
|
4270
|
+
paragraph: 'combinedTextBlock'
|
|
4271
|
+
};
|
|
4272
|
+
|
|
4273
|
+
function generateId() {
|
|
4274
|
+
return '_' + Math.random().toString(36).substring(2, 9);
|
|
4275
|
+
}
|
|
4276
|
+
|
|
4277
|
+
class CuiJTextApiService {
|
|
4278
|
+
constructor() {
|
|
4279
|
+
this.httpClient = inject(HttpClient);
|
|
4280
|
+
this.GET_BLOCK_DEFAULT_SIZE = 40;
|
|
4281
|
+
this.JTEXT_URL = 'framer/jtext';
|
|
4282
|
+
this.BLOCK_URL = 'block';
|
|
4283
|
+
this.BLOCKS_URL = 'blocks';
|
|
4284
|
+
this.JTEXT_BLOCK_URL = this.JTEXT_URL + '/' + this.BLOCK_URL;
|
|
4285
|
+
this.JTEXT_BLOCKS_URL = this.JTEXT_URL + '/' + this.BLOCKS_URL;
|
|
4286
|
+
this.options = {};
|
|
4287
|
+
}
|
|
4288
|
+
addOptions(options) {
|
|
4289
|
+
this.options = options ?? {};
|
|
4290
|
+
}
|
|
4291
|
+
createBlock(body) {
|
|
4292
|
+
return this.httpClient.post(this.JTEXT_BLOCK_URL, body, this.options);
|
|
4293
|
+
}
|
|
4294
|
+
updateBlock(body) {
|
|
4295
|
+
return this.httpClient.patch(this.JTEXT_BLOCK_URL, body, this.options);
|
|
4296
|
+
}
|
|
4297
|
+
getBlocks(fragmentId, page = 0, sizeBlock = this.GET_BLOCK_DEFAULT_SIZE) {
|
|
4298
|
+
return this.httpClient.get(`${this.JTEXT_URL}/${fragmentId}`, {
|
|
4299
|
+
params: { page, sizeBlock },
|
|
4300
|
+
headers: { 'Content-Type': 'application/x-ndjson' },
|
|
4301
|
+
observe: 'events',
|
|
4302
|
+
...this.options
|
|
4303
|
+
});
|
|
4304
|
+
}
|
|
4305
|
+
createBlocks(body) {
|
|
4306
|
+
return this.httpClient.post(this.JTEXT_BLOCKS_URL, body, this.options);
|
|
4307
|
+
}
|
|
4308
|
+
deleteBlock(containerId, blockId) {
|
|
4309
|
+
return this.httpClient.delete(`${this.JTEXT_URL}/${containerId}/${this.BLOCK_URL}/${blockId}`, this.options);
|
|
4310
|
+
}
|
|
4311
|
+
deleteBlocks(containerId, blocksIds) {
|
|
4312
|
+
return this.httpClient.delete(`${this.JTEXT_URL}/${containerId}/${this.BLOCKS_URL}`, {
|
|
4313
|
+
params: { blocksIds },
|
|
4314
|
+
...this.options
|
|
4315
|
+
});
|
|
4316
|
+
}
|
|
4317
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiJTextApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4318
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiJTextApiService }); }
|
|
4319
|
+
}
|
|
4320
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiJTextApiService, decorators: [{
|
|
4321
|
+
type: Injectable
|
|
4322
|
+
}] });
|
|
4323
|
+
|
|
4324
|
+
class CuiEditorService {
|
|
4325
|
+
constructor() {
|
|
4326
|
+
this.destroyRef = inject(DestroyRef);
|
|
4327
|
+
this.jtextService = inject(CuiJTextApiService);
|
|
4328
|
+
}
|
|
4329
|
+
sortEventsByTypes(events) {
|
|
4330
|
+
const blocks = {
|
|
4331
|
+
'block-removed': [],
|
|
4332
|
+
'block-added': [],
|
|
4333
|
+
'block-changed': []
|
|
4334
|
+
};
|
|
4335
|
+
events.forEach((editorEvent) => {
|
|
4336
|
+
if (editorEvent.detail.target.name === COMBINED_TEXT_BLOCK_NAME) {
|
|
4337
|
+
return;
|
|
4338
|
+
}
|
|
4339
|
+
const eventType = editorEvent.type;
|
|
4340
|
+
if (eventType === "block-changed" /* EventActions.update */) {
|
|
4341
|
+
const changedBlock = blocks["block-added" /* EventActions.add */].find((block) => block.detail.target.id === editorEvent.detail.target.id);
|
|
4342
|
+
if (changedBlock) {
|
|
3972
4343
|
return;
|
|
3973
4344
|
}
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
observer.complete();
|
|
3981
|
-
return;
|
|
3982
|
-
}
|
|
3983
|
-
buffer += decoder.decode(value);
|
|
3984
|
-
const lines = buffer.split('\n');
|
|
3985
|
-
buffer = lines.pop() ?? '';
|
|
3986
|
-
lines.forEach((line) => observer.next(JSON.parse(line)));
|
|
4345
|
+
}
|
|
4346
|
+
if (eventType === "block-removed" /* EventActions.remove */) {
|
|
4347
|
+
const len = blocks["block-added" /* EventActions.add */].length;
|
|
4348
|
+
blocks["block-added" /* EventActions.add */] = blocks["block-added" /* EventActions.add */].filter((block) => block.detail.target.id !== editorEvent.detail.target.id);
|
|
4349
|
+
if (len > blocks["block-added" /* EventActions.add */].length) {
|
|
4350
|
+
return;
|
|
3987
4351
|
}
|
|
3988
4352
|
}
|
|
3989
|
-
|
|
3990
|
-
|
|
4353
|
+
blocks[eventType].push(editorEvent);
|
|
4354
|
+
});
|
|
4355
|
+
return blocks;
|
|
4356
|
+
}
|
|
4357
|
+
collectAddedBlocksRequest(editorId, addedBlocks) {
|
|
4358
|
+
const addBlocksBody = {
|
|
4359
|
+
jtextContainerId: editorId,
|
|
4360
|
+
position: addedBlocks[0]?.index,
|
|
4361
|
+
block: addedBlocks.map((e) => e.block)
|
|
4362
|
+
};
|
|
4363
|
+
const addBlocks$ = addedBlocks.length ? this.jtextService.createBlocks(addBlocksBody) : of([]);
|
|
4364
|
+
return addBlocks$;
|
|
4365
|
+
}
|
|
4366
|
+
collectUpdatedBlocksRequest(updatedBlocks, blockIdsMap) {
|
|
4367
|
+
const updatedBlocksWithId = updatedBlocks.reduce((acc, block) => {
|
|
4368
|
+
const blockWithId = {
|
|
4369
|
+
...block,
|
|
4370
|
+
id: blockIdsMap.get(block.id)
|
|
4371
|
+
};
|
|
4372
|
+
if (blockWithId.id) {
|
|
4373
|
+
acc.push(blockWithId);
|
|
3991
4374
|
}
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
4375
|
+
return acc;
|
|
4376
|
+
}, []);
|
|
4377
|
+
const updateBlocksArray = updatedBlocksWithId.map((block) => this.jtextService.updateBlock(block));
|
|
4378
|
+
const updateBlocks$ = updatedBlocksWithId.length ? forkJoin(updateBlocksArray) : of([]);
|
|
4379
|
+
return updateBlocks$;
|
|
4380
|
+
}
|
|
4381
|
+
collectRemovedBlocksRequest(editorId, removedBlocksIds, blockIdsMap) {
|
|
4382
|
+
const removedBlocks = removedBlocksIds.reduce((blockIds, blockId) => {
|
|
4383
|
+
const backendID = blockIdsMap.get(blockId);
|
|
4384
|
+
if (backendID) {
|
|
4385
|
+
blockIds.push(backendID);
|
|
4386
|
+
}
|
|
4387
|
+
return blockIds;
|
|
4388
|
+
}, []);
|
|
4389
|
+
const removeBlocks$ = removedBlocks.length ? this.jtextService.deleteBlocks(editorId, removedBlocks) : of();
|
|
4390
|
+
removedBlocks.forEach((removedBlock) => {
|
|
4391
|
+
blockIdsMap.delete(removedBlock);
|
|
4392
|
+
});
|
|
4393
|
+
return removeBlocks$;
|
|
4394
|
+
}
|
|
4395
|
+
getFullBlockData(event, editorData) {
|
|
4396
|
+
const target = event.detail.target;
|
|
4397
|
+
const index = Number(target.holder.dataset['index']);
|
|
4398
|
+
const blockIndex = event.detail.index;
|
|
4399
|
+
const blockType = target.name;
|
|
4400
|
+
const blockId = target.id;
|
|
4401
|
+
const currentBlockByIndex = editorData.blocks[blockIndex];
|
|
4402
|
+
const blockData = currentBlockByIndex?.id === blockId ? editorData.blocks[blockIndex].data : { text: '' };
|
|
4403
|
+
return {
|
|
4404
|
+
index,
|
|
4405
|
+
id: blockId,
|
|
4406
|
+
block: {
|
|
4407
|
+
type: blockType,
|
|
4408
|
+
data: blockData
|
|
4409
|
+
}
|
|
4410
|
+
};
|
|
4411
|
+
}
|
|
4412
|
+
setListenersOnCustomBlockChanges(editor, data) {
|
|
4413
|
+
editor.on(COMBINED_TEXT_BLOCK_ADDED, data.addedCallback);
|
|
4414
|
+
editor.on(COMBINED_TEXT_BLOCK_UPDATED, data.updatedCallback);
|
|
4415
|
+
editor.on(COMBINED_TEXT_BLOCK_REMOVED, data.removedCallback);
|
|
4416
|
+
}
|
|
4417
|
+
setStartBlock(editorId, callback) {
|
|
4418
|
+
const blockId = generateId();
|
|
4419
|
+
const emptyBlock = {
|
|
4420
|
+
type: COMBINED_TEXT_BLOCK_PART,
|
|
4421
|
+
data: {
|
|
4422
|
+
text: '',
|
|
4423
|
+
parentId: blockId,
|
|
4424
|
+
parentType: COMBINED_TEXT_BLOCK_NAME
|
|
4425
|
+
}
|
|
4426
|
+
};
|
|
4427
|
+
const body = {
|
|
4428
|
+
position: 0,
|
|
4429
|
+
block: emptyBlock,
|
|
4430
|
+
jtextContainerId: editorId
|
|
4431
|
+
};
|
|
4432
|
+
this.jtextService
|
|
4433
|
+
.createBlock(body)
|
|
4434
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
4435
|
+
.subscribe((id) => {
|
|
4436
|
+
emptyBlock.id = id;
|
|
4437
|
+
const block = {
|
|
4438
|
+
id: blockId,
|
|
4439
|
+
type: COMBINED_TEXT_BLOCK_NAME,
|
|
4440
|
+
data: {
|
|
4441
|
+
id: blockId,
|
|
4442
|
+
textBlocks: [emptyBlock]
|
|
4443
|
+
}
|
|
4444
|
+
};
|
|
4445
|
+
callback(block, id);
|
|
4446
|
+
});
|
|
4447
|
+
}
|
|
4448
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4449
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorService }); }
|
|
4450
|
+
}
|
|
4451
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorService, decorators: [{
|
|
4452
|
+
type: Injectable
|
|
4453
|
+
}] });
|
|
3996
4454
|
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4455
|
+
class CuiMarkersService {
|
|
4456
|
+
constructor() {
|
|
4457
|
+
this.roles = [];
|
|
4458
|
+
this.tools = [
|
|
4459
|
+
{
|
|
4460
|
+
id: '0',
|
|
4461
|
+
image: 'blob:https://www.figma.com/f985f4fc-abc6-4727-857e-80633836e2b2',
|
|
4462
|
+
title: 'Шуруповерт',
|
|
4463
|
+
type: "tool" /* MarkerType.tool */
|
|
4464
|
+
},
|
|
4465
|
+
{
|
|
4466
|
+
id: '1',
|
|
4467
|
+
image: 'blob:https://www.figma.com/92ad9b38-566c-4ff6-84ba-0b20b24fef39',
|
|
4468
|
+
title: 'Молоток',
|
|
4469
|
+
type: "tool" /* MarkerType.tool */
|
|
4470
|
+
},
|
|
4471
|
+
{
|
|
4472
|
+
id: '2',
|
|
4473
|
+
image: '/assets/image 545.png',
|
|
4474
|
+
title: 'Лопата',
|
|
4475
|
+
type: "tool" /* MarkerType.tool */
|
|
4476
|
+
},
|
|
4477
|
+
{
|
|
4478
|
+
id: '3',
|
|
4479
|
+
image: '/assets/image 545.png',
|
|
4480
|
+
title: 'Лопата',
|
|
4481
|
+
type: "tool" /* MarkerType.tool */
|
|
4482
|
+
},
|
|
4483
|
+
{
|
|
4484
|
+
id: '4',
|
|
4485
|
+
image: '/assets/image 545.png',
|
|
4486
|
+
title: 'Лопата',
|
|
4487
|
+
type: "tool" /* MarkerType.tool */
|
|
4488
|
+
},
|
|
4489
|
+
{
|
|
4490
|
+
id: '5',
|
|
4491
|
+
image: '/assets/image 545.png',
|
|
4492
|
+
title: 'Лопата',
|
|
4493
|
+
type: "tool" /* MarkerType.tool */
|
|
4494
|
+
},
|
|
4495
|
+
{
|
|
4496
|
+
id: '6',
|
|
4497
|
+
image: '/assets/image 545.png',
|
|
4498
|
+
title: 'Лопата',
|
|
4499
|
+
type: "tool" /* MarkerType.tool */
|
|
4500
|
+
},
|
|
4501
|
+
{
|
|
4502
|
+
id: '7',
|
|
4503
|
+
image: '/assets/image 545.png',
|
|
4504
|
+
title: 'Лопата',
|
|
4505
|
+
type: "tool" /* MarkerType.tool */
|
|
4506
|
+
},
|
|
4507
|
+
{
|
|
4508
|
+
id: '8',
|
|
4509
|
+
image: '/assets/image 545.png',
|
|
4510
|
+
title: 'Лопата',
|
|
4511
|
+
type: "tool" /* MarkerType.tool */
|
|
4512
|
+
}
|
|
4513
|
+
];
|
|
4001
4514
|
}
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
}
|
|
4515
|
+
getMarkersByType(type) {
|
|
4516
|
+
return type === "role" /* MarkerType.role */ ? this.roles : this.tools;
|
|
4517
|
+
}
|
|
4518
|
+
getMarkerObjectByType(type, id) {
|
|
4519
|
+
const markersArray = this.getMarkersByType(type);
|
|
4520
|
+
return markersArray.find((marker) => marker.id === id);
|
|
4521
|
+
}
|
|
4522
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiMarkersService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4523
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiMarkersService, providedIn: 'root' }); }
|
|
4524
|
+
}
|
|
4525
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiMarkersService, decorators: [{
|
|
4526
|
+
type: Injectable,
|
|
4527
|
+
args: [{
|
|
4528
|
+
providedIn: 'root'
|
|
4529
|
+
}]
|
|
4530
|
+
}] });
|
|
4531
|
+
|
|
4532
|
+
class SelectOptionComponent {
|
|
4533
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectOptionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4534
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SelectOptionComponent, isStandalone: true, selector: "cc-select-option", inputs: { tool: "tool" }, ngImport: i0, template: "<ng-container *ngIf=\"tool\">\r\n <img\r\n *ngIf=\"tool.image\"\r\n class=\"image\"\r\n [src]=\"tool.image\"\r\n alt=\"\"\r\n />\r\n <h3 class=\"title\">{{ tool.title }}</h3>\r\n</ng-container>\r\n", styles: [":host{padding:4px 8px;cursor:pointer;display:flex;align-items:center;gap:8px;border-radius:8px}@media (hover: hover){:host:hover{background-color:var(--cui-base-50)}}:host:active{background-color:var(--cui-base-50)}.title{font-weight:400;font-size:14px;line-height:20px;padding-top:2px;padding-bottom:2px;color:var(--cui-base-900)}.image{width:23px;height:23px;object-fit:cover;object-position:center}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4535
|
+
}
|
|
4536
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SelectOptionComponent, decorators: [{
|
|
4537
|
+
type: Component,
|
|
4538
|
+
args: [{ selector: 'cc-select-option', standalone: true, imports: [NgIf], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"tool\">\r\n <img\r\n *ngIf=\"tool.image\"\r\n class=\"image\"\r\n [src]=\"tool.image\"\r\n alt=\"\"\r\n />\r\n <h3 class=\"title\">{{ tool.title }}</h3>\r\n</ng-container>\r\n", styles: [":host{padding:4px 8px;cursor:pointer;display:flex;align-items:center;gap:8px;border-radius:8px}@media (hover: hover){:host:hover{background-color:var(--cui-base-50)}}:host:active{background-color:var(--cui-base-50)}.title{font-weight:400;font-size:14px;line-height:20px;padding-top:2px;padding-bottom:2px;color:var(--cui-base-900)}.image{width:23px;height:23px;object-fit:cover;object-position:center}\n"] }]
|
|
4539
|
+
}], propDecorators: { tool: [{
|
|
4540
|
+
type: Input,
|
|
4541
|
+
args: [{ required: true }]
|
|
4542
|
+
}] } });
|
|
4543
|
+
|
|
4544
|
+
class MarkerSelectComponent {
|
|
4545
|
+
constructor() {
|
|
4546
|
+
this.document = inject(DOCUMENT);
|
|
4547
|
+
this.destroyRef = inject(DestroyRef);
|
|
4548
|
+
this.cuiClickOutsideDirective = inject(CuiClickOutsideDirective, { self: true });
|
|
4549
|
+
this.element = inject(ElementRef).nativeElement;
|
|
4550
|
+
this.markersService = inject(CuiMarkersService);
|
|
4551
|
+
this.SPACE_BETWEEN_TARGET_AND_LIST = 5;
|
|
4552
|
+
this.isVisible = signal(false);
|
|
4553
|
+
this.isHidden = signal(true);
|
|
4554
|
+
// TODO: set current type
|
|
4555
|
+
this.elements = this.markersService.getMarkersByType("tool" /* MarkerType.tool */);
|
|
4556
|
+
this.targetToggleEventListener = () => {
|
|
4557
|
+
this.isVisible.update((prev) => !prev);
|
|
4558
|
+
if (!this.isVisible()) {
|
|
4559
|
+
return;
|
|
4560
|
+
}
|
|
4561
|
+
this.calculateDropdownPosition();
|
|
4562
|
+
};
|
|
4563
|
+
}
|
|
4564
|
+
set space(value) {
|
|
4565
|
+
this.SPACE_BETWEEN_TARGET_AND_LIST = value;
|
|
4566
|
+
}
|
|
4567
|
+
get hide() {
|
|
4568
|
+
return this.isHidden();
|
|
4569
|
+
}
|
|
4570
|
+
writeValue(value) {
|
|
4571
|
+
this.value = value;
|
|
4572
|
+
}
|
|
4573
|
+
registerOnChange(fn) {
|
|
4574
|
+
this.onChange = fn;
|
|
4575
|
+
}
|
|
4576
|
+
registerOnTouched(fn) {
|
|
4577
|
+
this.onTouched = fn;
|
|
4578
|
+
}
|
|
4579
|
+
onScroll() {
|
|
4580
|
+
this.isVisible.set(false);
|
|
4581
|
+
}
|
|
4582
|
+
ngOnInit() {
|
|
4583
|
+
this.initTargetElementListener();
|
|
4584
|
+
this.initClickOutsideSubscription();
|
|
4585
|
+
this.initOnCloseWhenEditorScroll();
|
|
4586
|
+
}
|
|
4587
|
+
ngOnDestroy() {
|
|
4588
|
+
this.destroyEventListeners();
|
|
4589
|
+
}
|
|
4590
|
+
onToolClick(tool) {
|
|
4591
|
+
this.value = tool;
|
|
4592
|
+
this.onChange(this.value);
|
|
4593
|
+
this.onTouched();
|
|
4594
|
+
// this.isVisible.set(false);
|
|
4595
|
+
}
|
|
4596
|
+
initTargetElementListener() {
|
|
4597
|
+
this.target.addEventListener('click', this.targetToggleEventListener);
|
|
4598
|
+
}
|
|
4599
|
+
initClickOutsideSubscription() {
|
|
4600
|
+
this.cuiClickOutsideDirective.cuiClickOutside.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((target) => {
|
|
4601
|
+
if (this.target.contains(target) || !this.isVisible()) {
|
|
4602
|
+
return;
|
|
4603
|
+
}
|
|
4604
|
+
this.isVisible.set(false);
|
|
4605
|
+
});
|
|
4606
|
+
}
|
|
4607
|
+
initOnCloseWhenEditorScroll() {
|
|
4608
|
+
this.editor = this.element.closest(EDITOR_SELECTOR);
|
|
4609
|
+
this.editor?.addEventListener('scroll', this.onScroll.bind(this));
|
|
4610
|
+
}
|
|
4611
|
+
destroyEventListeners() {
|
|
4612
|
+
this.editor?.removeEventListener('scroll', this.onScroll.bind(this));
|
|
4613
|
+
this.target?.addEventListener('click', this.targetToggleEventListener);
|
|
4614
|
+
}
|
|
4615
|
+
calculateDropdownPosition() {
|
|
4616
|
+
this.isHidden.set(true);
|
|
4617
|
+
setTimeout(() => {
|
|
4618
|
+
const target = this.target;
|
|
4619
|
+
const { bottom: targetRectBottom, left: targetRectLeft } = target.getBoundingClientRect();
|
|
4620
|
+
const { clientHeight: documentClientHeight, clientWidth: documentClientWidth } = this.document.documentElement;
|
|
4621
|
+
const distanceToBottom = documentClientHeight - (targetRectBottom + this.SPACE_BETWEEN_TARGET_AND_LIST);
|
|
4622
|
+
const distanceToRight = documentClientWidth - targetRectLeft;
|
|
4623
|
+
const isListRight = distanceToRight < this.element.offsetWidth;
|
|
4624
|
+
const isListAbove = distanceToBottom < this.element.offsetHeight;
|
|
4625
|
+
this.changePositionY(isListAbove, target.offsetHeight, targetRectBottom);
|
|
4626
|
+
this.changePositionX(isListRight, target.offsetWidth, targetRectLeft);
|
|
4627
|
+
this.isHidden.set(false);
|
|
4628
|
+
});
|
|
4629
|
+
}
|
|
4630
|
+
changePositionX(isListRight, width, left) {
|
|
4631
|
+
if (isListRight) {
|
|
4632
|
+
this.element.style.right = 'auto';
|
|
4633
|
+
this.element.style.left = left;
|
|
4634
|
+
return;
|
|
4635
|
+
}
|
|
4636
|
+
this.element.style.right = left - this.element.offsetWidth + width;
|
|
4637
|
+
this.element.style.left = 'auto';
|
|
4638
|
+
}
|
|
4639
|
+
changePositionY(isListAbove, height, bottom) {
|
|
4640
|
+
if (isListAbove) {
|
|
4641
|
+
this.element.style.top =
|
|
4642
|
+
bottom - this.element.offsetHeight - height - this.SPACE_BETWEEN_TARGET_AND_LIST + 'px';
|
|
4643
|
+
return;
|
|
4644
|
+
}
|
|
4645
|
+
this.element.style.top = bottom + this.SPACE_BETWEEN_TARGET_AND_LIST + 'px';
|
|
4646
|
+
}
|
|
4647
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MarkerSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4648
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MarkerSelectComponent, isStandalone: true, selector: "cc-marker-select", inputs: { target: "target", space: "space" }, host: { properties: { "class._hidden": "this.hide" } }, providers: [
|
|
4649
|
+
{
|
|
4650
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4651
|
+
useExisting: forwardRef(() => MarkerSelectComponent),
|
|
4652
|
+
multi: true
|
|
4653
|
+
}
|
|
4654
|
+
], hostDirectives: [{ directive: i1$1.CuiClickOutsideDirective }], ngImport: i0, template: "<ng-container *ngIf=\"isVisible()\">\r\n <div\r\n #dropdown\r\n class=\"dropdown\"\r\n >\r\n <header class=\"header\">\r\n <cui-input-text\r\n class=\"header__input\"\r\n cuiTextFieldId=\"estimated\"\r\n cuiTextFieldPlaceholder=\"Search...\"\r\n />\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconFiltersLines\"\r\n ></button>\r\n </header>\r\n <div class=\"scrollable-content\">\r\n <cc-select-option\r\n *ngFor=\"let element of elements\"\r\n [class._selected]=\"element.id === value?.id\"\r\n (click)=\"onToolClick(element)\"\r\n [tool]=\"element\"\r\n />\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [":host{position:fixed;z-index:10;left:0}:host._hidden{visibility:hidden}._selected{background-color:var(--cui-base-50)}.dropdown{box-shadow:0 1px 4px #0000000a,0 1px 4px #0000000a;padding-top:3px;padding-bottom:3px;display:flex;flex-direction:column;gap:4px;border-radius:8px;border:1px solid var(--cui-base-200);max-height:350px;width:345px;background:var(--cui-base-0)}.header{padding:4px 5px;display:flex;align-items:center;gap:4px}.header__input{width:100%}.footer{padding:2px 5px}.title{font-weight:400;font-size:14px;line-height:20px;padding:2px 8px;color:var(--cui-base-500);text-transform:uppercase}.scrollable-content{padding-left:5px;overflow:auto}\n"], dependencies: [{ kind: "ngmodule", type: CuiButtonModule }, { kind: "component", type: CuiButtonComponent, selector: "button[cuiButton], a[cuiButton]", inputs: ["shape", "disabled", "isLoaderShown", "icon", "iconRight", "appearance", "size"] }, { kind: "ngmodule", type: CuiContextMenuModule }, { kind: "ngmodule", type: CuiInputModule }, { kind: "component", type: CuiInputTextComponent, selector: "cui-input-text" }, { kind: "directive", type: CuiTextFieldIdDirective, selector: "[cuiTextFieldId]", inputs: ["cuiTextFieldId"] }, { kind: "directive", type: CuiTextFieldPlaceholderDirective, selector: "[cuiTextFieldPlaceholder]", inputs: ["cuiTextFieldPlaceholder"] }, { kind: "ngmodule", type: CuiLabelModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: SelectOptionComponent, selector: "cc-select-option", inputs: ["tool"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4655
|
+
}
|
|
4656
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MarkerSelectComponent, decorators: [{
|
|
4657
|
+
type: Component,
|
|
4658
|
+
args: [{ selector: 'cc-marker-select', imports: [
|
|
4659
|
+
CuiButtonModule,
|
|
4660
|
+
CuiContextMenuModule,
|
|
4661
|
+
CuiInputModule,
|
|
4662
|
+
CuiLabelModule,
|
|
4663
|
+
FormsModule,
|
|
4664
|
+
ReactiveFormsModule,
|
|
4665
|
+
SelectOptionComponent,
|
|
4666
|
+
NgIf,
|
|
4667
|
+
NgFor
|
|
4668
|
+
], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [CuiClickOutsideDirective], providers: [
|
|
4669
|
+
{
|
|
4670
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4671
|
+
useExisting: forwardRef(() => MarkerSelectComponent),
|
|
4672
|
+
multi: true
|
|
4673
|
+
}
|
|
4674
|
+
], template: "<ng-container *ngIf=\"isVisible()\">\r\n <div\r\n #dropdown\r\n class=\"dropdown\"\r\n >\r\n <header class=\"header\">\r\n <cui-input-text\r\n class=\"header__input\"\r\n cuiTextFieldId=\"estimated\"\r\n cuiTextFieldPlaceholder=\"Search...\"\r\n />\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconFiltersLines\"\r\n ></button>\r\n </header>\r\n <div class=\"scrollable-content\">\r\n <cc-select-option\r\n *ngFor=\"let element of elements\"\r\n [class._selected]=\"element.id === value?.id\"\r\n (click)=\"onToolClick(element)\"\r\n [tool]=\"element\"\r\n />\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [":host{position:fixed;z-index:10;left:0}:host._hidden{visibility:hidden}._selected{background-color:var(--cui-base-50)}.dropdown{box-shadow:0 1px 4px #0000000a,0 1px 4px #0000000a;padding-top:3px;padding-bottom:3px;display:flex;flex-direction:column;gap:4px;border-radius:8px;border:1px solid var(--cui-base-200);max-height:350px;width:345px;background:var(--cui-base-0)}.header{padding:4px 5px;display:flex;align-items:center;gap:4px}.header__input{width:100%}.footer{padding:2px 5px}.title{font-weight:400;font-size:14px;line-height:20px;padding:2px 8px;color:var(--cui-base-500);text-transform:uppercase}.scrollable-content{padding-left:5px;overflow:auto}\n"] }]
|
|
4675
|
+
}], propDecorators: { target: [{
|
|
4676
|
+
type: Input
|
|
4677
|
+
}], space: [{
|
|
4678
|
+
type: Input
|
|
4679
|
+
}], hide: [{
|
|
4680
|
+
type: HostBinding,
|
|
4681
|
+
args: ['class._hidden']
|
|
4682
|
+
}] } });
|
|
4683
|
+
|
|
4684
|
+
const MARKER_SELECT_SELECTOR = 'marker-select';
|
|
4685
|
+
|
|
4686
|
+
class MarkerModalComponent {
|
|
4687
|
+
constructor() {
|
|
4688
|
+
this.element = inject(ElementRef).nativeElement;
|
|
4689
|
+
this.document = inject(DOCUMENT);
|
|
4690
|
+
this.destroyRef = inject(DestroyRef);
|
|
4691
|
+
this.cuiClickOutsideDirective = inject(CuiClickOutsideDirective, { self: true });
|
|
4692
|
+
this.cuiIdService = inject(CuiIdService);
|
|
4693
|
+
this.markersService = inject(CuiMarkersService);
|
|
4694
|
+
this.TITLE_MAX_LENGTH = 100;
|
|
4695
|
+
this.formTitle = signal('');
|
|
4696
|
+
this.isTitleEmpty = computed(() => !this.formTitle().length);
|
|
4697
|
+
this.isTitleMoreThanMaxLength = computed(() => this.formTitle().length > this.TITLE_MAX_LENGTH);
|
|
4698
|
+
this.isTitleInvalid = computed(() => this.isTitleEmpty() || this.isTitleMoreThanMaxLength());
|
|
4699
|
+
this.titleId = this.cuiIdService.generate();
|
|
4700
|
+
this.dataId = this.cuiIdService.generate();
|
|
4701
|
+
this.spaceBetweenTargetAndList = 5;
|
|
4702
|
+
this.startTitle = '';
|
|
4703
|
+
this.isGlobal = false;
|
|
4704
|
+
this.isTool = false;
|
|
4705
|
+
this.saveClicked = new EventEmitter();
|
|
4706
|
+
this.cancelClicked = new EventEmitter();
|
|
4707
|
+
this.isVisible = signal(false);
|
|
4708
|
+
this.isHidden = signal(true);
|
|
4709
|
+
this.targetToggleEventListener = () => {
|
|
4710
|
+
this.isVisible.update((prev) => !prev);
|
|
4711
|
+
if (!this.isVisible()) {
|
|
4712
|
+
return;
|
|
4713
|
+
}
|
|
4714
|
+
this.calculateDropdownPosition();
|
|
4715
|
+
};
|
|
4716
|
+
}
|
|
4717
|
+
set title(value) {
|
|
4718
|
+
this.startTitle = value;
|
|
4719
|
+
this.formTitle.set(value);
|
|
4720
|
+
}
|
|
4721
|
+
set url(value) {
|
|
4722
|
+
this.dynamicDataControl = new FormControl(value, {
|
|
4723
|
+
nonNullable: true,
|
|
4724
|
+
validators: [Validators.required, urlValidator()]
|
|
4725
|
+
});
|
|
4726
|
+
}
|
|
4727
|
+
set tool(value) {
|
|
4728
|
+
const tool = this.markersService.getMarkerObjectByType(value.type, value.id);
|
|
4729
|
+
this.dynamicDataControl = new FormControl(tool, {
|
|
4730
|
+
nonNullable: true,
|
|
4731
|
+
validators: [Validators.required]
|
|
4732
|
+
});
|
|
4733
|
+
}
|
|
4734
|
+
set space(value) {
|
|
4735
|
+
this.spaceBetweenTargetAndList = value;
|
|
4736
|
+
}
|
|
4737
|
+
get isFormInvalid() {
|
|
4738
|
+
return this.dynamicDataControl.invalid || this.isTitleInvalid();
|
|
4739
|
+
}
|
|
4740
|
+
get isDynamicDataErrorShown() {
|
|
4741
|
+
return this.dynamicDataControl.invalid && this.dynamicDataControl.dirty;
|
|
4742
|
+
}
|
|
4743
|
+
get hide() {
|
|
4744
|
+
return this.isHidden();
|
|
4745
|
+
}
|
|
4746
|
+
get fixed() {
|
|
4747
|
+
return this.isGlobal;
|
|
4748
|
+
}
|
|
4749
|
+
ngOnInit() {
|
|
4750
|
+
this.initTargetElementListener();
|
|
4751
|
+
this.initClickOutsideSubscription();
|
|
4752
|
+
this.initOnCloseWhenEditorScroll();
|
|
4753
|
+
}
|
|
4754
|
+
ngOnDestroy() {
|
|
4755
|
+
this.destroyEventListeners();
|
|
4756
|
+
}
|
|
4757
|
+
onTitleLabelClick(element) {
|
|
4758
|
+
const range = document.createRange();
|
|
4759
|
+
const selection = window.getSelection();
|
|
4760
|
+
range.selectNodeContents(element);
|
|
4761
|
+
range.collapse(false);
|
|
4762
|
+
selection?.removeAllRanges();
|
|
4763
|
+
selection?.addRange(range);
|
|
4764
|
+
}
|
|
4765
|
+
onSave() {
|
|
4766
|
+
if (this.isFormInvalid) {
|
|
4767
|
+
return;
|
|
4768
|
+
}
|
|
4769
|
+
this.isVisible.set(false);
|
|
4770
|
+
this.saveClicked.emit({ title: this.formTitle(), data: this.dynamicDataControl.value });
|
|
4771
|
+
}
|
|
4772
|
+
onScroll() {
|
|
4773
|
+
this.isVisible.set(false);
|
|
4774
|
+
}
|
|
4775
|
+
onCancel() {
|
|
4776
|
+
this.isVisible.set(false);
|
|
4777
|
+
this.cancelClicked.emit();
|
|
4778
|
+
}
|
|
4779
|
+
onClearTitle(titleElement) {
|
|
4780
|
+
this.formTitle.set('');
|
|
4781
|
+
titleElement.textContent = '';
|
|
4782
|
+
titleElement.focus();
|
|
4783
|
+
}
|
|
4784
|
+
onTitleChange(event) {
|
|
4785
|
+
if (event.key === 'Enter') {
|
|
4786
|
+
event.preventDefault();
|
|
4787
|
+
return;
|
|
4788
|
+
}
|
|
4789
|
+
const target = event.target;
|
|
4790
|
+
const value = target.textContent;
|
|
4791
|
+
this.formTitle.set(value);
|
|
4792
|
+
}
|
|
4793
|
+
async onTitlePaste(event) {
|
|
4794
|
+
event.stopPropagation();
|
|
4795
|
+
event.preventDefault();
|
|
4796
|
+
if (!this.document) {
|
|
4797
|
+
return;
|
|
4798
|
+
}
|
|
4799
|
+
const value = await window.navigator.clipboard.readText();
|
|
4800
|
+
const target = event.target;
|
|
4801
|
+
this.document.execCommand('insertText', false, value);
|
|
4802
|
+
setTimeout(() => this.formTitle.set(target.textContent));
|
|
4803
|
+
}
|
|
4804
|
+
initTargetElementListener() {
|
|
4805
|
+
this.target.addEventListener('click', this.targetToggleEventListener);
|
|
4806
|
+
}
|
|
4807
|
+
initClickOutsideSubscription() {
|
|
4808
|
+
this.cuiClickOutsideDirective.cuiClickOutside.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((target) => {
|
|
4809
|
+
if (this.element.contains(target) || this.target.contains(target) || !this.isVisible()) {
|
|
4810
|
+
return;
|
|
4811
|
+
}
|
|
4812
|
+
this.isVisible.set(false);
|
|
4813
|
+
});
|
|
4814
|
+
}
|
|
4815
|
+
initOnCloseWhenEditorScroll() {
|
|
4816
|
+
this.editor = this.document.querySelector(EDITOR_SELECTOR);
|
|
4817
|
+
this.editor.addEventListener('scroll', this.onScroll.bind(this));
|
|
4818
|
+
}
|
|
4819
|
+
destroyEventListeners() {
|
|
4820
|
+
this.editor.removeEventListener('scroll', this.onScroll.bind(this));
|
|
4821
|
+
this.target.addEventListener('click', this.targetToggleEventListener);
|
|
4822
|
+
}
|
|
4823
|
+
calculateDropdownPosition() {
|
|
4824
|
+
this.isHidden.set(true);
|
|
4825
|
+
setTimeout(() => {
|
|
4826
|
+
const target = this.target;
|
|
4827
|
+
const { bottom: targetRectBottom, left: targetRectLeft } = target.getBoundingClientRect();
|
|
4828
|
+
const { clientHeight: documentClientHeight, clientWidth: documentClientWidth } = this.document.documentElement;
|
|
4829
|
+
const distanceToBottom = documentClientHeight - (targetRectBottom + this.spaceBetweenTargetAndList);
|
|
4830
|
+
const distanceToRight = documentClientWidth - targetRectLeft;
|
|
4831
|
+
const isListRight = distanceToRight < this.element.offsetWidth;
|
|
4832
|
+
const isListAbove = distanceToBottom < this.element.offsetHeight;
|
|
4833
|
+
this.changePositionY(isListAbove, target.offsetHeight, targetRectBottom);
|
|
4834
|
+
this.changePositionX(isListRight, target.offsetWidth, targetRectLeft);
|
|
4835
|
+
this.isHidden.set(false);
|
|
4836
|
+
});
|
|
4837
|
+
}
|
|
4838
|
+
changePositionX(isListRight, width, left) {
|
|
4839
|
+
if (this.isGlobal) {
|
|
4840
|
+
this.changeGlobalPositionX(isListRight, width, left);
|
|
4841
|
+
return;
|
|
4842
|
+
}
|
|
4843
|
+
if (isListRight) {
|
|
4844
|
+
this.element.style.right = '0';
|
|
4845
|
+
this.element.style.left = 'auto';
|
|
4846
|
+
return;
|
|
4847
|
+
}
|
|
4848
|
+
this.element.style.right = 'auto';
|
|
4849
|
+
this.element.style.left = '0';
|
|
4850
|
+
}
|
|
4851
|
+
changePositionY(isListAbove, height, bottom) {
|
|
4852
|
+
if (this.isGlobal) {
|
|
4853
|
+
this.changeGlobalPositionY(isListAbove, height, bottom);
|
|
4854
|
+
return;
|
|
4855
|
+
}
|
|
4856
|
+
if (isListAbove) {
|
|
4857
|
+
this.element.style.bottom = height + this.spaceBetweenTargetAndList + 'px';
|
|
4858
|
+
this.element.style.top = 'auto';
|
|
4859
|
+
return;
|
|
4860
|
+
}
|
|
4861
|
+
this.element.style.top = height + this.spaceBetweenTargetAndList + 'px';
|
|
4862
|
+
this.element.style.bottom = 'auto';
|
|
4863
|
+
}
|
|
4864
|
+
changeGlobalPositionX(isListRight, width, left) {
|
|
4865
|
+
if (isListRight) {
|
|
4866
|
+
this.element.style.left = left - this.element.offsetWidth + width + 'px';
|
|
4867
|
+
return;
|
|
4868
|
+
}
|
|
4869
|
+
this.element.style.left = left + 'px';
|
|
4870
|
+
}
|
|
4871
|
+
changeGlobalPositionY(isListAbove, height, bottom) {
|
|
4872
|
+
if (isListAbove) {
|
|
4873
|
+
this.element.style.top =
|
|
4874
|
+
bottom - this.element.offsetHeight - height - this.spaceBetweenTargetAndList + 'px';
|
|
4875
|
+
return;
|
|
4876
|
+
}
|
|
4877
|
+
this.element.style.top = bottom + this.spaceBetweenTargetAndList + 'px';
|
|
4878
|
+
}
|
|
4879
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MarkerModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4880
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MarkerModalComponent, isStandalone: true, selector: "ng-component", inputs: { title: "title", url: "url", tool: "tool", isGlobal: "isGlobal", isTool: "isTool", target: "target", space: "space" }, outputs: { saveClicked: "saveClicked", cancelClicked: "cancelClicked" }, host: { properties: { "class._hidden": "this.hide", "class._fixed": "this.fixed" } }, hostDirectives: [{ directive: i1$1.CuiClickOutsideDirective }], ngImport: i0, template: "<ng-container *transloco=\"let t\">\r\n <ng-container *ngIf=\"isVisible()\">\r\n <form\r\n autocomplete=\"off\"\r\n class=\"wrapper\"\r\n >\r\n <cui-form-field>\r\n <!-- eslint-disable-next-line -->\r\n <label\r\n [for]=\"titleId\"\r\n cuiLabel\r\n [isRequired]=\"true\"\r\n (click)=\"onTitleLabelClick(titleElement)\"\r\n >\r\n {{ t('TITLE') }}\r\n </label>\r\n <!-- TODO: \u0435\u0441\u043B\u0438 \u043D\u0430\u0439\u0434\u0435\u0442\u0441\u044F \u0432\u0430\u0440\u0438\u043A \u0441\u0434\u0435\u043B\u0430\u0442\u044C \u0447\u0435\u0440\u0435\u0437 \u0444\u043E\u0440\u043C\u0443 -->\r\n <div\r\n class=\"title\"\r\n [class.title_invalid]=\"isTitleInvalid()\"\r\n >\r\n <div\r\n #titleElement\r\n class=\"title__text\"\r\n contenteditable\r\n attr.data-placeholder=\"{{ t('TITLE') }}...\"\r\n (paste)=\"onTitlePaste($event)\"\r\n (keyup)=\"onTitleChange($event)\"\r\n [innerHTML]=\"startTitle\"\r\n ></div>\r\n <button\r\n type=\"button\"\r\n class=\"title__clear\"\r\n (click)=\"onClearTitle(titleElement)\"\r\n >\r\n <cui-svg\r\n icon=\"cuiIconClear\"\r\n color=\"var(--cui-base-300)\"\r\n class=\"title__icon\"\r\n />\r\n </button>\r\n </div>\r\n\r\n <cui-hint *ngIf=\"isTitleInvalid()\" hintType=\"error\">\r\n <ng-container *ngIf=\"isTitleEmpty()\">\r\n {{ t('FIELD_IS_REQUIRED') }}\r\n </ng-container>\r\n <ng-container *ngIf=\"isTitleMoreThanMaxLength()\">\r\n {{ t('PLEASE_KEEP_FIELD_UNDER_CHARACTERS') }}\r\n </ng-container>\r\n </cui-hint>\r\n </cui-form-field>\r\n <cui-form-field>\r\n <label\r\n [for]=\"dataId\"\r\n cuiLabel\r\n [isRequired]=\"true\"\r\n >\r\n {{ isTool ? t('TOOL') : t('URL') }}\r\n </label>\r\n <ng-container *ngIf=\"dynamicDataControl\">\r\n <ng-container *ngIf=\"isTool; else input\">\r\n <div>\r\n <button\r\n #target=\"elementRef\"\r\n class=\"button tool-button\"\r\n cuiButton\r\n type=\"button\"\r\n cuiElement\r\n appearance=\"outlined-gray\"\r\n size=\"sm\"\r\n >\r\n {{ $any(dynamicDataControl.value)?.title || t('SELECT_TOOL') }}\r\n </button>\r\n </div>\r\n <cc-marker-select\r\n [formControl]=\"dynamicDataControl\"\r\n [target]=\"target.nativeElement\"\r\n />\r\n </ng-container>\r\n <ng-template #input>\r\n <cui-input-text\r\n [cuiTextFieldId]=\"dataId\"\r\n [formControl]=\"dynamicDataControl\"\r\n autocomplete=\"off\"\r\n [cuiTextFieldIsError]=\"isDynamicDataErrorShown\"\r\n cuiTextFieldPlaceholder=\"{{ t('LINK') }}...\"\r\n />\r\n <cui-hint *ngIf=\"isDynamicDataErrorShown\" hintType=\"error\">\r\n <ng-container *ngIf=\"dynamicDataControl.errors?.['required']\">\r\n {{ t('FIELD_IS_REQUIRED') }}\r\n </ng-container>\r\n <ng-container *ngIf=\"dynamicDataControl.errors?.['url']\">\r\n {{ t('INVALID_URL') }}\r\n </ng-container>\r\n </cui-hint>\r\n </ng-template>\r\n </ng-container>\r\n </cui-form-field>\r\n <div class=\"buttons\">\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"outlined-gray\"\r\n size=\"sm\"\r\n (click)=\"onCancel()\"\r\n >\r\n {{ t('CANCEL') }}\r\n </button>\r\n <button\r\n cuiButton\r\n type=\"submit\"\r\n appearance=\"action\"\r\n size=\"sm\"\r\n [disabled]=\"isFormInvalid\"\r\n (click)=\"onSave()\"\r\n >\r\n {{ t('SAVE') }}\r\n </button>\r\n </div>\r\n </form>\r\n </ng-container>\r\n</ng-container>\r\n\r\n", styles: [":host{position:absolute;z-index:1;left:0}:host._fixed{position:fixed}:host._hidden{position:fixed;visibility:hidden}:host ::ng-deep .tool-button{width:100%}:host ::ng-deep .tool-button>span{justify-content:flex-start!important}.wrapper{padding:11px;box-shadow:0 2px 4px -1px #0000000f,0 4px 6px -1px #0000001a;display:flex;flex-direction:column;gap:16px;border-radius:8px;border:1px solid var(--cui-base-200);max-width:450px;background-color:var(--cui-base-0)}.buttons{padding-top:12px;display:flex;justify-content:flex-end;gap:12px}.title{padding:7px 13px;cursor:text;display:flex;align-items:center;gap:8px;border:1px solid var(--cui-base-200);border-radius:8px;width:426px;background:var(--cui-input);color:var(--cui-base-900)}.title:hover{border-color:var(--cui-base-300)}.title:focus-within{outline:none;box-shadow:0 0 0 2px var(--cui-focus);border-color:var(--cui-info)}.title_invalid,.title_invalid:focus-within{box-shadow:none;border-color:var(--cui-danger)}.title__text{flex-grow:1;text-wrap:nowrap;overflow:hidden}.title__text[data-placeholder]:empty:before{content:attr(data-placeholder);position:absolute;color:var(--cui-base-400)}.title__text:focus{outline:none}.title__clear{padding:0;visibility:hidden}.title__icon{width:16px}.title__icon ::ng-deep [stroke]{stroke:var(--cui-base-0)}.title__text:not(:empty)+.title__clear{visibility:visible}\n"], dependencies: [{ kind: "ngmodule", type: CuiButtonModule }, { kind: "component", type: CuiButtonComponent, selector: "button[cuiButton], a[cuiButton]", inputs: ["shape", "disabled", "isLoaderShown", "icon", "iconRight", "appearance", "size"] }, { kind: "directive", type: CuiElementDirective, selector: "[cuiElement]", exportAs: ["elementRef"] }, { kind: "ngmodule", type: CuiFormFieldModule }, { kind: "component", type: CuiFormFieldComponent, selector: "cui-form-field" }, { kind: "ngmodule", type: CuiHintModule }, { kind: "component", type: CuiHintComponent, selector: "cui-hint", inputs: ["hintType"] }, { kind: "ngmodule", type: CuiInputModule }, { kind: "component", type: CuiInputTextComponent, selector: "cui-input-text" }, { kind: "directive", type: CuiTextFieldIdDirective, selector: "[cuiTextFieldId]", inputs: ["cuiTextFieldId"] }, { kind: "directive", type: CuiTextFieldPlaceholderDirective, selector: "[cuiTextFieldPlaceholder]", inputs: ["cuiTextFieldPlaceholder"] }, { kind: "directive", type: CuiTextFieldIsErrorDirective, selector: "[cuiTextFieldIsError]", inputs: ["cuiTextFieldIsError"] }, { kind: "ngmodule", type: CuiLabelModule }, { kind: "component", type: CuiLabelComponent, selector: "label[cuiLabel]", inputs: ["isRequired"] }, { kind: "ngmodule", type: CuiSvgModule }, { kind: "component", type: CuiSvgComponent, selector: "cui-svg[icon]", inputs: ["width", "height", "strokeWidth", "color", "icon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: MarkerSelectComponent, selector: "cc-marker-select", inputs: ["target", "space"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4881
|
+
}
|
|
4882
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MarkerModalComponent, decorators: [{
|
|
4883
|
+
type: Component,
|
|
4884
|
+
args: [{ standalone: true, imports: [
|
|
4885
|
+
CuiButtonModule,
|
|
4886
|
+
CuiElementDirective,
|
|
4887
|
+
CuiFormFieldModule,
|
|
4888
|
+
CuiHintModule,
|
|
4889
|
+
CuiInputModule,
|
|
4890
|
+
CuiLabelModule,
|
|
4891
|
+
CuiSvgModule,
|
|
4892
|
+
FormsModule,
|
|
4893
|
+
MarkerSelectComponent,
|
|
4894
|
+
ReactiveFormsModule,
|
|
4895
|
+
TranslocoDirective,
|
|
4896
|
+
NgIf
|
|
4897
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [CuiClickOutsideDirective], template: "<ng-container *transloco=\"let t\">\r\n <ng-container *ngIf=\"isVisible()\">\r\n <form\r\n autocomplete=\"off\"\r\n class=\"wrapper\"\r\n >\r\n <cui-form-field>\r\n <!-- eslint-disable-next-line -->\r\n <label\r\n [for]=\"titleId\"\r\n cuiLabel\r\n [isRequired]=\"true\"\r\n (click)=\"onTitleLabelClick(titleElement)\"\r\n >\r\n {{ t('TITLE') }}\r\n </label>\r\n <!-- TODO: \u0435\u0441\u043B\u0438 \u043D\u0430\u0439\u0434\u0435\u0442\u0441\u044F \u0432\u0430\u0440\u0438\u043A \u0441\u0434\u0435\u043B\u0430\u0442\u044C \u0447\u0435\u0440\u0435\u0437 \u0444\u043E\u0440\u043C\u0443 -->\r\n <div\r\n class=\"title\"\r\n [class.title_invalid]=\"isTitleInvalid()\"\r\n >\r\n <div\r\n #titleElement\r\n class=\"title__text\"\r\n contenteditable\r\n attr.data-placeholder=\"{{ t('TITLE') }}...\"\r\n (paste)=\"onTitlePaste($event)\"\r\n (keyup)=\"onTitleChange($event)\"\r\n [innerHTML]=\"startTitle\"\r\n ></div>\r\n <button\r\n type=\"button\"\r\n class=\"title__clear\"\r\n (click)=\"onClearTitle(titleElement)\"\r\n >\r\n <cui-svg\r\n icon=\"cuiIconClear\"\r\n color=\"var(--cui-base-300)\"\r\n class=\"title__icon\"\r\n />\r\n </button>\r\n </div>\r\n\r\n <cui-hint *ngIf=\"isTitleInvalid()\" hintType=\"error\">\r\n <ng-container *ngIf=\"isTitleEmpty()\">\r\n {{ t('FIELD_IS_REQUIRED') }}\r\n </ng-container>\r\n <ng-container *ngIf=\"isTitleMoreThanMaxLength()\">\r\n {{ t('PLEASE_KEEP_FIELD_UNDER_CHARACTERS') }}\r\n </ng-container>\r\n </cui-hint>\r\n </cui-form-field>\r\n <cui-form-field>\r\n <label\r\n [for]=\"dataId\"\r\n cuiLabel\r\n [isRequired]=\"true\"\r\n >\r\n {{ isTool ? t('TOOL') : t('URL') }}\r\n </label>\r\n <ng-container *ngIf=\"dynamicDataControl\">\r\n <ng-container *ngIf=\"isTool; else input\">\r\n <div>\r\n <button\r\n #target=\"elementRef\"\r\n class=\"button tool-button\"\r\n cuiButton\r\n type=\"button\"\r\n cuiElement\r\n appearance=\"outlined-gray\"\r\n size=\"sm\"\r\n >\r\n {{ $any(dynamicDataControl.value)?.title || t('SELECT_TOOL') }}\r\n </button>\r\n </div>\r\n <cc-marker-select\r\n [formControl]=\"dynamicDataControl\"\r\n [target]=\"target.nativeElement\"\r\n />\r\n </ng-container>\r\n <ng-template #input>\r\n <cui-input-text\r\n [cuiTextFieldId]=\"dataId\"\r\n [formControl]=\"dynamicDataControl\"\r\n autocomplete=\"off\"\r\n [cuiTextFieldIsError]=\"isDynamicDataErrorShown\"\r\n cuiTextFieldPlaceholder=\"{{ t('LINK') }}...\"\r\n />\r\n <cui-hint *ngIf=\"isDynamicDataErrorShown\" hintType=\"error\">\r\n <ng-container *ngIf=\"dynamicDataControl.errors?.['required']\">\r\n {{ t('FIELD_IS_REQUIRED') }}\r\n </ng-container>\r\n <ng-container *ngIf=\"dynamicDataControl.errors?.['url']\">\r\n {{ t('INVALID_URL') }}\r\n </ng-container>\r\n </cui-hint>\r\n </ng-template>\r\n </ng-container>\r\n </cui-form-field>\r\n <div class=\"buttons\">\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"outlined-gray\"\r\n size=\"sm\"\r\n (click)=\"onCancel()\"\r\n >\r\n {{ t('CANCEL') }}\r\n </button>\r\n <button\r\n cuiButton\r\n type=\"submit\"\r\n appearance=\"action\"\r\n size=\"sm\"\r\n [disabled]=\"isFormInvalid\"\r\n (click)=\"onSave()\"\r\n >\r\n {{ t('SAVE') }}\r\n </button>\r\n </div>\r\n </form>\r\n </ng-container>\r\n</ng-container>\r\n\r\n", styles: [":host{position:absolute;z-index:1;left:0}:host._fixed{position:fixed}:host._hidden{position:fixed;visibility:hidden}:host ::ng-deep .tool-button{width:100%}:host ::ng-deep .tool-button>span{justify-content:flex-start!important}.wrapper{padding:11px;box-shadow:0 2px 4px -1px #0000000f,0 4px 6px -1px #0000001a;display:flex;flex-direction:column;gap:16px;border-radius:8px;border:1px solid var(--cui-base-200);max-width:450px;background-color:var(--cui-base-0)}.buttons{padding-top:12px;display:flex;justify-content:flex-end;gap:12px}.title{padding:7px 13px;cursor:text;display:flex;align-items:center;gap:8px;border:1px solid var(--cui-base-200);border-radius:8px;width:426px;background:var(--cui-input);color:var(--cui-base-900)}.title:hover{border-color:var(--cui-base-300)}.title:focus-within{outline:none;box-shadow:0 0 0 2px var(--cui-focus);border-color:var(--cui-info)}.title_invalid,.title_invalid:focus-within{box-shadow:none;border-color:var(--cui-danger)}.title__text{flex-grow:1;text-wrap:nowrap;overflow:hidden}.title__text[data-placeholder]:empty:before{content:attr(data-placeholder);position:absolute;color:var(--cui-base-400)}.title__text:focus{outline:none}.title__clear{padding:0;visibility:hidden}.title__icon{width:16px}.title__icon ::ng-deep [stroke]{stroke:var(--cui-base-0)}.title__text:not(:empty)+.title__clear{visibility:visible}\n"] }]
|
|
4898
|
+
}], propDecorators: { title: [{
|
|
4899
|
+
type: Input
|
|
4900
|
+
}], url: [{
|
|
4901
|
+
type: Input
|
|
4902
|
+
}], tool: [{
|
|
4903
|
+
type: Input
|
|
4904
|
+
}], isGlobal: [{
|
|
4905
|
+
type: Input
|
|
4906
|
+
}], isTool: [{
|
|
4907
|
+
type: Input
|
|
4908
|
+
}], target: [{
|
|
4909
|
+
type: Input
|
|
4910
|
+
}], space: [{
|
|
4911
|
+
type: Input
|
|
4912
|
+
}], saveClicked: [{
|
|
4913
|
+
type: Output
|
|
4914
|
+
}], cancelClicked: [{
|
|
4915
|
+
type: Output
|
|
4916
|
+
}], hide: [{
|
|
4917
|
+
type: HostBinding,
|
|
4918
|
+
args: ['class._hidden']
|
|
4919
|
+
}], fixed: [{
|
|
4920
|
+
type: HostBinding,
|
|
4921
|
+
args: ['class._fixed']
|
|
4922
|
+
}] } });
|
|
4923
|
+
|
|
4924
|
+
const MARKER_MODAL_SELECTOR = 'cc-marker-modal';
|
|
4925
|
+
|
|
4926
|
+
function createLinkModal(tooltip, link) {
|
|
4927
|
+
const linkModal = document.createElement(MARKER_MODAL_SELECTOR);
|
|
4928
|
+
const button = tooltip.querySelector('.edit');
|
|
4929
|
+
linkModal.url = link.href;
|
|
4930
|
+
linkModal.title = link.innerText;
|
|
4931
|
+
linkModal.target = button;
|
|
4932
|
+
linkModal.space = 15;
|
|
4933
|
+
linkModal.addEventListener('saveClicked', (event) => {
|
|
4934
|
+
const customEvent = event;
|
|
4935
|
+
if (typeof customEvent.detail.data === 'string') {
|
|
4936
|
+
link.setAttribute('href', customEvent.detail.data);
|
|
4937
|
+
}
|
|
4938
|
+
link.innerHTML = customEvent.detail.title;
|
|
4939
|
+
tooltip.remove();
|
|
4940
|
+
});
|
|
4941
|
+
linkModal.addEventListener('cancelClicked', () => {
|
|
4942
|
+
tooltip.remove();
|
|
4943
|
+
});
|
|
4944
|
+
return linkModal;
|
|
4945
|
+
}
|
|
4946
|
+
|
|
4947
|
+
class EditorToolModalComponent {
|
|
4948
|
+
set marker(value) {
|
|
4949
|
+
this.calculateModalPosition(value);
|
|
4950
|
+
}
|
|
4951
|
+
get _isHidden() {
|
|
4952
|
+
return this.isHidden();
|
|
4953
|
+
}
|
|
4954
|
+
get _isFullscreen() {
|
|
4955
|
+
return this.isFullscreen();
|
|
4956
|
+
}
|
|
4957
|
+
constructor() {
|
|
4958
|
+
this.element = inject(ElementRef).nativeElement;
|
|
4959
|
+
this.window = inject(CUI_WINDOW);
|
|
4960
|
+
this.cuiClickOutsideDirective = inject(CuiClickOutsideDirective, { self: true });
|
|
4961
|
+
this.SPACE_BETWEEN_TARGET_AND_LIST = 10;
|
|
4962
|
+
this.isFullscreen = signal(false);
|
|
4963
|
+
this.isHidden = signal(true);
|
|
4964
|
+
this.closed = new EventEmitter();
|
|
4965
|
+
this.initClickOutsideSubscription();
|
|
4966
|
+
}
|
|
4967
|
+
onCloseModal() {
|
|
4968
|
+
this.closed.emit();
|
|
4969
|
+
}
|
|
4970
|
+
onMaximizeModal() {
|
|
4971
|
+
this.isFullscreen.update((prev) => !prev);
|
|
4972
|
+
}
|
|
4973
|
+
initClickOutsideSubscription() {
|
|
4974
|
+
this.cuiClickOutsideDirective.cuiClickOutside
|
|
4975
|
+
.pipe(skip(1), takeUntilDestroyed())
|
|
4976
|
+
.subscribe(() => this.onCloseModal());
|
|
4977
|
+
}
|
|
4978
|
+
calculateModalPosition(marker) {
|
|
4979
|
+
const { bottom, left } = marker.getBoundingClientRect();
|
|
4980
|
+
setTimeout(() => {
|
|
4981
|
+
const modalWidth = this.element.offsetWidth;
|
|
4982
|
+
this.element.style.top = bottom + this.window.scrollY + this.SPACE_BETWEEN_TARGET_AND_LIST + 'px';
|
|
4983
|
+
this.element.style.left = left + this.window.scrollX + marker.offsetWidth / 2 - modalWidth / 2 + 'px';
|
|
4984
|
+
this.isHidden.set(false);
|
|
4985
|
+
});
|
|
4986
|
+
}
|
|
4987
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorToolModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4988
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: EditorToolModalComponent, isStandalone: true, selector: "ng-component", inputs: { tool: "tool", marker: "marker" }, outputs: { closed: "closed" }, host: { properties: { "class._hidden": "this._isHidden", "class._fullscreen": "this._isFullscreen" } }, hostDirectives: [{ directive: i1$1.CuiClickOutsideDirective }], ngImport: i0, template: "<div class=\"triangle\"></div>\r\n<div class=\"wrapper\">\r\n <header class=\"header\">\r\n <h3 class=\"title\">{{ tool.title }}</h3>\r\n <div class=\"header__buttons\">\r\n <!-- TODO: replace icon with 'maximize' -->\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconArrowSortSm\"\r\n (click)=\"onMaximizeModal()\"\r\n ></button>\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconX\"\r\n (click)=\"onCloseModal()\"\r\n ></button>\r\n </div>\r\n </header>\r\n <div class=\"content\">\r\n <div class=\"info\">\r\n <!-- TODO: \u0431\u0443\u0434\u0435\u0442 \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0430-->\r\n <p class=\"info__item\">\r\n <span class=\"info__field\">\u0422\u0438\u043F:</span>\r\n <span class=\"info__title\">{{ tool.title }}</span>\r\n </p>\r\n <p class=\"info__item\">\r\n <span class=\"info__field\">\u0421\u0442\u0440\u0430\u043D\u0430 \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044C:</span>\r\n <span class=\"info__title\">{{ tool.title }}</span>\r\n </p>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".content{padding-right:23px;padding-left:23px;padding-bottom:7px;font-weight:400;font-size:14px;line-height:20px;font-family:var(--cui-main-font);max-height:415px;overflow-y:auto}:host{position:absolute;z-index:10;left:50%;top:30px;min-height:100px;max-width:450px}:host._fullscreen{position:fixed;top:0!important;left:0!important;max-width:none;height:100vh;width:100%;transform:none}:host._fullscreen .content{max-height:calc(100% - 56px)}:host._hidden{visibility:hidden}.triangle{position:absolute;top:-7px;left:50%;width:14px;height:14px;border-radius:2px;border:1px solid var(--cui-base-200);background:var(--cui-base-0);transform:translate(-50%) rotate(45deg)}.wrapper{position:relative;border-radius:8px;border:1px solid var(--cui-base-200);background:var(--cui-base-0);height:100%}.header{padding:8.2px 15px 8px;display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:12px}.title{font-weight:500;font-size:14px;line-height:20px;padding-top:2px;padding-bottom:2px;text-wrap:nowrap;text-overflow:ellipsis;overflow:hidden;color:var(--cui-base-900)}.info{display:flex;flex-direction:column;gap:8px}.info__item{display:flex;gap:8px}.info__field{font-weight:400;font-size:16px;line-height:24px;text-wrap:nowrap;color:var(--cui-gray-600)}.info__title{font-weight:500;font-size:16px;line-height:24px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;color:var(--cui-base-900)}\n"], dependencies: [{ kind: "ngmodule", type: CuiButtonModule }, { kind: "component", type: CuiButtonComponent, selector: "button[cuiButton], a[cuiButton]", inputs: ["shape", "disabled", "isLoaderShown", "icon", "iconRight", "appearance", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4989
|
+
}
|
|
4990
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorToolModalComponent, decorators: [{
|
|
4991
|
+
type: Component,
|
|
4992
|
+
args: [{ standalone: true, imports: [CuiButtonModule], changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [CuiClickOutsideDirective], template: "<div class=\"triangle\"></div>\r\n<div class=\"wrapper\">\r\n <header class=\"header\">\r\n <h3 class=\"title\">{{ tool.title }}</h3>\r\n <div class=\"header__buttons\">\r\n <!-- TODO: replace icon with 'maximize' -->\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconArrowSortSm\"\r\n (click)=\"onMaximizeModal()\"\r\n ></button>\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconX\"\r\n (click)=\"onCloseModal()\"\r\n ></button>\r\n </div>\r\n </header>\r\n <div class=\"content\">\r\n <div class=\"info\">\r\n <!-- TODO: \u0431\u0443\u0434\u0435\u0442 \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0430-->\r\n <p class=\"info__item\">\r\n <span class=\"info__field\">\u0422\u0438\u043F:</span>\r\n <span class=\"info__title\">{{ tool.title }}</span>\r\n </p>\r\n <p class=\"info__item\">\r\n <span class=\"info__field\">\u0421\u0442\u0440\u0430\u043D\u0430 \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044C:</span>\r\n <span class=\"info__title\">{{ tool.title }}</span>\r\n </p>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".content{padding-right:23px;padding-left:23px;padding-bottom:7px;font-weight:400;font-size:14px;line-height:20px;font-family:var(--cui-main-font);max-height:415px;overflow-y:auto}:host{position:absolute;z-index:10;left:50%;top:30px;min-height:100px;max-width:450px}:host._fullscreen{position:fixed;top:0!important;left:0!important;max-width:none;height:100vh;width:100%;transform:none}:host._fullscreen .content{max-height:calc(100% - 56px)}:host._hidden{visibility:hidden}.triangle{position:absolute;top:-7px;left:50%;width:14px;height:14px;border-radius:2px;border:1px solid var(--cui-base-200);background:var(--cui-base-0);transform:translate(-50%) rotate(45deg)}.wrapper{position:relative;border-radius:8px;border:1px solid var(--cui-base-200);background:var(--cui-base-0);height:100%}.header{padding:8.2px 15px 8px;display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:12px}.title{font-weight:500;font-size:14px;line-height:20px;padding-top:2px;padding-bottom:2px;text-wrap:nowrap;text-overflow:ellipsis;overflow:hidden;color:var(--cui-base-900)}.info{display:flex;flex-direction:column;gap:8px}.info__item{display:flex;gap:8px}.info__field{font-weight:400;font-size:16px;line-height:24px;text-wrap:nowrap;color:var(--cui-gray-600)}.info__title{font-weight:500;font-size:16px;line-height:24px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;color:var(--cui-base-900)}\n"] }]
|
|
4993
|
+
}], ctorParameters: () => [], propDecorators: { tool: [{
|
|
4994
|
+
type: Input,
|
|
4995
|
+
args: [{ required: true }]
|
|
4996
|
+
}], marker: [{
|
|
4997
|
+
type: Input
|
|
4998
|
+
}], closed: [{
|
|
4999
|
+
type: Output
|
|
5000
|
+
}], _isHidden: [{
|
|
5001
|
+
type: HostBinding,
|
|
5002
|
+
args: ['class._hidden']
|
|
5003
|
+
}], _isFullscreen: [{
|
|
5004
|
+
type: HostBinding,
|
|
5005
|
+
args: ['class._fullscreen']
|
|
5006
|
+
}] } });
|
|
5007
|
+
|
|
5008
|
+
const EDITOR_TOOL_MODAL_SELECTOR = 'cc-editor-tool-modal';
|
|
5009
|
+
|
|
5010
|
+
class EditorTooltipComponent {
|
|
5011
|
+
constructor() {
|
|
5012
|
+
// TODO: Удалить класс
|
|
5013
|
+
this.BUTTONS_OPTIONS = new Map([
|
|
5014
|
+
['copy', { icon: 'cuiIconCopy', handler: (event) => this.copyClicked.emit(event) }],
|
|
5015
|
+
['edit', { icon: 'cuiIconEdit', handler: (event) => this.editClicked.emit(event), class: 'edit' }],
|
|
5016
|
+
['delete', { icon: 'cuiIconTrash', handler: (event) => this.deleteClicked.emit(event) }]
|
|
5017
|
+
]);
|
|
5018
|
+
this._options = ['edit', 'delete'];
|
|
5019
|
+
this.buttons = this.getButtonsFromOptions(this._options);
|
|
5020
|
+
this.copyClicked = new EventEmitter();
|
|
5021
|
+
this.editClicked = new EventEmitter();
|
|
5022
|
+
this.deleteClicked = new EventEmitter();
|
|
5023
|
+
}
|
|
5024
|
+
set options(value) {
|
|
5025
|
+
this._options = value;
|
|
5026
|
+
this.buttons = this.getButtonsFromOptions(value);
|
|
5027
|
+
}
|
|
5028
|
+
getButtonsFromOptions(options) {
|
|
5029
|
+
return options.map((option) => this.BUTTONS_OPTIONS.get(option));
|
|
5030
|
+
}
|
|
5031
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5032
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: EditorTooltipComponent, isStandalone: true, selector: "ng-component", inputs: { title: "title", options: "options" }, outputs: { copyClicked: "copyClicked", editClicked: "editClicked", deleteClicked: "deleteClicked" }, ngImport: i0, template: "<h3 class=\"title\">{{ title }}</h3>\r\n<div class=\"buttons-container\">\r\n <ng-container *ngFor=\"let button of buttons\">\r\n <div class=\"divider\"></div>\r\n <!-- TODO: class \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0443\u0434\u0430\u043B\u0451\u043D \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043C-->\r\n <button\r\n class=\"button\"\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n [icon]=\"button.icon\"\r\n [class]=\"button.class\"\r\n (click)=\"button.handler($event)\"\r\n ></button>\r\n </ng-container>\r\n</div>\r\n", styles: [":host{padding:4px 6px;box-shadow:0 4px 6px -2px #0000000d,0 10px 15px -3px #0000001a;font-weight:400;font-size:14px;line-height:20px;position:fixed;z-index:12;left:0;top:0;display:flex;align-items:center;gap:12px;border-radius:4px;font-family:var(--cui-main-font);background:var(--cui-gray-800)}.title{font-weight:400;font-size:14px;line-height:20px;max-width:300px;text-wrap:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--cui-gray-0)}.divider{width:1px;height:24px;background:var(--cui-gray-500)}.buttons-container{display:flex;align-items:center;gap:4px}.button{--cui-base-50: rgba(255 255 255 / 10%);--cui-base-500: var(--cui-gray-0)}\n"], dependencies: [{ kind: "ngmodule", type: CuiButtonModule }, { kind: "component", type: CuiButtonComponent, selector: "button[cuiButton], a[cuiButton]", inputs: ["shape", "disabled", "isLoaderShown", "icon", "iconRight", "appearance", "size"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5033
|
+
}
|
|
5034
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorTooltipComponent, decorators: [{
|
|
5035
|
+
type: Component,
|
|
5036
|
+
args: [{ standalone: true, imports: [CuiButtonModule, NgFor], changeDetection: ChangeDetectionStrategy.OnPush, template: "<h3 class=\"title\">{{ title }}</h3>\r\n<div class=\"buttons-container\">\r\n <ng-container *ngFor=\"let button of buttons\">\r\n <div class=\"divider\"></div>\r\n <!-- TODO: class \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0443\u0434\u0430\u043B\u0451\u043D \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043C-->\r\n <button\r\n class=\"button\"\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n [icon]=\"button.icon\"\r\n [class]=\"button.class\"\r\n (click)=\"button.handler($event)\"\r\n ></button>\r\n </ng-container>\r\n</div>\r\n", styles: [":host{padding:4px 6px;box-shadow:0 4px 6px -2px #0000000d,0 10px 15px -3px #0000001a;font-weight:400;font-size:14px;line-height:20px;position:fixed;z-index:12;left:0;top:0;display:flex;align-items:center;gap:12px;border-radius:4px;font-family:var(--cui-main-font);background:var(--cui-gray-800)}.title{font-weight:400;font-size:14px;line-height:20px;max-width:300px;text-wrap:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--cui-gray-0)}.divider{width:1px;height:24px;background:var(--cui-gray-500)}.buttons-container{display:flex;align-items:center;gap:4px}.button{--cui-base-50: rgba(255 255 255 / 10%);--cui-base-500: var(--cui-gray-0)}\n"] }]
|
|
5037
|
+
}], propDecorators: { title: [{
|
|
5038
|
+
type: Input,
|
|
5039
|
+
args: [{ required: true }]
|
|
5040
|
+
}], options: [{
|
|
5041
|
+
type: Input
|
|
5042
|
+
}], copyClicked: [{
|
|
5043
|
+
type: Output
|
|
5044
|
+
}], editClicked: [{
|
|
5045
|
+
type: Output
|
|
5046
|
+
}], deleteClicked: [{
|
|
5047
|
+
type: Output
|
|
5048
|
+
}] } });
|
|
5049
|
+
|
|
5050
|
+
const EDITOR_TOOLTIP_SELECTOR = 'cc-editor-tooltip';
|
|
5051
|
+
|
|
5052
|
+
class EditorToolComponent {
|
|
5053
|
+
constructor() {
|
|
5054
|
+
this.window = inject(CUI_WINDOW);
|
|
5055
|
+
this.document = inject(DOCUMENT);
|
|
5056
|
+
this.readOnly = false;
|
|
5057
|
+
this.isLoading = false;
|
|
5058
|
+
this.fileSelected = new EventEmitter();
|
|
5059
|
+
this.captionChanged = new EventEmitter();
|
|
5060
|
+
this.previousValue = this.caption;
|
|
5061
|
+
}
|
|
5062
|
+
get isCaptionShown() {
|
|
5063
|
+
return !this.readOnly || !!this.caption;
|
|
5064
|
+
}
|
|
5065
|
+
onSelectFile() {
|
|
5066
|
+
this.fileSelected.emit();
|
|
5067
|
+
}
|
|
5068
|
+
onTitleChange(event) {
|
|
5069
|
+
const target = event.currentTarget;
|
|
5070
|
+
if (target.innerHTML === '<br>') {
|
|
5071
|
+
target.innerHTML = '';
|
|
5072
|
+
}
|
|
5073
|
+
const value = target.innerHTML;
|
|
5074
|
+
if (this.previousValue === value) {
|
|
5075
|
+
return;
|
|
5076
|
+
}
|
|
5077
|
+
this.previousValue = value;
|
|
5078
|
+
this.captionChanged.emit(value);
|
|
5079
|
+
}
|
|
5080
|
+
async onTitlePaste(event) {
|
|
5081
|
+
event.stopPropagation();
|
|
5082
|
+
event.preventDefault();
|
|
5083
|
+
if (!this.document) {
|
|
5084
|
+
return;
|
|
5085
|
+
}
|
|
5086
|
+
const value = await this.window.navigator.clipboard.readText();
|
|
5087
|
+
const target = event.target;
|
|
5088
|
+
this.document.execCommand('insertText', false, value);
|
|
5089
|
+
setTimeout(() => this.captionChanged.emit(target.textContent));
|
|
5090
|
+
}
|
|
5091
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorToolComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5092
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: EditorToolComponent, selector: "ng-component", inputs: { api: "api", preview: "preview", caption: "caption", buttonContent: "buttonContent", readOnly: "readOnly", isLoading: "isLoading" }, outputs: { fileSelected: "fileSelected", captionChanged: "captionChanged" }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5093
|
+
}
|
|
5094
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorToolComponent, decorators: [{
|
|
5095
|
+
type: Component,
|
|
5096
|
+
args: [{
|
|
5097
|
+
template: '',
|
|
5098
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
5099
|
+
}]
|
|
5100
|
+
}], propDecorators: { api: [{
|
|
5101
|
+
type: Input,
|
|
5102
|
+
args: [{ required: true }]
|
|
5103
|
+
}], preview: [{
|
|
5104
|
+
type: Input,
|
|
5105
|
+
args: [{ required: true }]
|
|
5106
|
+
}], caption: [{
|
|
5107
|
+
type: Input,
|
|
5108
|
+
args: [{ required: true }]
|
|
5109
|
+
}], buttonContent: [{
|
|
5110
|
+
type: Input,
|
|
5111
|
+
args: [{ required: true }]
|
|
5112
|
+
}], readOnly: [{
|
|
5113
|
+
type: Input
|
|
5114
|
+
}], isLoading: [{
|
|
5115
|
+
type: Input
|
|
5116
|
+
}], fileSelected: [{
|
|
5117
|
+
type: Output
|
|
5118
|
+
}], captionChanged: [{
|
|
5119
|
+
type: Output
|
|
5120
|
+
}] } });
|
|
5121
|
+
|
|
5122
|
+
class FileSizePipe {
|
|
5123
|
+
constructor() {
|
|
5124
|
+
this.SIZES = ['Bytes', 'KB', 'MB', 'GB'];
|
|
5125
|
+
this.BYTES_IN_KILOBYTE = 1024;
|
|
5126
|
+
}
|
|
5127
|
+
transform(bytes) {
|
|
5128
|
+
if (isNaN(bytes) || bytes === 0) {
|
|
5129
|
+
return '0 Bytes';
|
|
5130
|
+
}
|
|
5131
|
+
const index = Math.floor(Math.log(bytes) / Math.log(this.BYTES_IN_KILOBYTE));
|
|
5132
|
+
return `${parseFloat((bytes / Math.pow(this.BYTES_IN_KILOBYTE, index)).toFixed(1))} ${this.SIZES[index]}`;
|
|
5133
|
+
}
|
|
5134
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FileSizePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
5135
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: FileSizePipe, isStandalone: true, name: "fileSize" }); }
|
|
5136
|
+
}
|
|
5137
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FileSizePipe, decorators: [{
|
|
5138
|
+
type: Pipe,
|
|
5139
|
+
args: [{
|
|
5140
|
+
name: 'fileSize',
|
|
5141
|
+
standalone: true
|
|
5142
|
+
}]
|
|
5143
|
+
}] });
|
|
5144
|
+
|
|
5145
|
+
class EditorAttachesToolComponent extends EditorToolComponent {
|
|
5146
|
+
constructor() {
|
|
5147
|
+
super(...arguments);
|
|
5148
|
+
this.Extensions = {
|
|
5149
|
+
doc: '#1483E9',
|
|
5150
|
+
docx: '#1483E9',
|
|
5151
|
+
odt: '#1483E9',
|
|
5152
|
+
pdf: '#DB2F2F',
|
|
5153
|
+
rtf: '#744FDC',
|
|
5154
|
+
tex: '#5a5a5b',
|
|
5155
|
+
txt: '#5a5a5b',
|
|
5156
|
+
pptx: '#E35200',
|
|
5157
|
+
ppt: '#E35200',
|
|
5158
|
+
mp3: '#eab456',
|
|
5159
|
+
mp4: '#f676a6',
|
|
5160
|
+
xls: '#11AE3D',
|
|
5161
|
+
html: '#2988f0',
|
|
5162
|
+
htm: '#2988f0',
|
|
5163
|
+
png: '#AA2284',
|
|
5164
|
+
jpg: '#D13359',
|
|
5165
|
+
jpeg: '#D13359',
|
|
5166
|
+
gif: '#f6af76',
|
|
5167
|
+
zip: '#4f566f',
|
|
5168
|
+
rar: '#4f566f',
|
|
5169
|
+
exe: '#e26f6f',
|
|
5170
|
+
svg: '#bf5252',
|
|
5171
|
+
key: '#00B2FF',
|
|
5172
|
+
sketch: '#FFC700',
|
|
5173
|
+
ai: '#FB601D',
|
|
5174
|
+
psd: '#388ae5',
|
|
5175
|
+
dmg: '#e26f6f',
|
|
5176
|
+
json: '#2988f0',
|
|
5177
|
+
csv: '#11AE3D'
|
|
5178
|
+
};
|
|
5179
|
+
}
|
|
5180
|
+
get color() {
|
|
5181
|
+
return this.Extensions[this.file?.extension];
|
|
5182
|
+
}
|
|
5183
|
+
get isShowLoadButton() {
|
|
5184
|
+
return !this.file && !this.isCaptionShown && !this.isLoading;
|
|
5185
|
+
}
|
|
5186
|
+
onPreventEnter(event) {
|
|
5187
|
+
if (this.checkKey(event)) {
|
|
5188
|
+
return;
|
|
5189
|
+
}
|
|
5190
|
+
event.preventDefault();
|
|
5191
|
+
event.stopPropagation();
|
|
5192
|
+
}
|
|
5193
|
+
checkKey(event) {
|
|
5194
|
+
return event.key !== 'Enter';
|
|
5195
|
+
}
|
|
5196
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorAttachesToolComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
5197
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: EditorAttachesToolComponent, isStandalone: true, selector: "ng-component", inputs: { file: "file", title: "title" }, host: { properties: { "class._hidden": "isShowLoadButton" } }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"!isLoading; else preloader\">\r\n <ng-container *transloco=\"let t\">\r\n <div *ngIf=\"file; else buttonTemplate\" class=\"file\">\r\n <div\r\n class=\"icon\"\r\n [style.backgroundColor]=\"color\"\r\n >\r\n {{ file.extension | uppercase }}\r\n </div>\r\n <div class=\"info\">\r\n <div\r\n class=\"title\"\r\n attr.data-placeholder=\"{{ t('FILE_TITLE') }}...\"\r\n [innerHTML]=\"title\"\r\n [attr.contenteditable]=\"!readOnly\"\r\n (paste)=\"onTitlePaste($event)\"\r\n (keydown)=\"onPreventEnter($event)\"\r\n (keyup)=\"onTitleChange($event)\"\r\n ></div>\r\n <div *ngIf=\"file.size; let size\" class=\"size\">{{ size | fileSize }}</div>\r\n </div>\r\n <a\r\n class=\"download\"\r\n [href]=\"file.url\"\r\n target=\"_blank\"\r\n download\r\n >\r\n <cui-svg icon=\"cuiIconChevronDownSm\" />\r\n </a>\r\n </div>\r\n <ng-template #buttonTemplate>\r\n <button\r\n [class]=\"['select-btn', this.api.styles.button]\"\r\n (click)=\"onSelectFile()\"\r\n type=\"button\"\r\n >\r\n <cui-svg icon=\"cuiIconPaperclipSm\" />\r\n {{ buttonContent }}\r\n </button>\r\n </ng-template>\r\n </ng-container>\r\n</ng-container>\r\n\r\n<ng-template #preloader>\r\n <div class=\"wrapper\">\r\n <div class=\"preloader\"></div>\r\n </div>\r\n</ng-template>\r\n\r\n", styles: [":host{padding-top:6px;padding-bottom:6px;font-weight:400;font-size:14px;line-height:20px;font-family:var(--cui-main-font);display:block}:host._hidden{display:none}.file{padding:10px 12px;display:flex;justify-content:space-between;align-items:center;gap:8px;border-radius:10px;border:1px solid var(--cui-base-200);background-color:var(--cui-base-10)}.info{display:flex;flex-direction:column;gap:2px;width:85%}.icon{padding:6px 2px;font-weight:500;font-size:12px;line-height:14px;display:flex;align-items:flex-end;border-radius:8px;width:35px;height:35px;color:var(--cui-gray-0)}.title{font-weight:400;font-size:14px;line-height:20px;outline:none}.size{font-weight:400;font-size:13px;line-height:16px;color:var(--cui-base-500)}.download{padding:6px;margin-left:auto;border-radius:8px;color:var(--cui-base-0);background:var(--cui-base-50)}.wrapper{display:flex;flex-direction:column;margin-bottom:10px;border:1px solid var(--cui-base-200);border-radius:10px;min-height:50px;background-color:var(--cui-base-0)}.wrapper._loaded{min-height:auto}.preloader{width:30px;height:30px;border-radius:50%;background-size:cover;margin:auto;position:relative;background-position:center center}@keyframes preloader-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preloader:after{content:\"\";position:absolute;z-index:3;width:30px;height:30px;border-radius:50%;border:2px solid var(--cui-base-200);border-top-color:var(--cui-blue-600);left:50%;top:50%;margin-top:-15px;margin-left:-15px;animation:preloader-spin 2s infinite linear;box-sizing:border-box}.title[data-placeholder]:empty:before{content:attr(data-placeholder);position:absolute;color:var(--cui-base-400)}.select-btn{display:flex;align-items:center;justify-content:center;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CuiSvgModule }, { kind: "component", type: CuiSvgComponent, selector: "cui-svg[icon]", inputs: ["width", "height", "strokeWidth", "color", "icon"] }, { kind: "pipe", type: FileSizePipe, name: "fileSize" }, { kind: "ngmodule", type: FormsModule }, { kind: "pipe", type: UpperCasePipe, name: "uppercase" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5198
|
+
}
|
|
5199
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorAttachesToolComponent, decorators: [{
|
|
5200
|
+
type: Component,
|
|
5201
|
+
args: [{ standalone: true, imports: [CuiSvgModule, FileSizePipe, FormsModule, UpperCasePipe, NgIf, TranslocoDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
5202
|
+
'[class._hidden]': 'isShowLoadButton'
|
|
5203
|
+
}, template: "<ng-container *ngIf=\"!isLoading; else preloader\">\r\n <ng-container *transloco=\"let t\">\r\n <div *ngIf=\"file; else buttonTemplate\" class=\"file\">\r\n <div\r\n class=\"icon\"\r\n [style.backgroundColor]=\"color\"\r\n >\r\n {{ file.extension | uppercase }}\r\n </div>\r\n <div class=\"info\">\r\n <div\r\n class=\"title\"\r\n attr.data-placeholder=\"{{ t('FILE_TITLE') }}...\"\r\n [innerHTML]=\"title\"\r\n [attr.contenteditable]=\"!readOnly\"\r\n (paste)=\"onTitlePaste($event)\"\r\n (keydown)=\"onPreventEnter($event)\"\r\n (keyup)=\"onTitleChange($event)\"\r\n ></div>\r\n <div *ngIf=\"file.size; let size\" class=\"size\">{{ size | fileSize }}</div>\r\n </div>\r\n <a\r\n class=\"download\"\r\n [href]=\"file.url\"\r\n target=\"_blank\"\r\n download\r\n >\r\n <cui-svg icon=\"cuiIconChevronDownSm\" />\r\n </a>\r\n </div>\r\n <ng-template #buttonTemplate>\r\n <button\r\n [class]=\"['select-btn', this.api.styles.button]\"\r\n (click)=\"onSelectFile()\"\r\n type=\"button\"\r\n >\r\n <cui-svg icon=\"cuiIconPaperclipSm\" />\r\n {{ buttonContent }}\r\n </button>\r\n </ng-template>\r\n </ng-container>\r\n</ng-container>\r\n\r\n<ng-template #preloader>\r\n <div class=\"wrapper\">\r\n <div class=\"preloader\"></div>\r\n </div>\r\n</ng-template>\r\n\r\n", styles: [":host{padding-top:6px;padding-bottom:6px;font-weight:400;font-size:14px;line-height:20px;font-family:var(--cui-main-font);display:block}:host._hidden{display:none}.file{padding:10px 12px;display:flex;justify-content:space-between;align-items:center;gap:8px;border-radius:10px;border:1px solid var(--cui-base-200);background-color:var(--cui-base-10)}.info{display:flex;flex-direction:column;gap:2px;width:85%}.icon{padding:6px 2px;font-weight:500;font-size:12px;line-height:14px;display:flex;align-items:flex-end;border-radius:8px;width:35px;height:35px;color:var(--cui-gray-0)}.title{font-weight:400;font-size:14px;line-height:20px;outline:none}.size{font-weight:400;font-size:13px;line-height:16px;color:var(--cui-base-500)}.download{padding:6px;margin-left:auto;border-radius:8px;color:var(--cui-base-0);background:var(--cui-base-50)}.wrapper{display:flex;flex-direction:column;margin-bottom:10px;border:1px solid var(--cui-base-200);border-radius:10px;min-height:50px;background-color:var(--cui-base-0)}.wrapper._loaded{min-height:auto}.preloader{width:30px;height:30px;border-radius:50%;background-size:cover;margin:auto;position:relative;background-position:center center}@keyframes preloader-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preloader:after{content:\"\";position:absolute;z-index:3;width:30px;height:30px;border-radius:50%;border:2px solid var(--cui-base-200);border-top-color:var(--cui-blue-600);left:50%;top:50%;margin-top:-15px;margin-left:-15px;animation:preloader-spin 2s infinite linear;box-sizing:border-box}.title[data-placeholder]:empty:before{content:attr(data-placeholder);position:absolute;color:var(--cui-base-400)}.select-btn{display:flex;align-items:center;justify-content:center;width:100%}\n"] }]
|
|
5204
|
+
}], propDecorators: { file: [{
|
|
5205
|
+
type: Input,
|
|
5206
|
+
args: [{ required: true }]
|
|
5207
|
+
}], title: [{
|
|
5208
|
+
type: Input,
|
|
5209
|
+
args: [{ required: true }]
|
|
5210
|
+
}] } });
|
|
5211
|
+
|
|
5212
|
+
const EDITOR_ATTACHES_TOOL_SELECTOR = 'cc-editor-attaches-tool';
|
|
5213
|
+
|
|
5214
|
+
class EditorImageToolComponent extends EditorToolComponent {
|
|
5215
|
+
constructor() {
|
|
5216
|
+
super(...arguments);
|
|
5217
|
+
this.isLoaded = signal(false);
|
|
5218
|
+
this.tunesSignal = signal({});
|
|
5219
|
+
}
|
|
5220
|
+
set tunes(tunes) {
|
|
5221
|
+
this.tunesSignal.set(tunes);
|
|
5222
|
+
}
|
|
5223
|
+
get isShowLoadButton() {
|
|
5224
|
+
return !this.image && !this.isCaptionShown && !this.isLoading;
|
|
5225
|
+
}
|
|
5226
|
+
onPreventEnter(event) {
|
|
5227
|
+
if (this.checkKey(event)) {
|
|
5228
|
+
return;
|
|
5229
|
+
}
|
|
5230
|
+
event.stopPropagation();
|
|
5231
|
+
}
|
|
5232
|
+
checkKey(event) {
|
|
5233
|
+
return (event.key !== 'Backspace' && event.key !== 'Enter') || event.shiftKey;
|
|
5234
|
+
}
|
|
5235
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorImageToolComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
5236
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: EditorImageToolComponent, isStandalone: true, selector: "ng-component", inputs: { image: "image", tunes: "tunes" }, host: { properties: { "class._hidden": "isShowLoadButton" } }, usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"!isLoading; else preloader\">\r\n <ng-container *transloco=\"let t\">\r\n <ng-container *ngIf=\"image; else buttonTemplate\">\r\n <div\r\n class=\"wrapper\"\r\n [ngClass]=\"tunesSignal()\"\r\n [class._loaded]=\"isLoaded()\"\r\n >\r\n <img\r\n class=\"image\"\r\n [src]=\"image\"\r\n alt=\"Image\"\r\n />\r\n </div>\r\n <div\r\n *ngIf=\"isCaptionShown\"\r\n class=\"caption cdx-input\"\r\n [attr.contenteditable]=\"!readOnly\"\r\n attr.data-placeholder=\"{{ t('CAPTION') }}...\"\r\n (paste)=\"onTitlePaste($event)\"\r\n (keydown)=\"onPreventEnter($event)\"\r\n (keyup)=\"onTitleChange($event)\"\r\n [innerHTML]=\"caption\"\r\n ></div>\r\n </ng-container>\r\n <ng-template #buttonTemplate>\r\n <button\r\n #button\r\n type=\"button\"\r\n [class]=\"['select-btn', this.api.styles.button]\"\r\n (click)=\"onSelectFile()\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 20 20\"\r\n fill=\"none\"\r\n >\r\n <path\r\n d=\"M12.5013 4.1665H7.5013C5.66035 4.1665 4.16797 5.65889 4.16797 7.49984V12.4998C4.16797 14.3408 5.66035 15.8332 7.5013 15.8332H12.5013C14.3423 15.8332 15.8346 14.3408 15.8346 12.4998V7.49984C15.8346 5.65889 14.3423 4.1665 12.5013 4.1665Z\"\r\n stroke=\"#121315\"\r\n stroke-width=\"1.66667\"\r\n />\r\n <path\r\n d=\"M4.28125 12.7665L7.24033 9.63825C7.52263 9.33617 7.90546 9.1665 8.30463 9.1665C8.70377 9.1665 9.0866 9.33617 9.36893 9.63825L12.8208 13.3332M11.3154 11.7218L12.5092 10.444C12.7914 10.1419 13.1743 9.97217 13.5734 9.97217C13.9726 9.97217 14.3554 10.1419 14.6378 10.444L15.699 11.636\"\r\n stroke=\"#121315\"\r\n stroke-width=\"1.66667\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M11.4805 7.77783H11.4879\"\r\n stroke=\"#121315\"\r\n stroke-width=\"1.66667\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n {{ buttonContent }}\r\n </button>\r\n </ng-template>\r\n </ng-container>\r\n</ng-container>\r\n<ng-template #preloader>\r\n <div class=\"wrapper\">\r\n <div class=\"preloader\">\r\n <img\r\n *ngIf=\"preview\"\r\n class=\"preloader__image\"\r\n [src]=\"preview\"\r\n alt=\"Preloader\"\r\n />\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n", styles: [":host{padding-top:6px;padding-bottom:6px;font-weight:400;font-size:14px;line-height:20px;font-family:var(--cui-main-font);display:block}:host ::ng-deep .cdx-input{border:1px solid var(--cui-base-200);background:transparent;box-shadow:none}:host ::ng-deep .play{margin:auto}:host ::ng-deep .play path{fill:var(--cui-base-0);stroke:var(--cui-base-300)}:host._hidden{display:none}.image{display:block;max-width:100%;width:fit-content;height:250px}.wrapper{display:flex;flex-direction:column;margin-bottom:10px;border:1px solid var(--cui-base-200);border-radius:3px;min-height:200px;background-color:var(--cui-base-0)}.wrapper._loaded{min-height:auto}.wrapper.stretched .image{width:100%;height:auto}.wrapper.center .image{margin:auto}.preloader{width:50px;height:50px;border-radius:50%;background-size:cover;margin:auto;position:relative;background-color:var(--cui-base-200);background-position:center center}@keyframes preloader-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preloader__image{width:50px;height:50px;border-radius:50%}.preloader:after{content:\"\";position:absolute;z-index:3;width:60px;height:60px;border-radius:50%;border:2px solid var(--cui-base-200);border-top-color:var(--cui-blue-600);left:50%;top:50%;margin-top:-30px;margin-left:-30px;animation:preloader-spin 2s infinite linear;box-sizing:border-box}.caption[data-placeholder]:empty:before{content:attr(data-placeholder);position:absolute;color:var(--cui-base-400)}.select-btn{display:flex;align-items:center;justify-content:center;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CuiSvgModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5237
|
+
}
|
|
5238
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorImageToolComponent, decorators: [{
|
|
5239
|
+
type: Component,
|
|
5240
|
+
args: [{ standalone: true, imports: [CuiSvgModule, FormsModule, NgClass, NgIf, TranslocoDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
5241
|
+
'[class._hidden]': 'isShowLoadButton'
|
|
5242
|
+
}, template: "<ng-container *ngIf=\"!isLoading; else preloader\">\r\n <ng-container *transloco=\"let t\">\r\n <ng-container *ngIf=\"image; else buttonTemplate\">\r\n <div\r\n class=\"wrapper\"\r\n [ngClass]=\"tunesSignal()\"\r\n [class._loaded]=\"isLoaded()\"\r\n >\r\n <img\r\n class=\"image\"\r\n [src]=\"image\"\r\n alt=\"Image\"\r\n />\r\n </div>\r\n <div\r\n *ngIf=\"isCaptionShown\"\r\n class=\"caption cdx-input\"\r\n [attr.contenteditable]=\"!readOnly\"\r\n attr.data-placeholder=\"{{ t('CAPTION') }}...\"\r\n (paste)=\"onTitlePaste($event)\"\r\n (keydown)=\"onPreventEnter($event)\"\r\n (keyup)=\"onTitleChange($event)\"\r\n [innerHTML]=\"caption\"\r\n ></div>\r\n </ng-container>\r\n <ng-template #buttonTemplate>\r\n <button\r\n #button\r\n type=\"button\"\r\n [class]=\"['select-btn', this.api.styles.button]\"\r\n (click)=\"onSelectFile()\"\r\n >\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"20\"\r\n height=\"20\"\r\n viewBox=\"0 0 20 20\"\r\n fill=\"none\"\r\n >\r\n <path\r\n d=\"M12.5013 4.1665H7.5013C5.66035 4.1665 4.16797 5.65889 4.16797 7.49984V12.4998C4.16797 14.3408 5.66035 15.8332 7.5013 15.8332H12.5013C14.3423 15.8332 15.8346 14.3408 15.8346 12.4998V7.49984C15.8346 5.65889 14.3423 4.1665 12.5013 4.1665Z\"\r\n stroke=\"#121315\"\r\n stroke-width=\"1.66667\"\r\n />\r\n <path\r\n d=\"M4.28125 12.7665L7.24033 9.63825C7.52263 9.33617 7.90546 9.1665 8.30463 9.1665C8.70377 9.1665 9.0866 9.33617 9.36893 9.63825L12.8208 13.3332M11.3154 11.7218L12.5092 10.444C12.7914 10.1419 13.1743 9.97217 13.5734 9.97217C13.9726 9.97217 14.3554 10.1419 14.6378 10.444L15.699 11.636\"\r\n stroke=\"#121315\"\r\n stroke-width=\"1.66667\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n <path\r\n d=\"M11.4805 7.77783H11.4879\"\r\n stroke=\"#121315\"\r\n stroke-width=\"1.66667\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n {{ buttonContent }}\r\n </button>\r\n </ng-template>\r\n </ng-container>\r\n</ng-container>\r\n<ng-template #preloader>\r\n <div class=\"wrapper\">\r\n <div class=\"preloader\">\r\n <img\r\n *ngIf=\"preview\"\r\n class=\"preloader__image\"\r\n [src]=\"preview\"\r\n alt=\"Preloader\"\r\n />\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n", styles: [":host{padding-top:6px;padding-bottom:6px;font-weight:400;font-size:14px;line-height:20px;font-family:var(--cui-main-font);display:block}:host ::ng-deep .cdx-input{border:1px solid var(--cui-base-200);background:transparent;box-shadow:none}:host ::ng-deep .play{margin:auto}:host ::ng-deep .play path{fill:var(--cui-base-0);stroke:var(--cui-base-300)}:host._hidden{display:none}.image{display:block;max-width:100%;width:fit-content;height:250px}.wrapper{display:flex;flex-direction:column;margin-bottom:10px;border:1px solid var(--cui-base-200);border-radius:3px;min-height:200px;background-color:var(--cui-base-0)}.wrapper._loaded{min-height:auto}.wrapper.stretched .image{width:100%;height:auto}.wrapper.center .image{margin:auto}.preloader{width:50px;height:50px;border-radius:50%;background-size:cover;margin:auto;position:relative;background-color:var(--cui-base-200);background-position:center center}@keyframes preloader-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preloader__image{width:50px;height:50px;border-radius:50%}.preloader:after{content:\"\";position:absolute;z-index:3;width:60px;height:60px;border-radius:50%;border:2px solid var(--cui-base-200);border-top-color:var(--cui-blue-600);left:50%;top:50%;margin-top:-30px;margin-left:-30px;animation:preloader-spin 2s infinite linear;box-sizing:border-box}.caption[data-placeholder]:empty:before{content:attr(data-placeholder);position:absolute;color:var(--cui-base-400)}.select-btn{display:flex;align-items:center;justify-content:center;width:100%}\n"] }]
|
|
5243
|
+
}], propDecorators: { image: [{
|
|
5244
|
+
type: Input,
|
|
5245
|
+
args: [{ required: true }]
|
|
5246
|
+
}], tunes: [{
|
|
5247
|
+
type: Input
|
|
5248
|
+
}] } });
|
|
5249
|
+
|
|
5250
|
+
const EDITOR_IMAGE_TOOL_SELECTOR = 'cc-editor-image-tool';
|
|
5251
|
+
|
|
5252
|
+
class EditorVideoToolComponent extends EditorToolComponent {
|
|
5253
|
+
constructor() {
|
|
5254
|
+
super(...arguments);
|
|
5255
|
+
this.isLoaded = signal(false);
|
|
5256
|
+
}
|
|
5257
|
+
get isShowLoadButton() {
|
|
5258
|
+
return !this.video && !this.isCaptionShown && !this.isLoading;
|
|
5259
|
+
}
|
|
5260
|
+
onPlay() {
|
|
5261
|
+
this.isLoaded.set(true);
|
|
5262
|
+
}
|
|
5263
|
+
onPreventEnter(event) {
|
|
5264
|
+
if (this.checkKey(event)) {
|
|
5265
|
+
return;
|
|
5266
|
+
}
|
|
5267
|
+
event.stopPropagation();
|
|
5268
|
+
}
|
|
5269
|
+
checkKey(event) {
|
|
5270
|
+
return (event.key !== 'Backspace' && event.key !== 'Enter') || event.shiftKey;
|
|
5271
|
+
}
|
|
5272
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorVideoToolComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
5273
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: EditorVideoToolComponent, isStandalone: true, selector: "ng-component", inputs: { video: "video" }, host: { properties: { "class._hidden": "isShowLoadButton" } }, usesInheritance: true, ngImport: i0, template: "<ng-container *transloco=\"let t\">\r\n <ng-container *ngIf=\"!isLoading; else preloader\">\r\n <ng-container *ngIf=\"video; else buttonTemplate\">\r\n <div\r\n class=\"wrapper\"\r\n [class._loaded]=\"isLoaded()\"\r\n >\r\n <video\r\n *ngIf=\"isLoaded(); else playButtonTemplate\"\r\n class=\"video\"\r\n [src]=\"video\"\r\n controls\r\n autoplay\r\n ></video>\r\n\r\n <ng-template #playButtonTemplate>\r\n <button\r\n type=\"button\"\r\n class=\"play\"\r\n (click)=\"onPlay()\"\r\n >\r\n <cui-svg\r\n class=\"play\"\r\n icon=\"cuiIconPlayCircleSm\"\r\n [height]=\"72\"\r\n [width]=\"72\"\r\n [strokeWidth]=\"0.5\"\r\n />\r\n </button>\r\n </ng-template>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"isCaptionShown\"\r\n class=\"caption cdx-input\"\r\n [attr.contenteditable]=\"!readOnly\"\r\n attr.data-placeholder=\"{{ t('CAPTION') }}...\"\r\n (paste)=\"onTitlePaste($event)\"\r\n (keydown)=\"onPreventEnter($event)\"\r\n (keyup)=\"onTitleChange($event)\"\r\n [innerHTML]=\"caption\"\r\n ></div>\r\n </ng-container>\r\n\r\n <ng-template #buttonTemplate>\r\n <button\r\n type=\"button\"\r\n [class]=\"['select-btn', this.api.styles.button]\"\r\n (click)=\"onSelectFile()\"\r\n >\r\n <cui-svg icon=\"cuiIconPlayCircle\" />\r\n {{ buttonContent }}\r\n </button>\r\n </ng-template>\r\n </ng-container>\r\n</ng-container>\r\n\r\n\r\n<ng-template #preloader>\r\n <div class=\"wrapper\">\r\n <div class=\"preloader\">\r\n <img\r\n *ngIf=\"preview\"\r\n class=\"preloader__image\"\r\n [src]=\"preview\"\r\n alt=\"Preloader\"\r\n />\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n\r\n", styles: [":host{font-weight:400;font-size:14px;line-height:20px;padding-top:6px;padding-bottom:6px;font-family:var(--cui-main-font);display:block}:host ::ng-deep .cdx-input{border:1px solid var(--cui-base-200);background:transparent;box-shadow:none}:host ::ng-deep .play{margin:auto}:host ::ng-deep .play path{fill:var(--cui-base-0);stroke:var(--cui-base-300)}:host._hidden{display:none}.wrapper{display:flex;flex-direction:column;margin-bottom:10px;border:1px solid var(--cui-base-200);border-radius:3px;min-height:200px;background-color:var(--cui-base-0)}.wrapper._loaded{min-height:auto}.video{display:block;max-width:100%}.preloader{width:50px;height:50px;border-radius:50%;background-size:cover;margin:auto;position:relative;background-color:var(--cui-base-200);background-position:center center}@keyframes preloader-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preloader__image{width:50px;height:50px;border-radius:50%}.preloader:after{content:\"\";position:absolute;z-index:3;width:60px;height:60px;border-radius:50%;border:2px solid var(--cui-base-200);border-top-color:var(--cui-blue-600);left:50%;top:50%;margin-top:-30px;margin-left:-30px;animation:preloader-spin 2s infinite linear;box-sizing:border-box}.caption[data-placeholder]:empty:before{content:attr(data-placeholder);position:absolute;color:var(--cui-base-400)}.select-btn{display:flex;align-items:center;justify-content:center;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CuiSvgModule }, { kind: "component", type: CuiSvgComponent, selector: "cui-svg[icon]", inputs: ["width", "height", "strokeWidth", "color", "icon"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5274
|
+
}
|
|
5275
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditorVideoToolComponent, decorators: [{
|
|
5276
|
+
type: Component,
|
|
5277
|
+
args: [{ standalone: true, imports: [CuiSvgModule, FormsModule, NgIf, TranslocoDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
5278
|
+
'[class._hidden]': 'isShowLoadButton'
|
|
5279
|
+
}, template: "<ng-container *transloco=\"let t\">\r\n <ng-container *ngIf=\"!isLoading; else preloader\">\r\n <ng-container *ngIf=\"video; else buttonTemplate\">\r\n <div\r\n class=\"wrapper\"\r\n [class._loaded]=\"isLoaded()\"\r\n >\r\n <video\r\n *ngIf=\"isLoaded(); else playButtonTemplate\"\r\n class=\"video\"\r\n [src]=\"video\"\r\n controls\r\n autoplay\r\n ></video>\r\n\r\n <ng-template #playButtonTemplate>\r\n <button\r\n type=\"button\"\r\n class=\"play\"\r\n (click)=\"onPlay()\"\r\n >\r\n <cui-svg\r\n class=\"play\"\r\n icon=\"cuiIconPlayCircleSm\"\r\n [height]=\"72\"\r\n [width]=\"72\"\r\n [strokeWidth]=\"0.5\"\r\n />\r\n </button>\r\n </ng-template>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"isCaptionShown\"\r\n class=\"caption cdx-input\"\r\n [attr.contenteditable]=\"!readOnly\"\r\n attr.data-placeholder=\"{{ t('CAPTION') }}...\"\r\n (paste)=\"onTitlePaste($event)\"\r\n (keydown)=\"onPreventEnter($event)\"\r\n (keyup)=\"onTitleChange($event)\"\r\n [innerHTML]=\"caption\"\r\n ></div>\r\n </ng-container>\r\n\r\n <ng-template #buttonTemplate>\r\n <button\r\n type=\"button\"\r\n [class]=\"['select-btn', this.api.styles.button]\"\r\n (click)=\"onSelectFile()\"\r\n >\r\n <cui-svg icon=\"cuiIconPlayCircle\" />\r\n {{ buttonContent }}\r\n </button>\r\n </ng-template>\r\n </ng-container>\r\n</ng-container>\r\n\r\n\r\n<ng-template #preloader>\r\n <div class=\"wrapper\">\r\n <div class=\"preloader\">\r\n <img\r\n *ngIf=\"preview\"\r\n class=\"preloader__image\"\r\n [src]=\"preview\"\r\n alt=\"Preloader\"\r\n />\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n\r\n", styles: [":host{font-weight:400;font-size:14px;line-height:20px;padding-top:6px;padding-bottom:6px;font-family:var(--cui-main-font);display:block}:host ::ng-deep .cdx-input{border:1px solid var(--cui-base-200);background:transparent;box-shadow:none}:host ::ng-deep .play{margin:auto}:host ::ng-deep .play path{fill:var(--cui-base-0);stroke:var(--cui-base-300)}:host._hidden{display:none}.wrapper{display:flex;flex-direction:column;margin-bottom:10px;border:1px solid var(--cui-base-200);border-radius:3px;min-height:200px;background-color:var(--cui-base-0)}.wrapper._loaded{min-height:auto}.video{display:block;max-width:100%}.preloader{width:50px;height:50px;border-radius:50%;background-size:cover;margin:auto;position:relative;background-color:var(--cui-base-200);background-position:center center}@keyframes preloader-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.preloader__image{width:50px;height:50px;border-radius:50%}.preloader:after{content:\"\";position:absolute;z-index:3;width:60px;height:60px;border-radius:50%;border:2px solid var(--cui-base-200);border-top-color:var(--cui-blue-600);left:50%;top:50%;margin-top:-30px;margin-left:-30px;animation:preloader-spin 2s infinite linear;box-sizing:border-box}.caption[data-placeholder]:empty:before{content:attr(data-placeholder);position:absolute;color:var(--cui-base-400)}.select-btn{display:flex;align-items:center;justify-content:center;width:100%}\n"] }]
|
|
5280
|
+
}], propDecorators: { video: [{
|
|
5281
|
+
type: Input,
|
|
5282
|
+
args: [{ required: true }]
|
|
5283
|
+
}] } });
|
|
5284
|
+
|
|
5285
|
+
const EDITOR_VIDEO_TOOL_SELECTOR = 'cc-editor-video-tool';
|
|
5286
|
+
|
|
5287
|
+
function createSelect(marker, tooltip) {
|
|
5288
|
+
const select = document.createElement(MARKER_SELECT_SELECTOR);
|
|
5289
|
+
const button = tooltip.querySelector('.edit');
|
|
5290
|
+
select.space = 8;
|
|
5291
|
+
select.target = button;
|
|
5292
|
+
select.addEventListener('toolClick', (event) => onToolClick(marker, tooltip, event));
|
|
5293
|
+
return select;
|
|
5294
|
+
}
|
|
5295
|
+
function createToolModal(marker, tooltip) {
|
|
5296
|
+
const toolModal = document.createElement(MARKER_MODAL_SELECTOR);
|
|
5297
|
+
const button = tooltip.querySelector('.edit');
|
|
5298
|
+
const toolId = marker.dataset['id'];
|
|
5299
|
+
const toolType = marker.dataset['type'];
|
|
5300
|
+
toolModal.title = marker.innerText;
|
|
5301
|
+
toolModal.target = button;
|
|
5302
|
+
toolModal.isTool = true;
|
|
5303
|
+
toolModal.tool = {
|
|
5304
|
+
id: toolId,
|
|
5305
|
+
type: toolType
|
|
5306
|
+
};
|
|
5307
|
+
toolModal.space = 8;
|
|
5308
|
+
toolModal.addEventListener('saveClicked', (event) => {
|
|
5309
|
+
const customEvent = event;
|
|
5310
|
+
const data = customEvent.detail.data;
|
|
5311
|
+
if (data && typeof data !== 'string') {
|
|
5312
|
+
marker.setAttribute('data-id', data.id);
|
|
5313
|
+
marker.setAttribute('data-type', data.type);
|
|
5314
|
+
}
|
|
5315
|
+
marker.innerHTML = customEvent.detail.title;
|
|
5316
|
+
tooltip.remove();
|
|
5317
|
+
});
|
|
5318
|
+
toolModal.addEventListener('cancelClicked', () => {
|
|
5319
|
+
tooltip.remove();
|
|
5320
|
+
});
|
|
5321
|
+
return toolModal;
|
|
5322
|
+
}
|
|
5323
|
+
function onToolClick(marker, tooltip, event) {
|
|
5324
|
+
event.stopPropagation();
|
|
5325
|
+
const customEvent = event;
|
|
5326
|
+
const tool = customEvent.detail;
|
|
5327
|
+
marker.dataset['id'] = tool.id;
|
|
5328
|
+
tooltip.remove();
|
|
5329
|
+
}
|
|
5330
|
+
|
|
5331
|
+
function removeElementTagWrapper(element) {
|
|
5332
|
+
const parent = element.parentElement;
|
|
5333
|
+
const innerElementNodes = element.childNodes;
|
|
5334
|
+
let node;
|
|
5335
|
+
while (innerElementNodes.length) {
|
|
5336
|
+
node = innerElementNodes.item(0);
|
|
5337
|
+
parent?.insertBefore(node, element);
|
|
5338
|
+
}
|
|
5339
|
+
element.remove();
|
|
5340
|
+
}
|
|
5341
|
+
|
|
5342
|
+
const tooltipMap = {
|
|
5343
|
+
MARK: createMarkerTooltip,
|
|
5344
|
+
A: createLinkTooltip
|
|
5345
|
+
};
|
|
5346
|
+
function createMarkerTooltip(marker) {
|
|
5347
|
+
const tooltip = createTooltip(marker, marker.innerText);
|
|
5348
|
+
setTimeout(() => {
|
|
5349
|
+
const select = createToolModal(marker, tooltip);
|
|
5350
|
+
tooltip.append(select);
|
|
5351
|
+
});
|
|
5352
|
+
return tooltip;
|
|
5353
|
+
}
|
|
5354
|
+
function createLinkTooltip(link) {
|
|
5355
|
+
const linkElement = link;
|
|
5356
|
+
const options = ['copy', 'edit', 'delete'];
|
|
5357
|
+
const linkUrl = linkElement.href;
|
|
5358
|
+
const tooltip = createTooltip(linkElement, linkUrl, options);
|
|
5359
|
+
tooltip.addEventListener('copyClicked', () => {
|
|
5360
|
+
window?.navigator.clipboard.writeText(linkUrl);
|
|
5361
|
+
});
|
|
5362
|
+
setTimeout(() => {
|
|
5363
|
+
const linkModal = createLinkModal(tooltip, linkElement);
|
|
5364
|
+
tooltip.append(linkModal);
|
|
5365
|
+
});
|
|
5366
|
+
return tooltip;
|
|
5367
|
+
}
|
|
5368
|
+
function createTooltip(element, title, options) {
|
|
5369
|
+
const tooltip = document.createElement(EDITOR_TOOLTIP_SELECTOR);
|
|
5370
|
+
tooltip.title = title;
|
|
5371
|
+
if (options) {
|
|
5372
|
+
tooltip.options = options;
|
|
5373
|
+
}
|
|
5374
|
+
tooltip.addEventListener('deleteClicked', (event) => {
|
|
5375
|
+
event.stopPropagation();
|
|
5376
|
+
removeElementTagWrapper(element);
|
|
5377
|
+
tooltip.remove();
|
|
5378
|
+
});
|
|
5379
|
+
return tooltip;
|
|
5380
|
+
}
|
|
5381
|
+
|
|
5382
|
+
var CuiFileUploaderStatus;
|
|
5383
|
+
(function (CuiFileUploaderStatus) {
|
|
5384
|
+
CuiFileUploaderStatus["Loading"] = "loading";
|
|
5385
|
+
CuiFileUploaderStatus["Completed"] = "completed";
|
|
5386
|
+
})(CuiFileUploaderStatus || (CuiFileUploaderStatus = {}));
|
|
5387
|
+
class CuiFileUploader {
|
|
5388
|
+
constructor(config, onUpload, onError) {
|
|
5389
|
+
this.REQUEST_METHOD = 'POST';
|
|
5390
|
+
this.selectFile = ({ fileSelected }) => {
|
|
5391
|
+
const input = document.createElement('input');
|
|
5392
|
+
const types = this.config?.types || '*';
|
|
5393
|
+
input.type = 'file';
|
|
5394
|
+
input.accept = types;
|
|
5395
|
+
input.onchange = () => {
|
|
5396
|
+
const files = input.files;
|
|
5397
|
+
if (!files?.length) {
|
|
5398
|
+
return;
|
|
5399
|
+
}
|
|
5400
|
+
this.getFile(files, fileSelected);
|
|
5401
|
+
};
|
|
5402
|
+
input.click();
|
|
5403
|
+
};
|
|
5404
|
+
this.config = config;
|
|
5405
|
+
this.onUpload = onUpload;
|
|
5406
|
+
this.onError = onError;
|
|
5407
|
+
}
|
|
5408
|
+
getFile(files, fileSelected) {
|
|
5409
|
+
const file = files.item(0);
|
|
5410
|
+
if (!file) {
|
|
5411
|
+
return;
|
|
5412
|
+
}
|
|
5413
|
+
fileSelected(file);
|
|
5414
|
+
}
|
|
5415
|
+
uploadFile(file) {
|
|
5416
|
+
const formData = new FormData();
|
|
5417
|
+
const formField = this.config.field || 'file';
|
|
5418
|
+
formData.append(formField, file);
|
|
5419
|
+
if (!this.config.endpoint) {
|
|
5420
|
+
return;
|
|
5421
|
+
}
|
|
5422
|
+
this.config.load(CuiFileUploaderStatus.Loading);
|
|
5423
|
+
const upload = fetch(this.config.endpoint, {
|
|
5424
|
+
headers: this.config.additionalRequestHeaders,
|
|
5425
|
+
method: this.REQUEST_METHOD,
|
|
5426
|
+
body: formData
|
|
5427
|
+
});
|
|
5428
|
+
upload
|
|
5429
|
+
.then((response) => response.json())
|
|
5430
|
+
.then((response) => this.onUpload(response, file))
|
|
5431
|
+
.catch(() => this.onError())
|
|
5432
|
+
.finally(() => this.config.load(CuiFileUploaderStatus.Completed));
|
|
5433
|
+
}
|
|
5434
|
+
uploadByUrl(url) {
|
|
5435
|
+
this.onUpload({ success: 1, file: { url } });
|
|
5436
|
+
}
|
|
5437
|
+
}
|
|
5438
|
+
|
|
5439
|
+
function recalculateIndexes(blocksApi) {
|
|
5440
|
+
if (!blocksApi) {
|
|
5441
|
+
return;
|
|
5442
|
+
}
|
|
5443
|
+
const blocks = blocksApi.getBlocksCount();
|
|
5444
|
+
let index = 0;
|
|
5445
|
+
for (let i = 0; i < blocks; i++) {
|
|
5446
|
+
const block = blocksApi.getBlockByIndex(i);
|
|
5447
|
+
if (!block) {
|
|
5448
|
+
continue;
|
|
5449
|
+
}
|
|
5450
|
+
const blockElement = block?.holder;
|
|
5451
|
+
const subblocks = blockElement.querySelectorAll('.' + COMBINED_TEXT_BLOCK_PART);
|
|
5452
|
+
blockElement.setAttribute('data-index', String(index));
|
|
5453
|
+
if (!subblocks.length) {
|
|
5454
|
+
index++;
|
|
5455
|
+
continue;
|
|
5456
|
+
}
|
|
5457
|
+
subblocks.forEach((subblock) => {
|
|
5458
|
+
const subBlockIndex = subblock.getAttribute('data-index');
|
|
5459
|
+
const indexAsNumber = subBlockIndex ? Number(subBlockIndex) : null;
|
|
5460
|
+
if (indexAsNumber !== null && indexAsNumber === index) {
|
|
5461
|
+
index++;
|
|
5462
|
+
return;
|
|
5463
|
+
}
|
|
5464
|
+
subblock.setAttribute('data-index', String(index));
|
|
5465
|
+
index++;
|
|
5466
|
+
});
|
|
5467
|
+
}
|
|
5468
|
+
}
|
|
5469
|
+
|
|
5470
|
+
const unsplittableTags = { mark: true, a: true };
|
|
5471
|
+
const PART_LENGTH_MEASUREMENT_ERROR = 20;
|
|
5472
|
+
const BR_TAG = '<br>';
|
|
5473
|
+
function splitHTML(input, maxLength = SPLIT_LENGTH) {
|
|
5474
|
+
const parts = [];
|
|
5475
|
+
const tagNames = [];
|
|
5476
|
+
const tags = [];
|
|
5477
|
+
let currentPart = '';
|
|
5478
|
+
let index = 0;
|
|
5479
|
+
// remove specsymbols
|
|
5480
|
+
input = input.replaceAll(' ', ' ');
|
|
5481
|
+
while (input.length > index) {
|
|
5482
|
+
while (currentPart.length < maxLength && input.length > index) {
|
|
5483
|
+
if (checkIsBrTag(input, index)) {
|
|
5484
|
+
// when br tag
|
|
5485
|
+
if (currentPart.length + BR_TAG.length > maxLength) {
|
|
5486
|
+
parts.push(currentPart);
|
|
5487
|
+
currentPart = BR_TAG;
|
|
5488
|
+
}
|
|
5489
|
+
else {
|
|
5490
|
+
currentPart += BR_TAG;
|
|
5491
|
+
}
|
|
5492
|
+
index += BR_TAG.length - 1;
|
|
5493
|
+
}
|
|
5494
|
+
else if (checkIsEndOfTag(input, index)) {
|
|
5495
|
+
// when tag ends
|
|
5496
|
+
const tagName = getEndTag(tagNames.pop());
|
|
5497
|
+
tags.pop();
|
|
5498
|
+
if ((currentPart + tagName).length > maxLength) {
|
|
5499
|
+
parts.push(currentPart);
|
|
5500
|
+
currentPart = '';
|
|
5501
|
+
}
|
|
5502
|
+
else {
|
|
5503
|
+
currentPart += tagName;
|
|
5504
|
+
}
|
|
5505
|
+
index += tagName.length - 1;
|
|
5506
|
+
}
|
|
5507
|
+
else if (input[index] === '<') {
|
|
5508
|
+
// when tag starts
|
|
5509
|
+
const { tag, tagName, newIndex } = getTagAndTagName(input, index);
|
|
5510
|
+
index = newIndex;
|
|
5511
|
+
if (checkIsLengthEnough(currentPart, tag)) {
|
|
5512
|
+
currentPart = switchPartWhenUnclosedTagsExist(tagNames, tags, parts, currentPart);
|
|
5513
|
+
}
|
|
5514
|
+
currentPart += tag;
|
|
5515
|
+
if (!unsplittableTags[tagName]) {
|
|
5516
|
+
tagNames.push(tagName);
|
|
5517
|
+
tags.push(tag);
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
else {
|
|
5521
|
+
// other symbols
|
|
5522
|
+
currentPart += input[index];
|
|
5523
|
+
}
|
|
5524
|
+
index += 1;
|
|
5525
|
+
}
|
|
5526
|
+
currentPart = switchPartWhenUnclosedTagsExist(tagNames, tags, parts, currentPart);
|
|
5527
|
+
}
|
|
5528
|
+
return parts;
|
|
5529
|
+
}
|
|
5530
|
+
function switchPartWhenUnclosedTagsExist(tagNames, tags, parts, currentPart) {
|
|
5531
|
+
if (!tagNames.length) {
|
|
5532
|
+
parts.push(currentPart);
|
|
5533
|
+
return '';
|
|
5534
|
+
}
|
|
5535
|
+
let closeAllTags = '';
|
|
5536
|
+
for (let i = tagNames.length - 1; i >= 0; i -= 1) {
|
|
5537
|
+
closeAllTags += getEndTag(tagNames[i]);
|
|
5538
|
+
}
|
|
5539
|
+
currentPart += closeAllTags;
|
|
5540
|
+
parts.push(currentPart);
|
|
5541
|
+
currentPart = tags.reduce((openTags, tag) => (openTags += tag), '');
|
|
5542
|
+
return currentPart;
|
|
5543
|
+
}
|
|
5544
|
+
function getTagAndTagName(input, index) {
|
|
5545
|
+
let tag = '';
|
|
5546
|
+
let tagName = '';
|
|
5547
|
+
tag += input[index];
|
|
5548
|
+
index += 1;
|
|
5549
|
+
while (input[index] !== ' ' && input[index] !== '>') {
|
|
5550
|
+
tag += input[index];
|
|
5551
|
+
tagName += input[index];
|
|
5552
|
+
index += 1;
|
|
5553
|
+
}
|
|
5554
|
+
while (input[index] !== '>') {
|
|
5555
|
+
tag += input[index];
|
|
5556
|
+
index += 1;
|
|
5557
|
+
}
|
|
5558
|
+
tag += input[index];
|
|
5559
|
+
[tag, index] = getFullTag(input, index, tag, tagName);
|
|
5560
|
+
return { tag, tagName, newIndex: index };
|
|
5561
|
+
}
|
|
5562
|
+
function getFullTag(input, index, tag, tagName) {
|
|
5563
|
+
if (!unsplittableTags[tagName]) {
|
|
5564
|
+
return [tag, index];
|
|
5565
|
+
}
|
|
5566
|
+
let fullTag = tag;
|
|
5567
|
+
index += 1;
|
|
5568
|
+
while (!checkIsEndOfTag(input, index)) {
|
|
5569
|
+
fullTag += input[index];
|
|
5570
|
+
index += 1;
|
|
5571
|
+
}
|
|
5572
|
+
const endTag = getEndTag(tagName);
|
|
5573
|
+
index += endTag.length - 1;
|
|
5574
|
+
return [fullTag + endTag, index];
|
|
5575
|
+
}
|
|
5576
|
+
function checkIsLengthEnough(currentPart, tag) {
|
|
5577
|
+
return currentPart.length + tag.length + PART_LENGTH_MEASUREMENT_ERROR > SPLIT_LENGTH;
|
|
5578
|
+
}
|
|
5579
|
+
function getEndTag(tagName) {
|
|
5580
|
+
return '</' + tagName + '>';
|
|
5581
|
+
}
|
|
5582
|
+
function checkIsEndOfTag(input, index) {
|
|
5583
|
+
return input[index] === '<' && input[index + 1] === '/';
|
|
5584
|
+
}
|
|
5585
|
+
function checkIsBrTag(input, index) {
|
|
5586
|
+
let tag = '';
|
|
5587
|
+
if (input[index] !== '<') {
|
|
5588
|
+
return false;
|
|
5589
|
+
}
|
|
5590
|
+
while (input[index] && input[index] !== '>') {
|
|
5591
|
+
tag += input[index];
|
|
5592
|
+
index += 1;
|
|
5593
|
+
}
|
|
5594
|
+
return tag + '>' === BR_TAG;
|
|
5595
|
+
}
|
|
5596
|
+
|
|
5597
|
+
class CuiImageTool {
|
|
5598
|
+
get Tunes() {
|
|
5599
|
+
return [
|
|
5600
|
+
{
|
|
5601
|
+
name: 'stretched',
|
|
5602
|
+
title: 'Stretch image',
|
|
5603
|
+
toggle: true
|
|
5604
|
+
},
|
|
5605
|
+
{
|
|
5606
|
+
name: 'center',
|
|
5607
|
+
title: 'Center image',
|
|
5608
|
+
toggle: true
|
|
5609
|
+
}
|
|
5610
|
+
];
|
|
5611
|
+
}
|
|
5612
|
+
static get isReadOnlySupported() {
|
|
5613
|
+
return true;
|
|
5614
|
+
}
|
|
5615
|
+
static get toolbox() {
|
|
5616
|
+
return {
|
|
5617
|
+
/* eslint-disable */
|
|
5618
|
+
icon: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
5619
|
+
<path d="M12.5013 4.1665H7.5013C5.66035 4.1665 4.16797 5.65889 4.16797 7.49984V12.4998C4.16797 14.3408 5.66035 15.8332 7.5013 15.8332H12.5013C14.3423 15.8332 15.8346 14.3408 15.8346 12.4998V7.49984C15.8346 5.65889 14.3423 4.1665 12.5013 4.1665Z" stroke="#121315" stroke-width="1.66667"/>
|
|
5620
|
+
<path d="M4.28125 12.7665L7.24033 9.63825C7.52263 9.33617 7.90546 9.1665 8.30463 9.1665C8.70377 9.1665 9.0866 9.33617 9.36893 9.63825L12.8208 13.3332M11.3154 11.7218L12.5092 10.444C12.7914 10.1419 13.1743 9.97217 13.5734 9.97217C13.9726 9.97217 14.3554 10.1419 14.6378 10.444L15.699 11.636" stroke="#121315" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
|
|
5621
|
+
<path d="M11.4805 7.77783H11.4879" stroke="#121315" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
|
|
5622
|
+
</svg>`,
|
|
5623
|
+
/* eslint-enable */
|
|
5624
|
+
title: 'Image'
|
|
5625
|
+
};
|
|
5626
|
+
}
|
|
5627
|
+
static get pasteConfig() {
|
|
5628
|
+
return {
|
|
5629
|
+
tags: [
|
|
5630
|
+
{
|
|
5631
|
+
img: { src: true }
|
|
5632
|
+
}
|
|
5633
|
+
],
|
|
5634
|
+
files: {
|
|
5635
|
+
mimeTypes: ['image/*']
|
|
5636
|
+
}
|
|
5637
|
+
};
|
|
5638
|
+
}
|
|
5639
|
+
constructor(options) {
|
|
5640
|
+
this.selectedFile = null;
|
|
5641
|
+
this.onSelectFile = () => {
|
|
5642
|
+
return this.uploader.selectFile({
|
|
5643
|
+
fileSelected: (file) => {
|
|
5644
|
+
const url = URL.createObjectURL(file);
|
|
5645
|
+
this.imageTool.preview = url;
|
|
5646
|
+
this.imageTool.isLoading = true;
|
|
5647
|
+
this.selectedFile = file;
|
|
5648
|
+
this.uploader.uploadFile(file);
|
|
5649
|
+
}
|
|
5650
|
+
});
|
|
5651
|
+
};
|
|
5652
|
+
const { api, readOnly, config, data, block } = options;
|
|
5653
|
+
this.blockApi = block;
|
|
5654
|
+
this.api = api;
|
|
5655
|
+
this.readOnly = readOnly;
|
|
5656
|
+
this.config = {
|
|
5657
|
+
load: config?.load ?? (() => { }),
|
|
5658
|
+
field: config?.field ?? 'image',
|
|
5659
|
+
types: config?.types ?? 'image/*',
|
|
5660
|
+
endpoint: config?.endpoint ?? '',
|
|
5661
|
+
buttonContent: config?.buttonContent ?? this.api.i18n.t('Select an Image'),
|
|
5662
|
+
additionalRequestHeaders: config?.additionalRequestHeaders || {},
|
|
5663
|
+
};
|
|
5664
|
+
this.uploader = new CuiFileUploader(this.config, this.onUpload.bind(this), this.uploadingFailed.bind(this));
|
|
5665
|
+
this.data = data;
|
|
5666
|
+
this.data.tunes = this.data.tunes || {};
|
|
5667
|
+
}
|
|
5668
|
+
async onPaste(event) {
|
|
5669
|
+
const actions = {
|
|
5670
|
+
tag: this.pasteByTag.bind(this),
|
|
5671
|
+
file: this.pasteByFile.bind(this)
|
|
5672
|
+
};
|
|
5673
|
+
const key = event.type;
|
|
5674
|
+
this.imageTool.isLoading = true;
|
|
5675
|
+
actions[key](event);
|
|
5676
|
+
}
|
|
5677
|
+
pasteByFile(event) {
|
|
5678
|
+
const file = event.detail.file;
|
|
5679
|
+
this.selectedFile = file;
|
|
5680
|
+
this.uploader.uploadFile(file);
|
|
5681
|
+
}
|
|
5682
|
+
pasteByTag(event) {
|
|
5683
|
+
const file = event.detail.data.src;
|
|
5684
|
+
this.selectedFile = file;
|
|
5685
|
+
this.uploader.uploadByUrl(file);
|
|
5686
|
+
}
|
|
5687
|
+
appendCallback() {
|
|
5688
|
+
this.onSelectFile();
|
|
5689
|
+
}
|
|
5690
|
+
render() {
|
|
5691
|
+
this.imageTool = document.createElement(EDITOR_IMAGE_TOOL_SELECTOR);
|
|
5692
|
+
this.imageTool.api = this.api;
|
|
5693
|
+
this.imageTool.image = this.data.file?.url || '';
|
|
5694
|
+
this.imageTool.caption = this.data.caption || '';
|
|
5695
|
+
this.imageTool.tunes = this.data.tunes;
|
|
5696
|
+
this.imageTool.readOnly = this.readOnly;
|
|
5697
|
+
this.imageTool.buttonContent = this.config.buttonContent;
|
|
5698
|
+
this.imageTool.addEventListener('fileSelected', this.onSelectFile);
|
|
5699
|
+
this.imageTool.addEventListener('captionChanged', this.changeCaption.bind(this));
|
|
5700
|
+
return this.imageTool;
|
|
5701
|
+
}
|
|
5702
|
+
renderSettings() {
|
|
5703
|
+
return this.Tunes.map((tune) => ({
|
|
5704
|
+
icon: tune.icon,
|
|
5705
|
+
label: this.api.i18n.t(tune.title),
|
|
5706
|
+
name: tune.name,
|
|
5707
|
+
toggle: tune.toggle,
|
|
5708
|
+
isActive: this.data.tunes[tune.name],
|
|
5709
|
+
onActivate: () => this.tuneToggled(tune.name)
|
|
5710
|
+
}));
|
|
5711
|
+
}
|
|
5712
|
+
save() {
|
|
5713
|
+
return this.data;
|
|
5714
|
+
}
|
|
5715
|
+
removed() {
|
|
5716
|
+
this.imageTool.removeEventListener('fileSelected', this.onSelectFile);
|
|
5717
|
+
this.imageTool.removeEventListener('captionChanged', this.changeCaption);
|
|
5718
|
+
}
|
|
5719
|
+
changeCaption(event) {
|
|
5720
|
+
const customEvent = event;
|
|
5721
|
+
const value = customEvent.detail;
|
|
5722
|
+
this.data.caption = value;
|
|
5723
|
+
this.blockApi?.dispatchChange();
|
|
5724
|
+
}
|
|
5725
|
+
set image(file) {
|
|
5726
|
+
this.data.file = file || {};
|
|
5727
|
+
if (file && file.url) {
|
|
5728
|
+
this.imageTool.image = file.url;
|
|
5729
|
+
}
|
|
5730
|
+
}
|
|
5731
|
+
onUpload(response) {
|
|
5732
|
+
if (!response.success || !response.file || !this.selectedFile) {
|
|
5733
|
+
this.uploadingFailed();
|
|
5734
|
+
return;
|
|
5735
|
+
}
|
|
5736
|
+
const url = this.selectedFile instanceof File ? window.URL.createObjectURL(this.selectedFile) : this.selectedFile;
|
|
5737
|
+
this.data.file = response.file;
|
|
5738
|
+
this.imageTool.image = url;
|
|
5739
|
+
this.imageTool.isLoading = false;
|
|
5740
|
+
}
|
|
5741
|
+
uploadingFailed() {
|
|
5742
|
+
this.imageTool.image = '';
|
|
5743
|
+
this.imageTool.isLoading = false;
|
|
5744
|
+
}
|
|
5745
|
+
tuneToggled(tuneName) {
|
|
5746
|
+
const value = !(this.data.tunes[tuneName] || false);
|
|
5747
|
+
this.data.tunes[tuneName] = value;
|
|
5748
|
+
this.imageTool.tunes = { ...this.data.tunes };
|
|
5749
|
+
}
|
|
5750
|
+
}
|
|
5751
|
+
|
|
5752
|
+
class CuiVideoTool {
|
|
5753
|
+
static get isReadOnlySupported() {
|
|
5754
|
+
return true;
|
|
5755
|
+
}
|
|
5756
|
+
static get toolbox() {
|
|
5757
|
+
return {
|
|
5758
|
+
icon: CUI_ICONS.cuiIconPlayCircle,
|
|
5759
|
+
title: 'Video'
|
|
5760
|
+
};
|
|
5761
|
+
}
|
|
5762
|
+
static get pasteConfig() {
|
|
5763
|
+
return {
|
|
5764
|
+
tags: ['video'],
|
|
5765
|
+
patterns: {
|
|
5766
|
+
video: /https?:\/\/\S+\.(mp4)$/i
|
|
5767
|
+
},
|
|
5768
|
+
files: {
|
|
5769
|
+
mimeTypes: ['video/*']
|
|
5770
|
+
}
|
|
5771
|
+
};
|
|
5772
|
+
}
|
|
5773
|
+
constructor(options) {
|
|
5774
|
+
this.selectedFile = null;
|
|
5775
|
+
this.onSelectFile = () => {
|
|
5776
|
+
return this.uploader.selectFile({
|
|
5777
|
+
fileSelected: (file) => {
|
|
5778
|
+
const url = URL.createObjectURL(file);
|
|
5779
|
+
this.getCaptureFromVideo(url);
|
|
5780
|
+
this.videoTool.isLoading = true;
|
|
5781
|
+
this.selectedFile = file;
|
|
5782
|
+
this.uploader.uploadFile(file);
|
|
5783
|
+
}
|
|
5784
|
+
});
|
|
5785
|
+
};
|
|
5786
|
+
const { api, readOnly, config, data, block } = options;
|
|
5787
|
+
this.blockApi = block;
|
|
5788
|
+
this.api = api;
|
|
5789
|
+
this.readOnly = readOnly;
|
|
5790
|
+
this.config = {
|
|
5791
|
+
load: config?.load ?? (() => { }),
|
|
5792
|
+
field: config?.field ?? 'video',
|
|
5793
|
+
types: config?.types ?? 'video/*',
|
|
5794
|
+
endpoint: config?.endpoint ?? '',
|
|
5795
|
+
buttonContent: config?.buttonContent ?? this.api.i18n.t('Select a Video'),
|
|
5796
|
+
additionalRequestHeaders: config?.additionalRequestHeaders ?? {},
|
|
5797
|
+
};
|
|
5798
|
+
this.uploader = new CuiFileUploader(this.config, this.onUpload.bind(this), this.uploadingFailed.bind(this));
|
|
5799
|
+
this.data = data;
|
|
5800
|
+
}
|
|
5801
|
+
async onPaste(event) {
|
|
5802
|
+
if (event.type !== 'file') {
|
|
5803
|
+
return;
|
|
5804
|
+
}
|
|
5805
|
+
const file = event.detail.file;
|
|
5806
|
+
this.videoTool.isLoading = true;
|
|
5807
|
+
this.selectedFile = file;
|
|
5808
|
+
this.uploader.uploadFile(file);
|
|
5809
|
+
}
|
|
5810
|
+
appendCallback() {
|
|
5811
|
+
this.onSelectFile();
|
|
5812
|
+
}
|
|
5813
|
+
render() {
|
|
5814
|
+
this.videoTool = document.createElement(EDITOR_VIDEO_TOOL_SELECTOR);
|
|
5815
|
+
this.videoTool.api = this.api;
|
|
5816
|
+
this.videoTool.video = this.data.file?.url || '';
|
|
5817
|
+
this.videoTool.caption = this.data.caption || '';
|
|
5818
|
+
this.videoTool.readOnly = this.readOnly;
|
|
5819
|
+
this.videoTool.buttonContent = this.config.buttonContent;
|
|
5820
|
+
this.videoTool.addEventListener('fileSelected', this.onSelectFile);
|
|
5821
|
+
this.videoTool.addEventListener('captionChanged', this.changeCaption.bind(this));
|
|
5822
|
+
return this.videoTool;
|
|
5823
|
+
}
|
|
5824
|
+
save() {
|
|
5825
|
+
return this.data;
|
|
5826
|
+
}
|
|
5827
|
+
removed() {
|
|
5828
|
+
this.videoTool.removeEventListener('fileSelected', this.onSelectFile);
|
|
5829
|
+
this.videoTool.removeEventListener('captionChanged', this.changeCaption);
|
|
5830
|
+
}
|
|
5831
|
+
changeCaption(event) {
|
|
5832
|
+
const customEvent = event;
|
|
5833
|
+
const value = customEvent.detail;
|
|
5834
|
+
this.data.caption = value;
|
|
5835
|
+
this.blockApi?.dispatchChange();
|
|
5836
|
+
}
|
|
5837
|
+
set video(file) {
|
|
5838
|
+
this.data.file = file || {};
|
|
5839
|
+
if (file && file.url) {
|
|
5840
|
+
this.videoTool.video = file.url;
|
|
5841
|
+
}
|
|
5842
|
+
}
|
|
5843
|
+
onUpload(response) {
|
|
5844
|
+
if (!response.success || !response.file || !this.selectedFile) {
|
|
5845
|
+
this.uploadingFailed();
|
|
5846
|
+
return;
|
|
5847
|
+
}
|
|
5848
|
+
const url = this.selectedFile instanceof File ? window.URL.createObjectURL(this.selectedFile) : this.selectedFile;
|
|
5849
|
+
this.data.file = response.file;
|
|
5850
|
+
this.videoTool.video = url;
|
|
5851
|
+
this.videoTool.isLoading = false;
|
|
5852
|
+
}
|
|
5853
|
+
uploadingFailed() {
|
|
5854
|
+
this.videoTool.video = '';
|
|
5855
|
+
this.videoTool.isLoading = false;
|
|
5856
|
+
}
|
|
5857
|
+
getCaptureFromVideo(url) {
|
|
5858
|
+
const canvas = document.createElement('canvas');
|
|
5859
|
+
const video = document.createElement('video');
|
|
5860
|
+
video.src = url;
|
|
5861
|
+
video.currentTime = 1;
|
|
5862
|
+
canvas.width = 120;
|
|
5863
|
+
canvas.height = 120;
|
|
5864
|
+
video.onloadeddata = () => {
|
|
5865
|
+
const context = canvas.getContext('2d');
|
|
5866
|
+
if (!context) {
|
|
5867
|
+
return;
|
|
5868
|
+
}
|
|
5869
|
+
context.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
5870
|
+
canvas.toBlob((blob) => {
|
|
5871
|
+
if (!blob) {
|
|
5872
|
+
return;
|
|
5873
|
+
}
|
|
5874
|
+
this.videoTool.preview = URL.createObjectURL(blob);
|
|
5875
|
+
});
|
|
5876
|
+
};
|
|
5877
|
+
video.load();
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
|
|
5881
|
+
class CuiAttachesTool {
|
|
5882
|
+
static get isReadOnlySupported() {
|
|
5883
|
+
return true;
|
|
5884
|
+
}
|
|
5885
|
+
static get toolbox() {
|
|
5886
|
+
return {
|
|
5887
|
+
icon: CUI_ICONS.cuiIconPaperclipSm,
|
|
5888
|
+
title: 'File'
|
|
5889
|
+
};
|
|
5890
|
+
}
|
|
5891
|
+
constructor(options) {
|
|
5892
|
+
this.selectedFile = null;
|
|
5893
|
+
this.onSelectFile = () => {
|
|
5894
|
+
return this.uploader.selectFile({
|
|
5895
|
+
fileSelected: (file) => {
|
|
5896
|
+
this.attachesTool.isLoading = true;
|
|
5897
|
+
this.selectedFile = file;
|
|
5898
|
+
this.uploader.uploadFile(file);
|
|
5899
|
+
}
|
|
5900
|
+
});
|
|
5901
|
+
};
|
|
5902
|
+
const { api, readOnly, config, data, block } = options;
|
|
5903
|
+
this.blockApi = block;
|
|
5904
|
+
this.api = api;
|
|
5905
|
+
this.readOnly = readOnly;
|
|
5906
|
+
this.config = {
|
|
5907
|
+
load: config?.load ?? (() => { }),
|
|
5908
|
+
field: config?.field ?? 'file',
|
|
5909
|
+
types: config?.types ?? '*',
|
|
5910
|
+
endpoint: config?.endpoint ?? '',
|
|
5911
|
+
buttonContent: config?.buttonContent ?? this.api.i18n.t('Select a File'),
|
|
5912
|
+
additionalRequestHeaders: config?.additionalRequestHeaders ?? {},
|
|
5913
|
+
};
|
|
5914
|
+
this.uploader = new CuiFileUploader(this.config, this.onUpload.bind(this), this.uploadingFailed.bind(this));
|
|
5915
|
+
this.data = data;
|
|
5916
|
+
}
|
|
5917
|
+
appendCallback() {
|
|
5918
|
+
this.onSelectFile();
|
|
5919
|
+
}
|
|
5920
|
+
render() {
|
|
5921
|
+
this.attachesTool = document.createElement(EDITOR_ATTACHES_TOOL_SELECTOR);
|
|
5922
|
+
this.attachesTool.api = this.api;
|
|
5923
|
+
this.attachesTool.file = this.data.file ?? '';
|
|
5924
|
+
this.attachesTool.title = this.data.title ?? '';
|
|
5925
|
+
this.attachesTool.readOnly = this.readOnly;
|
|
5926
|
+
this.attachesTool.buttonContent = this.config.buttonContent;
|
|
5927
|
+
this.attachesTool.addEventListener('fileSelected', this.onSelectFile);
|
|
5928
|
+
this.attachesTool.addEventListener('captionChanged', this.changeCaption.bind(this));
|
|
5929
|
+
return this.attachesTool;
|
|
5930
|
+
}
|
|
5931
|
+
save() {
|
|
5932
|
+
return this.data;
|
|
5933
|
+
}
|
|
5934
|
+
removed() {
|
|
5935
|
+
this.attachesTool.removeEventListener('fileSelected', this.onSelectFile);
|
|
5936
|
+
this.attachesTool.removeEventListener('captionChanged', this.changeCaption);
|
|
5937
|
+
}
|
|
5938
|
+
changeCaption(event) {
|
|
5939
|
+
const customEvent = event;
|
|
5940
|
+
const value = customEvent.detail;
|
|
5941
|
+
this.data.title = value;
|
|
5942
|
+
this.blockApi?.dispatchChange();
|
|
5943
|
+
}
|
|
5944
|
+
set file(file) {
|
|
5945
|
+
this.data.title = file.name;
|
|
5946
|
+
this.data.file = {
|
|
5947
|
+
name: file.name,
|
|
5948
|
+
extension: file.name?.split('.').pop(),
|
|
5949
|
+
size: file.size,
|
|
5950
|
+
url: file.url
|
|
5951
|
+
};
|
|
5952
|
+
this.attachesTool.file = { ...this.data.file };
|
|
5953
|
+
this.attachesTool.title = file.name;
|
|
5954
|
+
}
|
|
5955
|
+
onUpload(response) {
|
|
5956
|
+
if (!response.success || !response.file || !this.selectedFile) {
|
|
5957
|
+
this.uploadingFailed();
|
|
5958
|
+
return;
|
|
5959
|
+
}
|
|
5960
|
+
this.file = {
|
|
5961
|
+
name: this.selectedFile.name,
|
|
5962
|
+
extension: this.selectedFile.name.split('.').pop(),
|
|
5963
|
+
size: this.selectedFile.size,
|
|
5964
|
+
url: response.file.url
|
|
5965
|
+
};
|
|
5966
|
+
this.attachesTool.isLoading = false;
|
|
5967
|
+
}
|
|
5968
|
+
uploadingFailed() {
|
|
5969
|
+
this.attachesTool.file = undefined;
|
|
5970
|
+
this.attachesTool.isLoading = false;
|
|
5971
|
+
}
|
|
5972
|
+
}
|
|
5973
|
+
|
|
5974
|
+
var RangeContainer;
|
|
5975
|
+
(function (RangeContainer) {
|
|
5976
|
+
RangeContainer["start"] = "startContainer";
|
|
5977
|
+
RangeContainer["end"] = "endContainer";
|
|
5978
|
+
})(RangeContainer || (RangeContainer = {}));
|
|
5979
|
+
class CuiMarkerTool {
|
|
5980
|
+
static get isInline() {
|
|
5981
|
+
return true;
|
|
5982
|
+
}
|
|
5983
|
+
get state() {
|
|
5984
|
+
return this._state;
|
|
5985
|
+
}
|
|
5986
|
+
set state(state) {
|
|
5987
|
+
this._state = state;
|
|
5988
|
+
this.button?.classList.toggle(this.api.styles.inlineToolButtonActive, state);
|
|
5989
|
+
}
|
|
5990
|
+
constructor(data) {
|
|
5991
|
+
this.LIST_CLASS = 'cdx-list__item';
|
|
5992
|
+
this.DEFAULT_CLASS = 'marker';
|
|
5993
|
+
this.DIV = 'div';
|
|
5994
|
+
this.TAG = 'MARK';
|
|
5995
|
+
this.CLASS = 'tool-marker';
|
|
5996
|
+
this._state = false;
|
|
5997
|
+
this.api = data.api;
|
|
5998
|
+
}
|
|
5999
|
+
render() {
|
|
6000
|
+
this.button = document.createElement('button');
|
|
6001
|
+
this.button.type = 'button';
|
|
6002
|
+
this.button.classList.add(this.api.styles.inlineToolButton);
|
|
6003
|
+
this.range = window.getSelection()?.getRangeAt(0).cloneRange();
|
|
6004
|
+
return this.button;
|
|
6005
|
+
}
|
|
6006
|
+
surround() {
|
|
6007
|
+
if (this.state) {
|
|
6008
|
+
this.api.inlineToolbar.close();
|
|
6009
|
+
this.unwrap();
|
|
6010
|
+
return;
|
|
6011
|
+
}
|
|
6012
|
+
this.markerModal.title = this.range.toString();
|
|
6013
|
+
}
|
|
6014
|
+
wrap(range) {
|
|
6015
|
+
const { startContainer, endContainer } = range;
|
|
6016
|
+
const selectedText = range.extractContents();
|
|
6017
|
+
const mark = this.createElement();
|
|
6018
|
+
mark.appendChild(selectedText);
|
|
6019
|
+
this.removeNestedMarkers(mark, this.DEFAULT_CLASS);
|
|
6020
|
+
this.addMarkerToDOM(range, mark, startContainer, endContainer);
|
|
6021
|
+
this.removeExternalMarkers(range, this.DEFAULT_CLASS);
|
|
6022
|
+
this.removeEmptyMarkers(range);
|
|
6023
|
+
this.api.selection.expandToTag(mark);
|
|
6024
|
+
}
|
|
6025
|
+
unwrap() {
|
|
6026
|
+
const mark = this.api.selection.findParentTag(this.TAG, this.CLASS);
|
|
6027
|
+
if (!mark) {
|
|
6028
|
+
return;
|
|
6029
|
+
}
|
|
6030
|
+
removeElementTagWrapper(mark);
|
|
6031
|
+
}
|
|
6032
|
+
createElement(text = '') {
|
|
6033
|
+
const element = document.createElement(this.TAG);
|
|
6034
|
+
element.classList.add(this.DEFAULT_CLASS);
|
|
6035
|
+
element.textContent = text;
|
|
6036
|
+
return element;
|
|
6037
|
+
}
|
|
6038
|
+
addMarkerToDOM(range, mark, startBlock, endBlock) {
|
|
6039
|
+
const classes = [this.LIST_CLASS, COMBINED_TEXT_BLOCK_PART];
|
|
6040
|
+
const { className, parent: startParent } = this.getClosestParentWithClass(startBlock, classes);
|
|
6041
|
+
const { parent: endParent } = this.getClosestParentWithClass(endBlock, classes);
|
|
6042
|
+
if (!className || startParent === endParent) {
|
|
6043
|
+
range.insertNode(mark);
|
|
6044
|
+
return;
|
|
6045
|
+
}
|
|
6046
|
+
this.removeAllParentsFromMarker(mark, className);
|
|
6047
|
+
startParent?.append(mark);
|
|
6048
|
+
}
|
|
6049
|
+
removeEmptyMarkers(range) {
|
|
6050
|
+
range.commonAncestorContainer.childNodes.forEach((node) => {
|
|
6051
|
+
if (node.nodeName !== this.TAG) {
|
|
6052
|
+
return;
|
|
6053
|
+
}
|
|
6054
|
+
if (node.textContent?.length) {
|
|
6055
|
+
return;
|
|
6056
|
+
}
|
|
6057
|
+
node.remove();
|
|
6058
|
+
});
|
|
6059
|
+
}
|
|
6060
|
+
removeExternalMarkers(range, className) {
|
|
6061
|
+
const startContainer = this.getElementFromContainerNode(range, RangeContainer.start, className);
|
|
6062
|
+
const endContainer = this.getElementFromContainerNode(range, RangeContainer.end, className);
|
|
6063
|
+
const startElement = startContainer?.closest('.' + className);
|
|
6064
|
+
const endElement = endContainer?.closest('.' + className);
|
|
6065
|
+
if (startElement !== endElement || !startElement?.classList.contains(className)) {
|
|
6066
|
+
return;
|
|
6067
|
+
}
|
|
6068
|
+
const marker = startElement;
|
|
6069
|
+
removeElementTagWrapper(marker);
|
|
6070
|
+
}
|
|
6071
|
+
removeNestedMarkers(element, selector) {
|
|
6072
|
+
const markers = element.querySelectorAll('.' + selector);
|
|
6073
|
+
markers.forEach((node) => {
|
|
6074
|
+
const marker = node;
|
|
6075
|
+
removeElementTagWrapper(marker);
|
|
6076
|
+
});
|
|
6077
|
+
}
|
|
6078
|
+
getElementFromContainerNode(range, key, className) {
|
|
6079
|
+
const container = range[key];
|
|
6080
|
+
if (container?.classList?.contains(className)) {
|
|
6081
|
+
return container;
|
|
6082
|
+
}
|
|
6083
|
+
return container.parentElement;
|
|
6084
|
+
}
|
|
6085
|
+
removeAllParentsFromMarker(mark, className) {
|
|
6086
|
+
const innerMarkerNodes = [];
|
|
6087
|
+
mark.childNodes.forEach((node) => {
|
|
6088
|
+
innerMarkerNodes.push(node);
|
|
6089
|
+
});
|
|
6090
|
+
innerMarkerNodes.forEach((node) => {
|
|
6091
|
+
const element = node;
|
|
6092
|
+
const isBlock = element.classList?.contains(className);
|
|
6093
|
+
if (!isBlock) {
|
|
6094
|
+
return;
|
|
6095
|
+
}
|
|
6096
|
+
removeElementTagWrapper(element);
|
|
6097
|
+
});
|
|
6098
|
+
}
|
|
6099
|
+
getClosestParentWithClass(node, classes) {
|
|
6100
|
+
const nodeParent = node.parentElement;
|
|
6101
|
+
let parent = nodeParent;
|
|
6102
|
+
let resultClassName = '';
|
|
6103
|
+
for (const className of classes) {
|
|
6104
|
+
const parentWithClass = parent.closest('.' + className);
|
|
6105
|
+
if (!parentWithClass) {
|
|
6106
|
+
continue;
|
|
6107
|
+
}
|
|
6108
|
+
parent = parentWithClass;
|
|
6109
|
+
resultClassName = className;
|
|
6110
|
+
break;
|
|
6111
|
+
}
|
|
6112
|
+
return { className: resultClassName, parent };
|
|
6113
|
+
}
|
|
6114
|
+
}
|
|
6115
|
+
|
|
6116
|
+
class CuiLinkMarker extends CuiMarkerTool {
|
|
6117
|
+
static get sanitize() {
|
|
6118
|
+
return {
|
|
6119
|
+
a: {
|
|
6120
|
+
href: true,
|
|
6121
|
+
class: true,
|
|
6122
|
+
target: true,
|
|
6123
|
+
contenteditable: true
|
|
6124
|
+
}
|
|
6125
|
+
};
|
|
6126
|
+
}
|
|
6127
|
+
constructor(data) {
|
|
6128
|
+
super(data);
|
|
6129
|
+
this.TAG = 'A';
|
|
6130
|
+
}
|
|
6131
|
+
render() {
|
|
6132
|
+
super.render();
|
|
6133
|
+
/* eslint-disable */
|
|
6134
|
+
this.button.innerHTML = `<svg width="20" height="15" viewBox="-3 -3 24 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
6135
|
+
<path d="M18.2813 1.22405C17.9329 0.874451 17.5189 0.597062 17.0631 0.407792C16.6073 0.218522 16.1186 0.121094 15.625 0.121094C15.1315 0.121094 14.6428 0.218522 14.187 0.407792C13.7312 0.597062 13.3172 0.874451 12.9688 1.22405L13.8563 2.11155C14.089 1.87886 14.3652 1.69429 14.6692 1.56836C14.9733 1.44243 15.2991 1.37762 15.6282 1.37762C15.9572 1.37762 16.2831 1.44243 16.5871 1.56836C16.8911 1.69429 17.1674 1.87886 17.4 2.11155C17.6327 2.34424 17.8173 2.62047 17.9432 2.92449C18.0692 3.22851 18.134 3.55436 18.134 3.88343C18.134 4.21249 18.0692 4.53834 17.9432 4.84236C17.8173 5.14638 17.6327 5.42261 17.4 5.6553L12.4 10.6553C11.9309 11.1252 11.2944 11.3896 10.6304 11.3901C9.96638 11.3907 9.32935 11.1275 8.85942 10.6584C8.38949 10.1893 8.12515 9.55275 8.12457 8.88876C8.12398 8.22476 8.38719 7.58773 8.85629 7.1178L9.73754 6.2303L8.85629 5.3428L7.96879 6.2303C7.61919 6.57869 7.3418 6.99266 7.15253 7.44848C6.96326 7.9043 6.86583 8.393 6.86583 8.88655C6.86583 9.3801 6.96326 9.8688 7.15253 10.3246C7.3418 10.7804 7.61919 11.1944 7.96879 11.5428C8.67597 12.2409 9.63134 12.6298 10.625 12.624C11.1205 12.6261 11.6114 12.5299 12.0695 12.3411C12.5276 12.1523 12.9437 11.8746 13.2938 11.524L18.2938 6.52405C18.9944 5.81927 19.3866 4.86522 19.3842 3.87146C19.3819 2.87771 18.9852 1.92552 18.2813 1.22405Z" fill="#595E6A"/>
|
|
6136
|
+
<path d="M2.61879 12.5115C2.38541 12.2793 2.20022 12.0031 2.07386 11.6991C1.94749 11.395 1.88244 11.069 1.88244 10.7397C1.88244 10.4104 1.94749 10.0844 2.07386 9.78028C2.20022 9.47621 2.38541 9.2001 2.61879 8.9678L7.61879 3.9678C7.85109 3.73442 8.1272 3.54923 8.43127 3.42287C8.73534 3.2965 9.06138 3.23145 9.39067 3.23145C9.71995 3.23145 10.046 3.2965 10.3501 3.42287C10.6541 3.54923 10.9302 3.73442 11.1625 3.9678C11.3944 4.20193 11.577 4.48022 11.6994 4.78619C11.8218 5.09215 11.8815 5.41958 11.875 5.74905C11.8769 6.07955 11.8133 6.40715 11.6878 6.7129C11.5623 7.01865 11.3774 7.29647 11.1438 7.5303L9.81879 8.87405L10.7063 9.76155L12.0313 8.43655C12.7366 7.73124 13.1328 6.77463 13.1328 5.77718C13.1328 4.77972 12.7366 3.82311 12.0313 3.1178C11.326 2.41249 10.3694 2.01625 9.37192 2.01625C8.37446 2.01625 7.41785 2.41249 6.71254 3.1178L1.71254 8.1178C1.362 8.4663 1.08382 8.88066 0.893994 9.33706C0.704168 9.79346 0.606445 10.2829 0.606445 10.7772C0.606445 11.2715 0.704168 11.7609 0.893994 12.2173C1.08382 12.6737 1.362 13.088 1.71254 13.4365C2.42431 14.1293 3.38185 14.5115 4.37504 14.499C5.37698 14.5 6.33862 14.1046 7.05004 13.399L6.16254 12.5115C5.93025 12.7449 5.65413 12.9301 5.35006 13.0565C5.04599 13.1829 4.71995 13.2479 4.39067 13.2479C4.06138 13.2479 3.73534 13.1829 3.43127 13.0565C3.1272 12.9301 2.85109 12.7449 2.61879 12.5115Z" fill="#595E6A"/>
|
|
6137
|
+
</svg>
|
|
6138
|
+
`;
|
|
6139
|
+
/* eslint-enable */
|
|
6140
|
+
return this.button;
|
|
6141
|
+
}
|
|
6142
|
+
renderActions() {
|
|
6143
|
+
this.dropdown = document.createElement(this.DIV);
|
|
6144
|
+
if (this.state) {
|
|
6145
|
+
return this.dropdown;
|
|
6146
|
+
}
|
|
6147
|
+
const linkModal = this.createLinkModal();
|
|
6148
|
+
this.dropdown.append(linkModal);
|
|
6149
|
+
return this.dropdown;
|
|
6150
|
+
}
|
|
6151
|
+
wrapLink(range, markerData) {
|
|
6152
|
+
const { startContainer, endContainer } = range;
|
|
6153
|
+
const url = markerData.data?.toString();
|
|
6154
|
+
const link = this.createElement(url, markerData.title);
|
|
6155
|
+
range.extractContents();
|
|
6156
|
+
this.addMarkerToDOM(range, link, startContainer, endContainer);
|
|
6157
|
+
this.removeExternalMarkers(range, this.DEFAULT_CLASS);
|
|
6158
|
+
this.removeEmptyMarkers(range);
|
|
6159
|
+
this.api.selection.expandToTag(link);
|
|
6160
|
+
}
|
|
6161
|
+
unwrap() {
|
|
6162
|
+
const mark = this.api.selection.findParentTag(this.TAG);
|
|
6163
|
+
if (!mark) {
|
|
6164
|
+
return;
|
|
6165
|
+
}
|
|
6166
|
+
removeElementTagWrapper(mark);
|
|
6167
|
+
}
|
|
6168
|
+
createElement(url = '', text = '') {
|
|
6169
|
+
const link = super.createElement(text);
|
|
6170
|
+
link.href = url;
|
|
6171
|
+
link.contentEditable = 'false';
|
|
6172
|
+
link.target = '_blank';
|
|
6173
|
+
return link;
|
|
6174
|
+
}
|
|
6175
|
+
checkState() {
|
|
6176
|
+
const link = this.api.selection.findParentTag(this.TAG);
|
|
6177
|
+
this.state = !!link;
|
|
6178
|
+
}
|
|
6179
|
+
createLinkModal() {
|
|
6180
|
+
this.markerModal = document.createElement(MARKER_MODAL_SELECTOR);
|
|
6181
|
+
this.markerModal.url = '';
|
|
6182
|
+
this.markerModal.target = this.button;
|
|
6183
|
+
this.markerModal.isGlobal = true;
|
|
6184
|
+
this.markerModal.addEventListener('saveClicked', (event) => {
|
|
6185
|
+
const customEvent = event;
|
|
6186
|
+
const data = customEvent.detail;
|
|
6187
|
+
this.wrapLink(this.range, data);
|
|
6188
|
+
});
|
|
6189
|
+
return this.markerModal;
|
|
6190
|
+
}
|
|
6191
|
+
}
|
|
6192
|
+
|
|
6193
|
+
class CuiCustomMarkerTool extends CuiMarkerTool {
|
|
6194
|
+
static get sanitize() {
|
|
6195
|
+
return {
|
|
6196
|
+
mark: {
|
|
6197
|
+
class: true,
|
|
6198
|
+
'data-id': true,
|
|
6199
|
+
'data-type': true,
|
|
6200
|
+
contenteditable: true
|
|
6201
|
+
}
|
|
6202
|
+
};
|
|
6203
|
+
}
|
|
6204
|
+
constructor(data) {
|
|
6205
|
+
super(data);
|
|
6206
|
+
}
|
|
6207
|
+
wrapTool(range, markerData) {
|
|
6208
|
+
const { startContainer, endContainer } = range;
|
|
6209
|
+
if (markerData.data && typeof markerData.data !== 'string') {
|
|
6210
|
+
this.id = markerData.data.id;
|
|
6211
|
+
this.type = markerData.data.type;
|
|
6212
|
+
}
|
|
6213
|
+
const mark = this.createElement(markerData.title);
|
|
6214
|
+
range.extractContents();
|
|
6215
|
+
this.removeNestedMarkers(mark, this.DEFAULT_CLASS);
|
|
6216
|
+
this.addMarkerToDOM(range, mark, startContainer, endContainer);
|
|
6217
|
+
this.removeExternalMarkers(range, this.DEFAULT_CLASS);
|
|
6218
|
+
this.removeEmptyMarkers(range);
|
|
6219
|
+
this.api.selection.expandToTag(mark);
|
|
6220
|
+
}
|
|
6221
|
+
onToolButtonClick(event) {
|
|
6222
|
+
const range = window.getSelection()?.getRangeAt(0);
|
|
6223
|
+
if (range) {
|
|
6224
|
+
return;
|
|
6225
|
+
}
|
|
6226
|
+
event.stopImmediatePropagation();
|
|
6227
|
+
}
|
|
6228
|
+
render() {
|
|
6229
|
+
super.render();
|
|
6230
|
+
this.button.onclick = this.onToolButtonClick.bind(this);
|
|
6231
|
+
return this.button;
|
|
6232
|
+
}
|
|
6233
|
+
renderActions() {
|
|
6234
|
+
this.dropdown = document.createElement(this.DIV);
|
|
6235
|
+
if (this.state) {
|
|
6236
|
+
return this.dropdown;
|
|
6237
|
+
}
|
|
6238
|
+
const markerSelect = this.createLinkModal();
|
|
6239
|
+
this.dropdown.append(markerSelect);
|
|
6240
|
+
return this.dropdown;
|
|
6241
|
+
}
|
|
6242
|
+
createElement(text = '') {
|
|
6243
|
+
const element = super.createElement(text);
|
|
6244
|
+
element.contentEditable = 'false';
|
|
6245
|
+
element.classList.add(this.CLASS);
|
|
6246
|
+
element.setAttribute('data-id', this.id);
|
|
6247
|
+
element.setAttribute('data-type', this.type);
|
|
6248
|
+
return element;
|
|
6249
|
+
}
|
|
6250
|
+
checkState(select) {
|
|
6251
|
+
const range = select.getRangeAt(0);
|
|
6252
|
+
const mark = this.api.selection.findParentTag(this.TAG);
|
|
6253
|
+
const isCorrectTool = mark?.classList.contains(this.CLASS);
|
|
6254
|
+
if (!mark || !isCorrectTool) {
|
|
6255
|
+
this.state = false;
|
|
6256
|
+
return;
|
|
6257
|
+
}
|
|
6258
|
+
const startContainer = range.startContainer;
|
|
6259
|
+
const endContainer = range.endContainer;
|
|
6260
|
+
const isStartMarker = mark.contains(startContainer);
|
|
6261
|
+
const isEndMarker = mark.contains(endContainer);
|
|
6262
|
+
this.state = isStartMarker && isEndMarker && isStartMarker === isEndMarker;
|
|
6263
|
+
}
|
|
6264
|
+
createLinkModal() {
|
|
6265
|
+
this.markerModal = document.createElement(MARKER_MODAL_SELECTOR);
|
|
6266
|
+
this.markerModal.tool = { id: '', title: '', type: undefined };
|
|
6267
|
+
this.markerModal.target = this.button;
|
|
6268
|
+
this.markerModal.isTool = true;
|
|
6269
|
+
this.markerModal.isGlobal = true;
|
|
6270
|
+
this.markerModal.addEventListener('saveClicked', (event) => {
|
|
6271
|
+
const customEvent = event;
|
|
6272
|
+
const data = customEvent.detail;
|
|
6273
|
+
this.wrapTool(this.range, data);
|
|
6274
|
+
});
|
|
6275
|
+
return this.markerModal;
|
|
6276
|
+
}
|
|
6277
|
+
}
|
|
6278
|
+
|
|
6279
|
+
class CuiRoleMarker extends CuiCustomMarkerTool {
|
|
6280
|
+
constructor(data) {
|
|
6281
|
+
super(data);
|
|
6282
|
+
this.CLASS = 'role-marker';
|
|
6283
|
+
}
|
|
6284
|
+
render() {
|
|
6285
|
+
super.render();
|
|
6286
|
+
/* eslint-disable */
|
|
6287
|
+
this.button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="-3 -3 24 24" fill="none">
|
|
6288
|
+
<path d="M13.3335 17.5V15.8333C13.3335 14.9493 12.9823 14.1014 12.3572 13.4763C11.7321 12.8512 10.8842 12.5 10.0002 12.5H4.16683C3.28277 12.5 2.43493 12.8512 1.80981 13.4763C1.18469 14.1014 0.833496 14.9493 0.833496 15.8333V17.5M16.6668 6.66667V11.6667M19.1668 9.16667H14.1668M10.4168 5.83333C10.4168 7.67428 8.92445 9.16667 7.0835 9.16667C5.24255 9.16667 3.75016 7.67428 3.75016 5.83333C3.75016 3.99238 5.24255 2.5 7.0835 2.5C8.92445 2.5 10.4168 3.99238 10.4168 5.83333Z" stroke="#595E6A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
6289
|
+
</svg>`;
|
|
6290
|
+
/* eslint-enable */
|
|
6291
|
+
return this.button;
|
|
6292
|
+
}
|
|
6293
|
+
}
|
|
6294
|
+
|
|
6295
|
+
class CuiToolMarker extends CuiCustomMarkerTool {
|
|
6296
|
+
constructor(data) {
|
|
6297
|
+
super(data);
|
|
6298
|
+
this.CLASS = 'tool-marker';
|
|
6299
|
+
}
|
|
6300
|
+
render() {
|
|
6301
|
+
super.render();
|
|
6302
|
+
this.button.innerHTML =
|
|
6303
|
+
'<svg width="20" height="20" viewBox="-2 -3 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="technologies-tools"><path id="Vector" d="M16.3581 15.3966L16.3581 11.4729C16.3581 11.4158 16.3469 11.3592 16.325 11.3064C16.3031 11.2536 16.2711 11.2056 16.2307 11.1652C16.1903 11.1248 16.1423 11.0928 16.0895 11.0709C16.0368 11.0491 15.9802 11.0378 15.923 11.0378H13.2574L13.2593 11.0372C13.2007 11.0348 13.1422 11.0443 13.0874 11.0651C13.0326 11.0859 12.9825 11.1176 12.9402 11.1582C12.898 11.1989 12.8643 11.2476 12.8414 11.3016C12.8184 11.3556 12.8066 11.4136 12.8067 11.4723L12.8067 15.3972M14.584 11.0334V5.8334M16.3582 15.1022L16.3582 17.0647C16.3583 17.1234 16.3465 17.1814 16.3235 17.2354C16.3006 17.2893 16.2669 17.3381 16.2247 17.3787C16.1824 17.4194 16.1323 17.4511 16.0775 17.4719C16.0227 17.4927 15.9642 17.5022 15.9056 17.4998L15.9075 17.4992H13.2419C13.1847 17.4992 13.1282 17.4879 13.0754 17.466C13.0226 17.4442 12.9746 17.4121 12.9342 17.3717C12.8938 17.3313 12.8618 17.2834 12.8399 17.2306C12.818 17.1778 12.8068 17.1212 12.8068 17.0641L12.8068 15.1022M5.59636 9.88719L5.59636 15.9284C5.59627 16.0872 5.62748 16.2445 5.68821 16.3912C5.74895 16.5379 5.838 16.6713 5.9503 16.7836C6.06259 16.8959 6.19591 16.9849 6.34265 17.0456C6.48938 17.1064 6.64665 17.1376 6.80545 17.1375C7.12589 17.1375 7.43318 17.0101 7.65976 16.7836C7.88634 16.557 8.01365 16.2497 8.0137 15.9293L8.01284 9.88719C9.29329 9.32793 10.4298 8.05047 10.4298 6.56367C10.4302 5.07729 9.22194 3.54264 8.01284 3.241L8.01327 5.83907L6.8046 7.2887L5.59636 5.83864L5.59636 3.241C4.38769 3.54306 3.17902 5.07729 3.17902 6.5641C3.17944 8.05048 4.31591 9.32793 5.59636 9.88719ZM14.9916 5.56545L14.1253 5.56545L13.2589 4.69909L13.6921 2.5332L15.4248 2.5332L15.858 4.69909L14.9916 5.56545Z" stroke="#595E6A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></g></svg>';
|
|
6304
|
+
return this.button;
|
|
6305
|
+
}
|
|
6306
|
+
}
|
|
6307
|
+
|
|
6308
|
+
class CuiCombinedTextBlockTool {
|
|
6309
|
+
constructor(options) {
|
|
6310
|
+
this.TAG = 'span';
|
|
6311
|
+
this.DEBOUNCE_TIME = 350;
|
|
6312
|
+
this.MAX_CHILD_COUNT_FOR_EMPTY = 1;
|
|
6313
|
+
this.PLACEHOLDER_ATTRIBUTE_NAME = 'placeholderActive';
|
|
6314
|
+
this.mutationConfig = {
|
|
6315
|
+
subtree: true,
|
|
6316
|
+
childList: true,
|
|
6317
|
+
characterData: true
|
|
6318
|
+
};
|
|
6319
|
+
this.changes = new Map();
|
|
6320
|
+
this.getMutationCallback = (wait) => {
|
|
6321
|
+
let timeoutId = null;
|
|
6322
|
+
return () => {
|
|
6323
|
+
if (timeoutId) {
|
|
6324
|
+
clearTimeout(timeoutId);
|
|
6325
|
+
}
|
|
6326
|
+
timeoutId = setTimeout(() => this.handleMutations(), wait);
|
|
6327
|
+
};
|
|
6328
|
+
};
|
|
6329
|
+
const body = options;
|
|
6330
|
+
const data = body.data;
|
|
6331
|
+
this.readOnly = body.readOnly;
|
|
6332
|
+
this.placeholder = this.getPlaceholder(body.config);
|
|
6333
|
+
this.api = body.api;
|
|
6334
|
+
this.data = {
|
|
6335
|
+
id: data.id || generateId(),
|
|
6336
|
+
textBlocks: data.textBlocks || []
|
|
6337
|
+
};
|
|
6338
|
+
this.convertDefaultDataToCustom(data);
|
|
6339
|
+
}
|
|
6340
|
+
static get isInline() {
|
|
6341
|
+
return false;
|
|
6342
|
+
}
|
|
6343
|
+
static get isReadOnlySupported() {
|
|
6344
|
+
return true;
|
|
6345
|
+
}
|
|
6346
|
+
static get enableLineBreaks() {
|
|
6347
|
+
return false;
|
|
6348
|
+
}
|
|
6349
|
+
static get toolbox() {
|
|
6350
|
+
return {
|
|
6351
|
+
icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M8 9V7.2C8 7.08954 8.08954 7 8.2 7L12 7M16 9V7.2C16 7.08954 15.9105 7 15.8 7L12 7M12 7L12 17M12 17H10M12 17H14"></path></svg>',
|
|
6352
|
+
title: 'Text'
|
|
6353
|
+
};
|
|
6354
|
+
}
|
|
6355
|
+
static get pasteConfig() {
|
|
6356
|
+
return {
|
|
6357
|
+
tags: ['P']
|
|
6358
|
+
};
|
|
6359
|
+
}
|
|
6360
|
+
onPaste(event) {
|
|
6361
|
+
if (event.type !== 'tag') {
|
|
6362
|
+
return;
|
|
6363
|
+
}
|
|
6364
|
+
const text = event.detail.data.textContent;
|
|
6365
|
+
this.data.textBlocks.splice(this.data.textBlocks.length - 1, 1, this.getBlockPartObject(generateId(), text));
|
|
6366
|
+
this.update(this.data.textBlocks);
|
|
6367
|
+
}
|
|
6368
|
+
render() {
|
|
6369
|
+
this.wrapper = document.createElement('div');
|
|
6370
|
+
this.wrapper.classList.add(COMBINED_TEXT_BLOCK);
|
|
6371
|
+
this.wrapper.dataset[this.PLACEHOLDER_ATTRIBUTE_NAME] = this.api.i18n.t(this.placeholder);
|
|
6372
|
+
if (!this.readOnly) {
|
|
6373
|
+
this.wrapper.contentEditable = 'true';
|
|
6374
|
+
}
|
|
6375
|
+
if (!this.data.textBlocks.length) {
|
|
6376
|
+
this.data.textBlocks.push(this.getBlockPartObject(generateId(), ''));
|
|
6377
|
+
}
|
|
6378
|
+
this.update(this.data.textBlocks);
|
|
6379
|
+
this.checkIsEditorEmpty();
|
|
6380
|
+
if (!this.readOnly) {
|
|
6381
|
+
const callback = this.getMutationCallback(this.DEBOUNCE_TIME);
|
|
6382
|
+
this.observer = new MutationObserver(this.onMutationEvent.bind(this, callback));
|
|
6383
|
+
this.observer.observe(this.wrapper, this.mutationConfig);
|
|
6384
|
+
}
|
|
6385
|
+
return this.wrapper;
|
|
6386
|
+
}
|
|
6387
|
+
merge(blocksData) {
|
|
6388
|
+
if (!this.wrapper) {
|
|
6389
|
+
return;
|
|
6390
|
+
}
|
|
6391
|
+
let blocksTextContent = '';
|
|
6392
|
+
this.data.textBlocks = [];
|
|
6393
|
+
blocksData.forEach((block) => {
|
|
6394
|
+
blocksTextContent += block.data.text;
|
|
6395
|
+
});
|
|
6396
|
+
for (let i = 0; i < this.wrapper.childNodes.length; i++) {
|
|
6397
|
+
const node = this.wrapper.childNodes.item(i);
|
|
6398
|
+
if (!(node instanceof HTMLSpanElement)) {
|
|
6399
|
+
return;
|
|
6400
|
+
}
|
|
6401
|
+
i--;
|
|
6402
|
+
blocksTextContent = node.innerHTML + blocksTextContent;
|
|
6403
|
+
node.remove();
|
|
6404
|
+
}
|
|
6405
|
+
const parts = blocksTextContent.length < SPLIT_MAX_LENGTH ? [blocksTextContent] : splitHTML(blocksTextContent);
|
|
6406
|
+
parts.forEach((part) => {
|
|
6407
|
+
const blockObject = this.getBlockPartObject(generateId(), part);
|
|
6408
|
+
this.data.textBlocks.push(blockObject);
|
|
6409
|
+
});
|
|
6410
|
+
this.update(this.data.textBlocks);
|
|
6411
|
+
}
|
|
6412
|
+
save(blockContent) {
|
|
6413
|
+
const textBlocks = [];
|
|
6414
|
+
blockContent.querySelectorAll(this.TAG).forEach((span) => {
|
|
6415
|
+
textBlocks.push(this.getBlockPartObject(span.dataset['id'], span.innerHTML));
|
|
6416
|
+
});
|
|
6417
|
+
return textBlocks;
|
|
6418
|
+
}
|
|
6419
|
+
removed() {
|
|
6420
|
+
this.observer?.disconnect();
|
|
6421
|
+
const blockIds = new Set();
|
|
6422
|
+
this.data.textBlocks.forEach((block) => {
|
|
6423
|
+
blockIds.add(block.id || '');
|
|
6424
|
+
});
|
|
6425
|
+
this.removeBlocks(blockIds);
|
|
6426
|
+
}
|
|
6427
|
+
onMutationEvent(callback, mutationList) {
|
|
6428
|
+
if (mutationList.length === 0) {
|
|
6429
|
+
return;
|
|
6430
|
+
}
|
|
6431
|
+
mutationList.forEach((mutation) => {
|
|
6432
|
+
if (mutation.removedNodes.length) {
|
|
6433
|
+
this.changes.set(generateId(), mutation);
|
|
6434
|
+
return;
|
|
6435
|
+
}
|
|
6436
|
+
this.changes.set(mutation.target, mutation);
|
|
6437
|
+
});
|
|
6438
|
+
callback(mutationList);
|
|
6439
|
+
this.checkIsEditorEmpty();
|
|
6440
|
+
}
|
|
6441
|
+
handleMutations() {
|
|
6442
|
+
const mutationsList = [...this.changes.values()];
|
|
6443
|
+
const { updatedElements, removedElementsIds } = this.getMutationActions(mutationsList);
|
|
6444
|
+
const splitedParts = [];
|
|
6445
|
+
updatedElements.forEach((element) => {
|
|
6446
|
+
const elementContent = element.innerHTML;
|
|
6447
|
+
if (elementContent.length < SPLIT_MAX_LENGTH) {
|
|
6448
|
+
return;
|
|
6449
|
+
}
|
|
6450
|
+
const parts = splitHTML(elementContent);
|
|
6451
|
+
parts.forEach((part, index) => {
|
|
6452
|
+
if (index === 0) {
|
|
6453
|
+
return;
|
|
6454
|
+
}
|
|
6455
|
+
const blockId = generateId();
|
|
6456
|
+
const textElement = this.createBlock(blockId, part);
|
|
6457
|
+
splitedParts.push(textElement);
|
|
6458
|
+
});
|
|
6459
|
+
element.innerHTML = parts[0];
|
|
6460
|
+
element.after(...splitedParts);
|
|
6461
|
+
});
|
|
6462
|
+
this.addBlocks(splitedParts, updatedElements);
|
|
6463
|
+
this.updateBlocks(updatedElements);
|
|
6464
|
+
this.removeBlocks(removedElementsIds);
|
|
6465
|
+
this.changes.clear();
|
|
6466
|
+
}
|
|
6467
|
+
getNextIndex() {
|
|
6468
|
+
recalculateIndexes(this.api.blocks);
|
|
6469
|
+
const index = this.api.blocks.getCurrentBlockIndex();
|
|
6470
|
+
const block = this.api.blocks.getBlockByIndex(index);
|
|
6471
|
+
const dataIndex = Number(block?.holder.dataset['index']);
|
|
6472
|
+
const selection = window.getSelection();
|
|
6473
|
+
const range = selection?.rangeCount ? selection.getRangeAt(0) : null;
|
|
6474
|
+
const caretPosition = range?.startOffset ?? 1;
|
|
6475
|
+
let nextBlockIndex = dataIndex;
|
|
6476
|
+
if (caretPosition !== 0) {
|
|
6477
|
+
const blockContainer = block?.holder.querySelector('.' + COMBINED_TEXT_BLOCK);
|
|
6478
|
+
const childrenCount = blockContainer?.children?.length ? blockContainer?.children?.length - 1 : 0;
|
|
6479
|
+
nextBlockIndex = dataIndex + childrenCount + 1;
|
|
6480
|
+
}
|
|
6481
|
+
if (!nextBlockIndex) {
|
|
6482
|
+
nextBlockIndex ||= 0;
|
|
6483
|
+
}
|
|
6484
|
+
return nextBlockIndex;
|
|
6485
|
+
}
|
|
6486
|
+
getBlockPartObject(blockId, text) {
|
|
6487
|
+
return {
|
|
6488
|
+
id: blockId,
|
|
6489
|
+
type: COMBINED_TEXT_BLOCK_PART,
|
|
6490
|
+
data: {
|
|
6491
|
+
text,
|
|
6492
|
+
parentId: this.data.id,
|
|
6493
|
+
parentType: COMBINED_TEXT_BLOCK_NAME
|
|
6494
|
+
}
|
|
6495
|
+
};
|
|
6496
|
+
}
|
|
6497
|
+
getMutationActions(mutationList) {
|
|
6498
|
+
const updatedElements = new Set();
|
|
6499
|
+
const removedElementsIds = new Set();
|
|
6500
|
+
const changedOutsideElements = [];
|
|
6501
|
+
this.lastBlockElement = undefined;
|
|
6502
|
+
mutationList.forEach((mutation) => {
|
|
6503
|
+
this.handleUpdatedBlocks(mutation, updatedElements, changedOutsideElements);
|
|
6504
|
+
this.handleRemovedBlocks(mutation, removedElementsIds);
|
|
6505
|
+
});
|
|
6506
|
+
if (this.lastBlockElement) {
|
|
6507
|
+
const lastBlockElement = this.lastBlockElement;
|
|
6508
|
+
lastBlockElement.append(...changedOutsideElements);
|
|
6509
|
+
this.setCaretToBlocksEnd(lastBlockElement);
|
|
6510
|
+
}
|
|
6511
|
+
return {
|
|
6512
|
+
updatedElements,
|
|
6513
|
+
removedElementsIds
|
|
6514
|
+
};
|
|
6515
|
+
}
|
|
6516
|
+
setCaretToBlocksEnd(block) {
|
|
6517
|
+
const selection = window.getSelection();
|
|
6518
|
+
const range = document.createRange();
|
|
6519
|
+
range.setStart(block, block.childNodes.length);
|
|
6520
|
+
selection?.removeAllRanges();
|
|
6521
|
+
selection?.addRange(range);
|
|
6522
|
+
}
|
|
6523
|
+
handleUpdatedBlocks(mutation, updatedElements, outsideChanges) {
|
|
6524
|
+
let element = mutation.target;
|
|
6525
|
+
if (mutation.target.nodeType === Node.TEXT_NODE) {
|
|
6526
|
+
element = mutation.target.parentElement;
|
|
6527
|
+
}
|
|
6528
|
+
const span = element?.closest('.' + COMBINED_TEXT_BLOCK_PART);
|
|
6529
|
+
if (span) {
|
|
6530
|
+
updatedElements.add(span);
|
|
6531
|
+
return;
|
|
6532
|
+
}
|
|
6533
|
+
this.handleChangesOutsideBlock(element, outsideChanges);
|
|
6534
|
+
}
|
|
6535
|
+
handleChangesOutsideBlock(element, outsideChanges) {
|
|
6536
|
+
if (!element || this.lastBlockElement) {
|
|
6537
|
+
return;
|
|
6538
|
+
}
|
|
6539
|
+
element.childNodes.forEach((block) => {
|
|
6540
|
+
const blockElement = block;
|
|
6541
|
+
if (blockElement.classList?.contains(COMBINED_TEXT_BLOCK_PART)) {
|
|
6542
|
+
this.lastBlockElement = blockElement;
|
|
6543
|
+
return;
|
|
6544
|
+
}
|
|
6545
|
+
outsideChanges.push(block);
|
|
6546
|
+
});
|
|
6547
|
+
}
|
|
6548
|
+
addBlocks(splicedParts, updatedElements) {
|
|
6549
|
+
if (!splicedParts.length) {
|
|
6550
|
+
return;
|
|
6551
|
+
}
|
|
6552
|
+
const addedBlocks = splicedParts.map((block) => {
|
|
6553
|
+
const blockId = block.dataset['id'];
|
|
6554
|
+
return {
|
|
6555
|
+
id: blockId,
|
|
6556
|
+
type: COMBINED_TEXT_BLOCK_PART,
|
|
6557
|
+
data: {
|
|
6558
|
+
text: block.innerHTML,
|
|
6559
|
+
parentId: this.data.id,
|
|
6560
|
+
parentType: COMBINED_TEXT_BLOCK_NAME
|
|
6561
|
+
}
|
|
6562
|
+
};
|
|
6563
|
+
});
|
|
6564
|
+
const previousElement = updatedElements.values().next().value;
|
|
6565
|
+
const id = previousElement?.dataset['id'];
|
|
6566
|
+
const index = Number(previousElement?.dataset['index']) + 1;
|
|
6567
|
+
const blockIndex = this.data.textBlocks.findIndex((block) => block.id === id);
|
|
6568
|
+
this.data.textBlocks.splice(blockIndex, 0, ...addedBlocks);
|
|
6569
|
+
this.api.events.emit(COMBINED_TEXT_BLOCK_ADDED, {
|
|
6570
|
+
index,
|
|
6571
|
+
blockIndex,
|
|
6572
|
+
blocks: addedBlocks,
|
|
6573
|
+
data: this.data.textBlocks
|
|
6574
|
+
});
|
|
6575
|
+
}
|
|
6576
|
+
updateBlocks(updatedElements) {
|
|
6577
|
+
if (!updatedElements.size) {
|
|
6578
|
+
return;
|
|
6579
|
+
}
|
|
6580
|
+
const updatedBlocks = [...updatedElements.values()].map((block) => {
|
|
6581
|
+
return {
|
|
6582
|
+
id: block.dataset['id'],
|
|
6583
|
+
type: COMBINED_TEXT_BLOCK_PART,
|
|
6584
|
+
data: {
|
|
6585
|
+
text: block.innerHTML,
|
|
6586
|
+
parentId: this.data.id,
|
|
6587
|
+
parentType: COMBINED_TEXT_BLOCK_NAME
|
|
6588
|
+
}
|
|
6589
|
+
};
|
|
6590
|
+
});
|
|
6591
|
+
this.api.events.emit(COMBINED_TEXT_BLOCK_UPDATED, updatedBlocks);
|
|
6592
|
+
}
|
|
6593
|
+
handleRemovedBlocks(mutation, removedElementsIds) {
|
|
6594
|
+
if (mutation.removedNodes.length === 0) {
|
|
6595
|
+
return;
|
|
6596
|
+
}
|
|
6597
|
+
mutation.removedNodes.forEach((node) => {
|
|
6598
|
+
if (!(node instanceof HTMLElement)) {
|
|
6599
|
+
return;
|
|
6600
|
+
}
|
|
6601
|
+
const blockId = node.dataset['id'];
|
|
6602
|
+
if (!blockId) {
|
|
6603
|
+
return;
|
|
6604
|
+
}
|
|
6605
|
+
removedElementsIds.add(blockId);
|
|
6606
|
+
});
|
|
6607
|
+
}
|
|
6608
|
+
removeBlocks(ids) {
|
|
6609
|
+
if (!ids.size) {
|
|
6610
|
+
return;
|
|
6611
|
+
}
|
|
6612
|
+
const removedElementIds = [...ids.values()];
|
|
6613
|
+
this.data.textBlocks = this.data.textBlocks.filter((block) => !ids.has(block.id || ''));
|
|
6614
|
+
this.api.events.emit(COMBINED_TEXT_BLOCK_REMOVED, removedElementIds);
|
|
6615
|
+
}
|
|
6616
|
+
update(blocks) {
|
|
6617
|
+
if (!blocks.length) {
|
|
6618
|
+
return;
|
|
6619
|
+
}
|
|
6620
|
+
blocks.forEach((block) => {
|
|
6621
|
+
const textElement = this.createBlock(block.id || generateId(), block.data.text);
|
|
6622
|
+
if (!this.wrapper) {
|
|
6623
|
+
return;
|
|
6624
|
+
}
|
|
6625
|
+
if (this.wrapper.querySelector('.' + COMBINED_TEXT_BLOCK_PART)) {
|
|
6626
|
+
this.wrapper.append(textElement);
|
|
6627
|
+
return;
|
|
6628
|
+
}
|
|
6629
|
+
this.wrapper.replaceChildren(textElement);
|
|
6630
|
+
});
|
|
6631
|
+
setTimeout(() => {
|
|
6632
|
+
this.api.events.emit(COMBINED_TEXT_BLOCK_ADDED, {
|
|
6633
|
+
blocks
|
|
6634
|
+
});
|
|
6635
|
+
});
|
|
6636
|
+
}
|
|
6637
|
+
createBlock(id, text) {
|
|
6638
|
+
const textElement = document.createElement(this.TAG);
|
|
6639
|
+
textElement.classList.add(COMBINED_TEXT_BLOCK_PART);
|
|
6640
|
+
textElement.innerHTML = text;
|
|
6641
|
+
textElement.dataset['id'] = id;
|
|
6642
|
+
return textElement;
|
|
6643
|
+
}
|
|
6644
|
+
convertDefaultDataToCustom(data) {
|
|
6645
|
+
if (Array.isArray(data)) {
|
|
6646
|
+
this.data.textBlocks = data.map((block) => {
|
|
6647
|
+
block.id = generateId();
|
|
6648
|
+
block.data.parentId = this.data.id;
|
|
6649
|
+
return block;
|
|
6650
|
+
});
|
|
6651
|
+
}
|
|
6652
|
+
if (!data.text) {
|
|
6653
|
+
return;
|
|
6654
|
+
}
|
|
6655
|
+
const fragment = document.createRange().createContextualFragment(data.text);
|
|
6656
|
+
let elementContent = '';
|
|
6657
|
+
fragment.childNodes.forEach((node) => {
|
|
6658
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
6659
|
+
elementContent += node.textContent;
|
|
6660
|
+
return;
|
|
6661
|
+
}
|
|
6662
|
+
elementContent += node.innerHTML;
|
|
6663
|
+
});
|
|
6664
|
+
const parts = elementContent.length < SPLIT_MAX_LENGTH ? [elementContent] : splitHTML(elementContent);
|
|
6665
|
+
parts.forEach((part) => {
|
|
6666
|
+
const blockObject = this.getBlockPartObject(generateId(), part);
|
|
6667
|
+
this.data.textBlocks.push(blockObject);
|
|
6668
|
+
});
|
|
6669
|
+
}
|
|
6670
|
+
checkIsEditorEmpty() {
|
|
6671
|
+
if (!this.wrapper || this.wrapper.children.length > this.MAX_CHILD_COUNT_FOR_EMPTY) {
|
|
6672
|
+
return;
|
|
6673
|
+
}
|
|
6674
|
+
const item = this.wrapper.children.item(0);
|
|
6675
|
+
const isItemEmpty = !item.textContent?.length;
|
|
6676
|
+
this.wrapper.dataset['empty'] = `${isItemEmpty}`;
|
|
6677
|
+
}
|
|
6678
|
+
getPlaceholder(config) {
|
|
6679
|
+
if (this.readOnly) {
|
|
6680
|
+
return config.readonlyPlaceholder ?? DEFAULT_READONLY_PLACEHOLDER;
|
|
6681
|
+
}
|
|
6682
|
+
return config.placeholder ?? DEFAULT_PLACEHOLDER;
|
|
6683
|
+
}
|
|
6684
|
+
}
|
|
6685
|
+
|
|
6686
|
+
const getEditorConfig = (id, config = DEFAULT_CONFIG) => ({
|
|
6687
|
+
holder: id,
|
|
6688
|
+
logLevel: 'ERROR',
|
|
6689
|
+
readOnly: config.readOnly,
|
|
6690
|
+
autofocus: config.autofocus,
|
|
6691
|
+
tools: {
|
|
6692
|
+
paragraph: {
|
|
6693
|
+
class: CuiCombinedTextBlockTool,
|
|
6694
|
+
inlineToolbar: true,
|
|
6695
|
+
config: {
|
|
6696
|
+
placeholder: config.placeholder,
|
|
6697
|
+
readonlyPlaceholder: config.readonlyPlaceholder
|
|
6698
|
+
}
|
|
6699
|
+
},
|
|
6700
|
+
link: {
|
|
6701
|
+
class: CuiLinkMarker
|
|
6702
|
+
},
|
|
6703
|
+
bold: {
|
|
6704
|
+
class: CuiBoldInlineTool
|
|
6705
|
+
},
|
|
6706
|
+
italic: {
|
|
6707
|
+
class: CuiItalicInlineTool
|
|
6708
|
+
},
|
|
6709
|
+
...config.tools
|
|
6710
|
+
},
|
|
6711
|
+
defaultBlock: COMBINED_TEXT_BLOCK_NAME
|
|
6712
|
+
});
|
|
6713
|
+
|
|
6714
|
+
const EDITOR_CUSTOM_ELEMENTS = [
|
|
6715
|
+
{
|
|
6716
|
+
selector: EDITOR_TOOLTIP_SELECTOR,
|
|
6717
|
+
component: EditorTooltipComponent
|
|
6718
|
+
},
|
|
6719
|
+
{
|
|
6720
|
+
selector: MARKER_SELECT_SELECTOR,
|
|
6721
|
+
component: MarkerSelectComponent
|
|
6722
|
+
},
|
|
6723
|
+
{
|
|
6724
|
+
selector: EDITOR_TOOL_MODAL_SELECTOR,
|
|
6725
|
+
component: EditorToolModalComponent
|
|
6726
|
+
},
|
|
6727
|
+
{
|
|
6728
|
+
selector: MARKER_MODAL_SELECTOR,
|
|
6729
|
+
component: MarkerModalComponent
|
|
6730
|
+
},
|
|
6731
|
+
{
|
|
6732
|
+
selector: EDITOR_VIDEO_TOOL_SELECTOR,
|
|
6733
|
+
component: EditorVideoToolComponent
|
|
6734
|
+
},
|
|
6735
|
+
{
|
|
6736
|
+
selector: EDITOR_IMAGE_TOOL_SELECTOR,
|
|
6737
|
+
component: EditorImageToolComponent
|
|
6738
|
+
},
|
|
6739
|
+
{
|
|
6740
|
+
selector: EDITOR_ATTACHES_TOOL_SELECTOR,
|
|
6741
|
+
component: EditorAttachesToolComponent
|
|
6742
|
+
}
|
|
6743
|
+
];
|
|
6744
|
+
|
|
6745
|
+
function cuiProvideEditor() {
|
|
6746
|
+
return [
|
|
6747
|
+
{
|
|
6748
|
+
provide: APP_INITIALIZER,
|
|
6749
|
+
useFactory: (injector) => () => {
|
|
6750
|
+
EDITOR_CUSTOM_ELEMENTS.forEach(({ component, selector }) => {
|
|
6751
|
+
const element = createCustomElement(component, { injector });
|
|
6752
|
+
window.customElements.define(selector, element);
|
|
6753
|
+
});
|
|
6754
|
+
},
|
|
6755
|
+
deps: [Injector],
|
|
6756
|
+
multi: true,
|
|
6757
|
+
},
|
|
6758
|
+
];
|
|
6759
|
+
}
|
|
6760
|
+
|
|
6761
|
+
function setEditorDragEvents(editorElement, signal) {
|
|
6762
|
+
editorElement.addEventListener('dragstart', dragstartListener, { signal });
|
|
6763
|
+
}
|
|
6764
|
+
function dragstartListener(event) {
|
|
6765
|
+
event.preventDefault();
|
|
6766
|
+
}
|
|
6767
|
+
|
|
6768
|
+
const FIRST_CHILD_SELECTOR = '_selected';
|
|
6769
|
+
function setEditorKeyboardEvents(editorElement, signal) {
|
|
6770
|
+
editorElement.addEventListener('keydown', keydownListener, { signal });
|
|
6771
|
+
}
|
|
6772
|
+
function keydownListener(event) {
|
|
6773
|
+
const target = event.target;
|
|
6774
|
+
const block = target.closest(`.${COMBINED_TEXT_BLOCK}`);
|
|
6775
|
+
if (!block) {
|
|
6776
|
+
return;
|
|
6777
|
+
}
|
|
6778
|
+
const selection = window.getSelection();
|
|
6779
|
+
const ranges = selection?.rangeCount;
|
|
6780
|
+
if (!ranges || !checkIsBlockFullySelected(block)) {
|
|
6781
|
+
return;
|
|
6782
|
+
}
|
|
6783
|
+
const firstChild = block?.firstElementChild;
|
|
6784
|
+
firstChild?.classList.add(FIRST_CHILD_SELECTOR);
|
|
6785
|
+
setTimeout(() => firstChild?.classList.remove(FIRST_CHILD_SELECTOR));
|
|
6786
|
+
}
|
|
6787
|
+
function checkIsBlockFullySelected(blockElement) {
|
|
6788
|
+
const selection = window.getSelection();
|
|
6789
|
+
if (!selection || selection.rangeCount === 0) {
|
|
6790
|
+
return false;
|
|
6791
|
+
}
|
|
6792
|
+
const range = selection.getRangeAt(0);
|
|
6793
|
+
const startBlock = range.startContainer.parentElement?.closest('.' + COMBINED_TEXT_BLOCK_PART);
|
|
6794
|
+
const endBlock = range.endContainer.parentElement?.closest('.' + COMBINED_TEXT_BLOCK_PART);
|
|
6795
|
+
const isStartAtBlockStart = startBlock === blockElement.firstChild && range.startOffset === 0;
|
|
6796
|
+
const isEndAtBlockEnd = endBlock === blockElement.lastChild;
|
|
6797
|
+
return isStartAtBlockStart && isEndAtBlockEnd;
|
|
6798
|
+
}
|
|
6799
|
+
|
|
6800
|
+
function setEditorInfoModalEvents(editorElement, signal) {
|
|
6801
|
+
editorElement?.addEventListener('pointerup', pointerUpListener, { signal });
|
|
6802
|
+
}
|
|
6803
|
+
function pointerUpListener(event) {
|
|
6804
|
+
const selection = window.getSelection();
|
|
6805
|
+
if (selection && selection.toString().length > 0) {
|
|
6806
|
+
return;
|
|
6807
|
+
}
|
|
6808
|
+
const target = event.target;
|
|
6809
|
+
const marker = target.closest('.marker');
|
|
6810
|
+
if (!marker) {
|
|
6811
|
+
return;
|
|
6812
|
+
}
|
|
6813
|
+
onMarkerClick(marker);
|
|
6814
|
+
}
|
|
6815
|
+
function onMarkerClick(marker) {
|
|
6816
|
+
const id = marker.dataset['id'];
|
|
6817
|
+
const type = marker.dataset['type'];
|
|
6818
|
+
if (!(id && type)) {
|
|
6819
|
+
return;
|
|
6820
|
+
}
|
|
6821
|
+
const toolModal = document.createElement(EDITOR_TOOL_MODAL_SELECTOR);
|
|
6822
|
+
toolModal.tool = { id, type, title: 'Молоток КУБИПРО Ультра MAX 3000' };
|
|
6823
|
+
toolModal.marker = marker;
|
|
6824
|
+
toolModal.addEventListener('closed', function onCloseModal() {
|
|
6825
|
+
toolModal.remove();
|
|
6826
|
+
});
|
|
6827
|
+
document.body.append(toolModal);
|
|
6828
|
+
}
|
|
6829
|
+
|
|
6830
|
+
const TOOLTIP_POSITION_X = 5;
|
|
6831
|
+
const TOOLTIP_POSITION_Y = 40;
|
|
6832
|
+
const TOOLTIP_SAFE_RIGHT_SHIFT = 10;
|
|
6833
|
+
const TOOLTIP_DEBOUNCE_TIME = 500;
|
|
6834
|
+
const CLOSE_TOOLTIP_DEBOUNCE_TIME = 50;
|
|
6835
|
+
let tooltip;
|
|
6836
|
+
let timeoutId;
|
|
6837
|
+
let closeTimeoutId;
|
|
6838
|
+
const closeTooltipHandler = () => closeTooltip();
|
|
6839
|
+
function closeTooltip(callback) {
|
|
6840
|
+
clearTimeout(closeTimeoutId);
|
|
6841
|
+
closeTimeoutId = setTimeout(() => {
|
|
6842
|
+
clearTimeout(timeoutId);
|
|
6843
|
+
tooltip?.remove();
|
|
6844
|
+
callback?.();
|
|
6845
|
+
}, CLOSE_TOOLTIP_DEBOUNCE_TIME);
|
|
6846
|
+
}
|
|
6847
|
+
const debouncedEvent = (event, marker, target) => {
|
|
6848
|
+
clearTimeout(timeoutId);
|
|
6849
|
+
timeoutId = setTimeout(() => {
|
|
6850
|
+
if (tooltip && tooltip?.contains(target)) {
|
|
6851
|
+
return;
|
|
6852
|
+
}
|
|
6853
|
+
closeTooltip(() => openTooltip(event, marker));
|
|
6854
|
+
}, TOOLTIP_DEBOUNCE_TIME);
|
|
6855
|
+
};
|
|
6856
|
+
function openTooltip(event, marker) {
|
|
6857
|
+
const type = marker.tagName;
|
|
6858
|
+
tooltip = tooltipMap[type](marker);
|
|
6859
|
+
tooltip.style.visibility = 'hidden';
|
|
6860
|
+
document.body.append(tooltip);
|
|
6861
|
+
setTimeout(() => {
|
|
6862
|
+
const positionX = event.clientX;
|
|
6863
|
+
const positionY = event.clientY;
|
|
6864
|
+
const rightX = document.documentElement.clientWidth - positionX;
|
|
6865
|
+
const rightShiftDiffX = tooltip.offsetWidth - rightX;
|
|
6866
|
+
const rightShiftX = rightShiftDiffX > 0 ? rightShiftDiffX + TOOLTIP_SAFE_RIGHT_SHIFT : 0;
|
|
6867
|
+
tooltip.style.top = positionY - TOOLTIP_POSITION_Y + 'px';
|
|
6868
|
+
tooltip.style.left = positionX + TOOLTIP_POSITION_X - rightShiftX + 'px';
|
|
6869
|
+
tooltip.style.visibility = 'visible';
|
|
6870
|
+
});
|
|
6871
|
+
}
|
|
6872
|
+
function setEditorTooltipEvents(signal) {
|
|
6873
|
+
document.body.addEventListener('mousemove', mouseMoveListener, { signal });
|
|
6874
|
+
document.body.addEventListener('mouseleave', closeTooltipHandler, { signal });
|
|
6875
|
+
}
|
|
6876
|
+
function mouseMoveListener(event) {
|
|
6877
|
+
const target = event.target;
|
|
6878
|
+
const marker = target.closest('.marker');
|
|
6879
|
+
if (tooltip?.contains(target)) {
|
|
6880
|
+
clearTimeout(timeoutId);
|
|
6881
|
+
clearTimeout(closeTimeoutId);
|
|
6882
|
+
return;
|
|
6883
|
+
}
|
|
6884
|
+
if (!marker) {
|
|
6885
|
+
closeTooltip();
|
|
6886
|
+
return;
|
|
6887
|
+
}
|
|
6888
|
+
clearTimeout(closeTimeoutId);
|
|
6889
|
+
debouncedEvent(event, marker, target);
|
|
6890
|
+
}
|
|
6891
|
+
|
|
6892
|
+
function setEditorEvents(editorElement, signal) {
|
|
6893
|
+
setEditorTooltipEvents(signal);
|
|
6894
|
+
setEditorInfoModalEvents(editorElement, signal);
|
|
6895
|
+
setEditorDragEvents(editorElement, signal);
|
|
6896
|
+
setEditorKeyboardEvents(editorElement, signal);
|
|
6897
|
+
}
|
|
6898
|
+
|
|
6899
|
+
class CuiEditorComponent {
|
|
6900
|
+
constructor() {
|
|
6901
|
+
this.destroy = inject(DestroyRef);
|
|
6902
|
+
this.editorService = inject(CuiEditorService);
|
|
6903
|
+
this.jTextService = inject(CuiJTextApiService);
|
|
6904
|
+
this.POOLING_DELAY = 100;
|
|
6905
|
+
this.ELEMENT_SPACE_TO_BOTTOM = 150;
|
|
6906
|
+
this.SCROLL_THROTTLE_TIME = 200;
|
|
6907
|
+
this.isReadonly = computed(() => this.config?.readOnly);
|
|
6908
|
+
this.emptyQueue = new Subject();
|
|
6909
|
+
this.editorEmpty = new EventEmitter();
|
|
6910
|
+
this.config = DEFAULT_CONFIG;
|
|
6911
|
+
this.requestSize = 40;
|
|
6912
|
+
this.isSkipCombinedBlockOnChange = [];
|
|
6913
|
+
this.isFirst = true;
|
|
6914
|
+
this.isChanging = false;
|
|
6915
|
+
this.isSkip = false;
|
|
6916
|
+
this.isRequested = false;
|
|
6917
|
+
this.isDestroyed = false;
|
|
6918
|
+
this.blockIdsMap = new Map();
|
|
6919
|
+
this.combinedBlocks = new Map();
|
|
6920
|
+
this.index = 0;
|
|
6921
|
+
this.page = 0;
|
|
6922
|
+
this.addedBlocks = [];
|
|
6923
|
+
this.updatedBlocks = [];
|
|
6924
|
+
this.removedBlocksIds = [];
|
|
6925
|
+
this.changesQueue = [];
|
|
6926
|
+
this.abortController = new AbortController();
|
|
6927
|
+
}
|
|
6928
|
+
ngOnChanges(changes) {
|
|
6929
|
+
if (changes['editorID'] || changes['config']) {
|
|
6930
|
+
this.initEditorChanges();
|
|
6931
|
+
}
|
|
6932
|
+
}
|
|
6933
|
+
ngOnDestroy() {
|
|
6934
|
+
this.isDestroyed = true;
|
|
6935
|
+
this.destroyEditor();
|
|
6936
|
+
}
|
|
6937
|
+
onScrollEvent(element) {
|
|
6938
|
+
const overallHeight = element.scrollHeight - this.ELEMENT_SPACE_TO_BOTTOM;
|
|
6939
|
+
const currentHeight = element.scrollTop + element.clientHeight;
|
|
6940
|
+
if (currentHeight < overallHeight || this.isRequested) {
|
|
6941
|
+
return;
|
|
6942
|
+
}
|
|
6943
|
+
this.isRequested = true;
|
|
6944
|
+
const size = this.requestSize;
|
|
6945
|
+
let blocksCount = 0;
|
|
6946
|
+
this.getBlocks(this.page, size)
|
|
6947
|
+
.pipe(tap((blocks) => (blocksCount = blocks.length)), finalize(() => {
|
|
6948
|
+
this.isRequested = false;
|
|
6949
|
+
if (blocksCount >= size) {
|
|
6950
|
+
return;
|
|
6951
|
+
}
|
|
6952
|
+
this.scrollSubscription.unsubscribe();
|
|
6953
|
+
}))
|
|
6954
|
+
.subscribe();
|
|
6955
|
+
this.page++;
|
|
6956
|
+
}
|
|
6957
|
+
async onEditorChange(_, event) {
|
|
6958
|
+
if (this.isReadonly()) {
|
|
6959
|
+
return;
|
|
6960
|
+
}
|
|
6961
|
+
if (!Array.isArray(event)) {
|
|
6962
|
+
event = [event];
|
|
6963
|
+
}
|
|
6964
|
+
recalculateIndexes(this.editor.blocks);
|
|
6965
|
+
if (this.isChanging) {
|
|
6966
|
+
this.changesQueue.unshift(event);
|
|
6967
|
+
}
|
|
6968
|
+
this.startChanges(event);
|
|
6969
|
+
this.editorEmpty.emit(this.checkIsEmpty());
|
|
6970
|
+
}
|
|
6971
|
+
onAddedCombinedBlock(data) {
|
|
6972
|
+
if (this.isSkipCombinedBlockOnChange.length) {
|
|
6973
|
+
this.isSkipCombinedBlockOnChange.pop();
|
|
6974
|
+
return;
|
|
6975
|
+
}
|
|
6976
|
+
const blocksWithoutId = data.blocks.map((block) => ({
|
|
6977
|
+
block: { ...block, id: undefined },
|
|
6978
|
+
id: block.id
|
|
6979
|
+
}));
|
|
6980
|
+
this.addedBlocks.push(...blocksWithoutId);
|
|
6981
|
+
}
|
|
6982
|
+
onUpdatedCombinedBlock(updatedBlocks) {
|
|
6983
|
+
if (!updatedBlocks.length) {
|
|
6984
|
+
return;
|
|
6985
|
+
}
|
|
6986
|
+
this.updatedBlocks.push(...updatedBlocks);
|
|
6987
|
+
}
|
|
6988
|
+
onRemovedCombinedBlock(blockIds) {
|
|
6989
|
+
if (!blockIds.length) {
|
|
6990
|
+
return;
|
|
6991
|
+
}
|
|
6992
|
+
this.removedBlocksIds.push(...blockIds);
|
|
6993
|
+
}
|
|
6994
|
+
initEditorChanges() {
|
|
6995
|
+
this.jTextService.addOptions(this.config.requestOptions);
|
|
6996
|
+
this.editor = this.initEditor(this.editorID);
|
|
6997
|
+
this.editor.isReady.then(() => {
|
|
6998
|
+
this.editorElement = this.editorRef.nativeElement;
|
|
6999
|
+
this.initEditorEvents(this.editorElement);
|
|
7000
|
+
this.initScrollObserver();
|
|
7001
|
+
this.startPooling(this.requestSize);
|
|
7002
|
+
this.setListenersOnCustomBlockChanges();
|
|
7003
|
+
});
|
|
7004
|
+
}
|
|
7005
|
+
initEditor(id) {
|
|
7006
|
+
const config = this.config;
|
|
7007
|
+
this.destroyEditor();
|
|
7008
|
+
this.editor = new EditorJS({
|
|
7009
|
+
...getEditorConfig(id, config),
|
|
7010
|
+
onChange: this.onEditorChange.bind(this)
|
|
7011
|
+
});
|
|
7012
|
+
return this.editor;
|
|
7013
|
+
}
|
|
7014
|
+
initScrollObserver() {
|
|
7015
|
+
const element = this.config?.element ?? this.editorElement;
|
|
7016
|
+
const scrollObserver = fromEvent(element, 'scroll');
|
|
7017
|
+
this.scrollSubscription = scrollObserver
|
|
7018
|
+
.pipe(takeUntilDestroyed(this.destroy), throttleTime(this.SCROLL_THROTTLE_TIME, undefined, {
|
|
7019
|
+
leading: true,
|
|
7020
|
+
trailing: true
|
|
7021
|
+
}), map(() => this.onScrollEvent(element)))
|
|
7022
|
+
.subscribe();
|
|
7023
|
+
}
|
|
7024
|
+
initEditorEvents(element) {
|
|
7025
|
+
const readOnly = this.isReadonly();
|
|
7026
|
+
if (readOnly) {
|
|
7027
|
+
return;
|
|
7028
|
+
}
|
|
7029
|
+
setEditorEvents(element, this.abortController.signal);
|
|
7030
|
+
}
|
|
7031
|
+
startPooling(size) {
|
|
7032
|
+
const scrollElement = this.config?.element ?? this.editorElement;
|
|
7033
|
+
const withoutPreload = this.config?.withoutPreload;
|
|
7034
|
+
this.poolingSubscription = timer(0, this.POOLING_DELAY)
|
|
7035
|
+
.pipe(concatMap(() => this.getBlocks(this.page, size).pipe(delay(this.POOLING_DELAY))), tap(() => this.page++), takeWhile((blocks) => !withoutPreload &&
|
|
7036
|
+
scrollElement.scrollHeight <= scrollElement.clientHeight &&
|
|
7037
|
+
blocks.length >= size), finalize(() => {
|
|
7038
|
+
if (this.isDestroyed) {
|
|
7039
|
+
return;
|
|
7040
|
+
}
|
|
7041
|
+
this.setStartBlock();
|
|
7042
|
+
}))
|
|
7043
|
+
.subscribe();
|
|
7044
|
+
}
|
|
7045
|
+
destroyEditor() {
|
|
7046
|
+
this.abortController.abort();
|
|
7047
|
+
this.resetData();
|
|
7048
|
+
// TODO: в рандом кейсах падает ошибка если убрать проверку на вызов destroy
|
|
7049
|
+
this.editor?.destroy?.();
|
|
7050
|
+
}
|
|
7051
|
+
setListenersOnCustomBlockChanges() {
|
|
7052
|
+
this.editorService.setListenersOnCustomBlockChanges(this.editor, {
|
|
7053
|
+
removedCallback: this.onRemovedCombinedBlock.bind(this),
|
|
7054
|
+
updatedCallback: this.onUpdatedCombinedBlock.bind(this),
|
|
7055
|
+
addedCallback: this.onAddedCombinedBlock.bind(this)
|
|
7056
|
+
});
|
|
7057
|
+
}
|
|
7058
|
+
async startChanges(event) {
|
|
7059
|
+
if (this.isSkip || this.isChanging || !this.editor) {
|
|
7060
|
+
this.isSkip = false;
|
|
7061
|
+
return;
|
|
7062
|
+
}
|
|
7063
|
+
this.isChanging = true;
|
|
7064
|
+
const editorOutput = await this.editor.save();
|
|
7065
|
+
const events = event.filter((data) => data.detail.target.name !== COMBINED_TEXT_BLOCK_NAME);
|
|
7066
|
+
const blocks = this.editorService.sortEventsByTypes(events);
|
|
7067
|
+
const { addBlocks$, addedBlocks } = this.collectAddedBlocksRequest(blocks, editorOutput);
|
|
7068
|
+
this.addedBlocks = [];
|
|
7069
|
+
addBlocks$
|
|
7070
|
+
.pipe(tap((blockIds) => this.setBlockIdsToMap(blockIds, addedBlocks)), concatMap(() => this.collectUpdatedBlocksRequest(blocks, editorOutput)), concatMap(() => this.collectRemovedBlocksRequest(blocks)))
|
|
7071
|
+
.subscribe({
|
|
7072
|
+
complete: () => this.startNextChange(),
|
|
7073
|
+
error: () => this.startNextChange()
|
|
7074
|
+
});
|
|
7075
|
+
}
|
|
7076
|
+
startNextChange() {
|
|
7077
|
+
this.isChanging = false;
|
|
7078
|
+
const nextEvents = this.changesQueue.pop();
|
|
7079
|
+
if (nextEvents) {
|
|
7080
|
+
this.startChanges(nextEvents);
|
|
7081
|
+
}
|
|
7082
|
+
this.emptyQueue.next(null);
|
|
7083
|
+
}
|
|
7084
|
+
collectAddedBlocksRequest(blocks, editorOutput) {
|
|
7085
|
+
const defaultBlocksWithIndex = blocks["block-added" /* EventActions.add */].map((addedBlock) => this.editorService.getFullBlockData(addedBlock, editorOutput));
|
|
7086
|
+
const combinedBlocksWithIndex = this.addedBlocks.map((block) => {
|
|
7087
|
+
const element = this.editorElement.querySelector(`[data-id="${block.id}"]`);
|
|
7088
|
+
const index = Number(element?.dataset['index']);
|
|
7089
|
+
return { ...block, index };
|
|
7090
|
+
});
|
|
7091
|
+
const addedBlocks = [...defaultBlocksWithIndex, ...combinedBlocksWithIndex].sort((first, second) => first.index - second.index);
|
|
7092
|
+
const addBlocks$ = this.editorService.collectAddedBlocksRequest(this.editorID, addedBlocks);
|
|
7093
|
+
return {
|
|
7094
|
+
addedBlocks,
|
|
7095
|
+
addBlocks$
|
|
7096
|
+
};
|
|
7097
|
+
}
|
|
7098
|
+
collectUpdatedBlocksRequest(blocks, editorOutput) {
|
|
7099
|
+
blocks["block-changed" /* EventActions.update */].forEach((updateBlock) => {
|
|
7100
|
+
const { id, block } = this.editorService.getFullBlockData(updateBlock, editorOutput);
|
|
7101
|
+
block.id = id;
|
|
7102
|
+
this.updatedBlocks.push(block);
|
|
7103
|
+
});
|
|
7104
|
+
const updateBlocks$ = this.editorService.collectUpdatedBlocksRequest(this.updatedBlocks, this.blockIdsMap);
|
|
7105
|
+
this.updatedBlocks = [];
|
|
7106
|
+
return updateBlocks$;
|
|
7107
|
+
}
|
|
7108
|
+
collectRemovedBlocksRequest(blocks) {
|
|
7109
|
+
blocks["block-removed" /* EventActions.remove */].forEach((block) => {
|
|
7110
|
+
const id = block.detail.target.id;
|
|
7111
|
+
this.removedBlocksIds.push(id);
|
|
7112
|
+
});
|
|
7113
|
+
const removeBlocks$ = this.editorService.collectRemovedBlocksRequest(this.editorID, this.removedBlocksIds, this.blockIdsMap);
|
|
7114
|
+
this.removedBlocksIds = [];
|
|
7115
|
+
return removeBlocks$;
|
|
7116
|
+
}
|
|
7117
|
+
getBlocks(page = 0, size = 40) {
|
|
7118
|
+
let combinedBlock;
|
|
7119
|
+
return this.jTextService.getBlocks(this.editorID, page, size).pipe(takeUntilDestroyed(this.destroy), finalize(() => {
|
|
7120
|
+
if (combinedBlock) {
|
|
7121
|
+
this.addCombinedBlock(combinedBlock);
|
|
7122
|
+
combinedBlock = null;
|
|
7123
|
+
}
|
|
7124
|
+
recalculateIndexes(this.editor.blocks);
|
|
7125
|
+
}), map((block) => {
|
|
7126
|
+
if (block.type === COMBINED_TEXT_BLOCK_PART) {
|
|
7127
|
+
const blockData = block.data;
|
|
7128
|
+
if (combinedBlock && blockData.parentId !== combinedBlock?.id) {
|
|
7129
|
+
this.addCombinedBlock(combinedBlock);
|
|
7130
|
+
combinedBlock = null;
|
|
7131
|
+
}
|
|
7132
|
+
combinedBlock = this.setCombinedBlock(block);
|
|
7133
|
+
return;
|
|
7134
|
+
}
|
|
7135
|
+
if (combinedBlock) {
|
|
7136
|
+
this.addCombinedBlock(combinedBlock);
|
|
7137
|
+
combinedBlock = null;
|
|
7138
|
+
}
|
|
7139
|
+
this.addBlock(block);
|
|
7140
|
+
}), toArray());
|
|
7141
|
+
}
|
|
7142
|
+
addBlock(block) {
|
|
7143
|
+
if (typeof block.type !== 'string') {
|
|
7144
|
+
return;
|
|
7145
|
+
}
|
|
7146
|
+
this.blockIdsMap.set(block.id, block.id);
|
|
7147
|
+
this.insert(block);
|
|
7148
|
+
}
|
|
7149
|
+
addCombinedBlock(combinedBlock) {
|
|
7150
|
+
this.isSkipCombinedBlockOnChange.push(true);
|
|
7151
|
+
const block = this.editor.blocks.getById(combinedBlock.id || '');
|
|
7152
|
+
if (block) {
|
|
7153
|
+
this.editor.blocks.update(block.id, combinedBlock.data);
|
|
7154
|
+
return;
|
|
7155
|
+
}
|
|
7156
|
+
this.insert(combinedBlock);
|
|
7157
|
+
}
|
|
7158
|
+
insert(block) {
|
|
7159
|
+
this.checkFirst(block);
|
|
7160
|
+
this.index++;
|
|
7161
|
+
}
|
|
7162
|
+
checkFirst(block) {
|
|
7163
|
+
if (!this.isFirst) {
|
|
7164
|
+
this.isSkip = true;
|
|
7165
|
+
this.editor.blocks.insert(block.type, block.data, {}, this.index, false, false, block.id);
|
|
7166
|
+
return;
|
|
7167
|
+
}
|
|
7168
|
+
// TODO: есть варик что что то пойдет не так
|
|
7169
|
+
this.editor.blocks.render({ blocks: [block] }).then(() => this.isSkip = false);
|
|
7170
|
+
this.isFirst = false;
|
|
7171
|
+
}
|
|
7172
|
+
setCombinedBlock(block) {
|
|
7173
|
+
const combinedBlockData = block.data;
|
|
7174
|
+
const parent = this.combinedBlocks.get(combinedBlockData.parentId);
|
|
7175
|
+
this.blockIdsMap.set(block.id, block.id);
|
|
7176
|
+
if (parent) {
|
|
7177
|
+
const parentData = parent.data;
|
|
7178
|
+
parentData.textBlocks.push(block);
|
|
7179
|
+
return parent;
|
|
7180
|
+
}
|
|
7181
|
+
const parentObject = {
|
|
7182
|
+
id: combinedBlockData.parentId,
|
|
7183
|
+
type: COMBINED_TEXT_BLOCK_NAME,
|
|
7184
|
+
data: {
|
|
7185
|
+
id: combinedBlockData.parentId,
|
|
7186
|
+
textBlocks: [block]
|
|
7187
|
+
}
|
|
7188
|
+
};
|
|
7189
|
+
this.combinedBlocks.set(combinedBlockData.parentId, parentObject);
|
|
7190
|
+
return parentObject;
|
|
7191
|
+
}
|
|
7192
|
+
setBlockIdsToMap(blockIds, addedBlocks) {
|
|
7193
|
+
if (!blockIds.length) {
|
|
7194
|
+
return;
|
|
7195
|
+
}
|
|
7196
|
+
addedBlocks.forEach((blockData, index) => {
|
|
7197
|
+
this.blockIdsMap.set(blockData.id, blockIds[index]);
|
|
7198
|
+
});
|
|
7199
|
+
}
|
|
7200
|
+
setStartBlock() {
|
|
7201
|
+
if (this.blockIdsMap.size) {
|
|
7202
|
+
this.setFocus();
|
|
7203
|
+
this.editorEmpty.emit(this.checkIsEmpty());
|
|
7204
|
+
return;
|
|
7205
|
+
}
|
|
7206
|
+
if (this.isReadonly()) {
|
|
7207
|
+
this.editor.render({ blocks: [] });
|
|
7208
|
+
return;
|
|
7209
|
+
}
|
|
7210
|
+
this.editorService.setStartBlock(this.editorID, async (block, id) => {
|
|
7211
|
+
this.blockIdsMap.set(id, id);
|
|
7212
|
+
this.isSkipCombinedBlockOnChange.push(true);
|
|
7213
|
+
await this.editor.render({ blocks: [block] });
|
|
7214
|
+
this.setFocus();
|
|
7215
|
+
recalculateIndexes(this.editor.blocks);
|
|
7216
|
+
});
|
|
7217
|
+
}
|
|
7218
|
+
setFocus() {
|
|
7219
|
+
if (!this.config?.autofocus) {
|
|
7220
|
+
return;
|
|
7221
|
+
}
|
|
7222
|
+
this.editor.caret.focus();
|
|
7223
|
+
}
|
|
7224
|
+
checkIsEmpty() {
|
|
7225
|
+
const MIN_BLOCKS_COUNT = 1;
|
|
7226
|
+
const REDACTOR_SELECTOR = '.codex-editor__redactor';
|
|
7227
|
+
const redactor = this.editorElement.querySelector(REDACTOR_SELECTOR);
|
|
7228
|
+
const blocksCount = redactor?.childElementCount ?? 0;
|
|
7229
|
+
return blocksCount <= MIN_BLOCKS_COUNT && !redactor?.textContent;
|
|
7230
|
+
}
|
|
7231
|
+
resetData() {
|
|
7232
|
+
this.scrollSubscription?.unsubscribe();
|
|
7233
|
+
this.poolingSubscription?.unsubscribe();
|
|
7234
|
+
this.isSkipCombinedBlockOnChange = [];
|
|
7235
|
+
this.isFirst = true;
|
|
7236
|
+
this.isChanging = false;
|
|
7237
|
+
this.isSkip = false;
|
|
7238
|
+
this.isRequested = false;
|
|
7239
|
+
this.blockIdsMap = new Map();
|
|
7240
|
+
this.combinedBlocks = new Map();
|
|
7241
|
+
this.index = 0;
|
|
7242
|
+
this.page = 0;
|
|
7243
|
+
this.addedBlocks = [];
|
|
7244
|
+
this.updatedBlocks = [];
|
|
7245
|
+
this.removedBlocksIds = [];
|
|
7246
|
+
this.changesQueue = [];
|
|
7247
|
+
this.abortController = new AbortController();
|
|
7248
|
+
}
|
|
7249
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7250
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CuiEditorComponent, isStandalone: true, selector: "cui-editor", inputs: { editorID: "editorID", config: "config", requestSize: "requestSize" }, outputs: { editorEmpty: "editorEmpty" }, providers: [CuiEditorService, CuiJTextApiService], viewQueries: [{ propertyName: "editorRef", first: true, predicate: ["editor"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\r\n #editor\r\n [id]=\"editorID\"\r\n [class._readonly]=\"config.readOnly\"\r\n data-editor\r\n></div>\r\n", styles: [":host{--textColor: var(--cui-base-900);--menuBackground: var(--cui-base-0);--menuBorder: var(--cui-base-200);--menuItemHover: var(--cui-base-10);--menuItemBackground: var(cui-base-900);--menuIconBackground: var(--cui-base-50);--menuIconHover: var(--cui-base-10);font-weight:400;font-size:14px;line-height:20px;font-family:var(--cui-main-font)}:host ::ng-deep .ce-popover{--color-background: var(--menuBackground);--color-text-primary: var(--textColor);--color-border: var(--menuBorder);--color-border-icon: var(--menuBorder);--color-background-item: var(--menuItemBackground);--color-background-item-hover: var(--menuItemHover)}:host ::ng-deep .ce-popover__search{background:var(--menuIconBackground)}:host ::ng-deep .ce-popover .ce-popover-item__icon{background:var(--menuIconBackground)}:host ::ng-deep .ce-conversion-toolbar{background-color:var(--menuBackground);border-color:var(--menuBorder)}:host ::ng-deep .ce-conversion-toolbar__tools{padding:0 6px 6px}:host ::ng-deep .ce-conversion-tool{padding:3px;border-radius:6px}:host ::ng-deep .ce-conversion-tool__icon{border:1px solid var(--menuBorder);background-color:var(--menuIconBackground);box-shadow:none}:host ::ng-deep .ce-conversion-tool:hover{background-color:var(--menuItemHover)}:host ::ng-deep .ce-conversion-tool:hover .ce-conversion-tool__icon{border-color:var(--menuIconHover)}:host ::ng-deep .combined-text-block{padding:.4em 0;line-height:1.6em;outline:none}:host ::ng-deep .combined-text-block .combined-text-block-part{outline:none}:host ::ng-deep .combined-text-block .combined-text-block-part:only-child,:host ::ng-deep .combined-text-block .combined-text-block-part._selected{display:list-item}:host ::ng-deep .combined-text-block .combined-text-block-part:only-child::marker,:host ::ng-deep .combined-text-block .combined-text-block-part._selected::marker{content:\"\"}:host ::ng-deep .image-tool__image{border:1px solid var(--cui-base-200);background-color:var(--cui-base-0)}:host ::ng-deep .image-tool__image-preloader{background-color:var(--cui-base-200)}:host ::ng-deep .image-tool__image-preloader:after{border:1px solid var(--cui-base-200);border-top:1px solid var(--cui-blue-600)}:host ::ng-deep .cdx-button{border:1px solid var(--cui-base-200);color:var(--textColor);background-color:var(--cui-base-0);box-shadow:none}:host ::ng-deep .ce-inline-toolbar{border-color:var(--cui-base-100);color:var(--textColor);background-color:var(--cui-base-0)}:host ::ng-deep .ce-inline-toolbar__dropdown:hover{background-color:var(--cui-base-100)}:host ::ng-deep .ce-inline-tool:hover{background-color:var(--cui-base-100)}:host ::ng-deep .ce-toolbar__plus,:host ::ng-deep .ce-toolbar__settings-btn{color:var(--cui-base-500)}:host ::ng-deep .ce-toolbar__plus:hover,:host ::ng-deep .ce-toolbar__settings-btn:hover{background-color:var(--cui-base-100)}:host ::ng-deep .ce-toolbar__actions{right:100%}:host ::ng-deep .ce-toolbar__content{max-width:none}:host ::ng-deep .ce-block--selected .ce-block__content{background-color:var(--cui-base-200)}:host ::ng-deep .ce-block__content{max-width:100%}:host ::ng-deep .ce-block:only-of-type .combined-text-block[data-placeholder-active][data-empty=true]:before{content:attr(data-placeholder-active);position:absolute;color:var(--cui-base-400)}:host ::ng-deep [data-editor]{padding-right:4px;width:100%;height:100%;min-height:200px;overflow:hidden auto;scrollbar-gutter:stable}:host ::ng-deep [data-editor] .codex-editor{margin-left:60px}:host ::ng-deep [data-editor] .codex-editor--narrow .ce-popover{right:auto}:host ::ng-deep [data-editor] .codex-editor__redactor{margin-right:auto;padding-bottom:260px!important}:host ::ng-deep [data-editor]._readonly{min-height:auto}:host ::ng-deep [data-editor]._readonly .codex-editor{margin:auto}:host ::ng-deep [data-editor]._readonly .codex-editor__redactor{padding-bottom:0!important}:host ::ng-deep [data-editor]._readonly .combined-text-block{padding:0}:host ::ng-deep [data-editor] [data-item-name=move-up],:host ::ng-deep [data-editor] [data-item-name=move-down],:host ::ng-deep [data-editor] [data-tool=paragraph]{display:none}:host ::ng-deep [data-editor] *::selection{background:var(--cui-base-200)}:host ::ng-deep [data-editor] a{color:var(--cui-light-blue-600)}:host ::ng-deep .marker{cursor:pointer;text-decoration:underline;color:var(--cui-light-blue-600);background-color:transparent}:host ::ng-deep .tool-marker,:host ::ng-deep .role-marker{margin:0 5px}:host ::ng-deep .tool-marker{color:#e97c00}:host ::ng-deep .role-marker{color:#8803f1}.form{height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7251
|
+
}
|
|
7252
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorComponent, decorators: [{
|
|
7253
|
+
type: Component,
|
|
7254
|
+
args: [{ selector: 'cui-editor', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [CuiEditorService, CuiJTextApiService], template: "<div\r\n #editor\r\n [id]=\"editorID\"\r\n [class._readonly]=\"config.readOnly\"\r\n data-editor\r\n></div>\r\n", styles: [":host{--textColor: var(--cui-base-900);--menuBackground: var(--cui-base-0);--menuBorder: var(--cui-base-200);--menuItemHover: var(--cui-base-10);--menuItemBackground: var(cui-base-900);--menuIconBackground: var(--cui-base-50);--menuIconHover: var(--cui-base-10);font-weight:400;font-size:14px;line-height:20px;font-family:var(--cui-main-font)}:host ::ng-deep .ce-popover{--color-background: var(--menuBackground);--color-text-primary: var(--textColor);--color-border: var(--menuBorder);--color-border-icon: var(--menuBorder);--color-background-item: var(--menuItemBackground);--color-background-item-hover: var(--menuItemHover)}:host ::ng-deep .ce-popover__search{background:var(--menuIconBackground)}:host ::ng-deep .ce-popover .ce-popover-item__icon{background:var(--menuIconBackground)}:host ::ng-deep .ce-conversion-toolbar{background-color:var(--menuBackground);border-color:var(--menuBorder)}:host ::ng-deep .ce-conversion-toolbar__tools{padding:0 6px 6px}:host ::ng-deep .ce-conversion-tool{padding:3px;border-radius:6px}:host ::ng-deep .ce-conversion-tool__icon{border:1px solid var(--menuBorder);background-color:var(--menuIconBackground);box-shadow:none}:host ::ng-deep .ce-conversion-tool:hover{background-color:var(--menuItemHover)}:host ::ng-deep .ce-conversion-tool:hover .ce-conversion-tool__icon{border-color:var(--menuIconHover)}:host ::ng-deep .combined-text-block{padding:.4em 0;line-height:1.6em;outline:none}:host ::ng-deep .combined-text-block .combined-text-block-part{outline:none}:host ::ng-deep .combined-text-block .combined-text-block-part:only-child,:host ::ng-deep .combined-text-block .combined-text-block-part._selected{display:list-item}:host ::ng-deep .combined-text-block .combined-text-block-part:only-child::marker,:host ::ng-deep .combined-text-block .combined-text-block-part._selected::marker{content:\"\"}:host ::ng-deep .image-tool__image{border:1px solid var(--cui-base-200);background-color:var(--cui-base-0)}:host ::ng-deep .image-tool__image-preloader{background-color:var(--cui-base-200)}:host ::ng-deep .image-tool__image-preloader:after{border:1px solid var(--cui-base-200);border-top:1px solid var(--cui-blue-600)}:host ::ng-deep .cdx-button{border:1px solid var(--cui-base-200);color:var(--textColor);background-color:var(--cui-base-0);box-shadow:none}:host ::ng-deep .ce-inline-toolbar{border-color:var(--cui-base-100);color:var(--textColor);background-color:var(--cui-base-0)}:host ::ng-deep .ce-inline-toolbar__dropdown:hover{background-color:var(--cui-base-100)}:host ::ng-deep .ce-inline-tool:hover{background-color:var(--cui-base-100)}:host ::ng-deep .ce-toolbar__plus,:host ::ng-deep .ce-toolbar__settings-btn{color:var(--cui-base-500)}:host ::ng-deep .ce-toolbar__plus:hover,:host ::ng-deep .ce-toolbar__settings-btn:hover{background-color:var(--cui-base-100)}:host ::ng-deep .ce-toolbar__actions{right:100%}:host ::ng-deep .ce-toolbar__content{max-width:none}:host ::ng-deep .ce-block--selected .ce-block__content{background-color:var(--cui-base-200)}:host ::ng-deep .ce-block__content{max-width:100%}:host ::ng-deep .ce-block:only-of-type .combined-text-block[data-placeholder-active][data-empty=true]:before{content:attr(data-placeholder-active);position:absolute;color:var(--cui-base-400)}:host ::ng-deep [data-editor]{padding-right:4px;width:100%;height:100%;min-height:200px;overflow:hidden auto;scrollbar-gutter:stable}:host ::ng-deep [data-editor] .codex-editor{margin-left:60px}:host ::ng-deep [data-editor] .codex-editor--narrow .ce-popover{right:auto}:host ::ng-deep [data-editor] .codex-editor__redactor{margin-right:auto;padding-bottom:260px!important}:host ::ng-deep [data-editor]._readonly{min-height:auto}:host ::ng-deep [data-editor]._readonly .codex-editor{margin:auto}:host ::ng-deep [data-editor]._readonly .codex-editor__redactor{padding-bottom:0!important}:host ::ng-deep [data-editor]._readonly .combined-text-block{padding:0}:host ::ng-deep [data-editor] [data-item-name=move-up],:host ::ng-deep [data-editor] [data-item-name=move-down],:host ::ng-deep [data-editor] [data-tool=paragraph]{display:none}:host ::ng-deep [data-editor] *::selection{background:var(--cui-base-200)}:host ::ng-deep [data-editor] a{color:var(--cui-light-blue-600)}:host ::ng-deep .marker{cursor:pointer;text-decoration:underline;color:var(--cui-light-blue-600);background-color:transparent}:host ::ng-deep .tool-marker,:host ::ng-deep .role-marker{margin:0 5px}:host ::ng-deep .tool-marker{color:#e97c00}:host ::ng-deep .role-marker{color:#8803f1}.form{height:100%}\n"] }]
|
|
7255
|
+
}], propDecorators: { editorRef: [{
|
|
7256
|
+
type: ViewChild,
|
|
7257
|
+
args: ['editor']
|
|
7258
|
+
}], editorEmpty: [{
|
|
7259
|
+
type: Output
|
|
7260
|
+
}], editorID: [{
|
|
7261
|
+
type: Input,
|
|
7262
|
+
args: [{ required: true }]
|
|
7263
|
+
}], config: [{
|
|
7264
|
+
type: Input
|
|
7265
|
+
}], requestSize: [{
|
|
7266
|
+
type: Input
|
|
7267
|
+
}] } });
|
|
7268
|
+
|
|
7269
|
+
class CuiEditorReadonlyComponent {
|
|
7270
|
+
constructor() {
|
|
7271
|
+
this.isShowMore = signal(false);
|
|
7272
|
+
this.isMoreButtonShown = signal(false);
|
|
7273
|
+
this.editorConfig = computed(() => ({ readOnly: true, withoutPreload: true, ...this.config() }));
|
|
7274
|
+
this.editor = viewChild.required('editor');
|
|
7275
|
+
this.editorId = input.required();
|
|
7276
|
+
this.config = input.required();
|
|
7277
|
+
this.buttonTemplate = input.required();
|
|
7278
|
+
this.shortHeight = input(68);
|
|
7279
|
+
this.initEditorIdEffect();
|
|
7280
|
+
this.initReadEditorProperty();
|
|
7281
|
+
}
|
|
7282
|
+
onShow(editor) {
|
|
7283
|
+
editor.editorElement.scrollTo(0, 0);
|
|
7284
|
+
this.isShowMore.update((prev) => !prev);
|
|
7285
|
+
}
|
|
7286
|
+
initReadEditorProperty() {
|
|
7287
|
+
afterRender({
|
|
7288
|
+
read: () => this.isMoreButtonShown.set(this.editor().editorElement?.scrollHeight > this.shortHeight())
|
|
7289
|
+
});
|
|
7290
|
+
}
|
|
7291
|
+
initEditorIdEffect() {
|
|
7292
|
+
effect(() => {
|
|
7293
|
+
this.editorId();
|
|
7294
|
+
this.isShowMore.set(false);
|
|
7295
|
+
}, { allowSignalWrites: true });
|
|
7296
|
+
}
|
|
7297
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorReadonlyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7298
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CuiEditorReadonlyComponent, isStandalone: true, selector: "cui-editor-readonly", inputs: { editorId: { classPropertyName: "editorId", publicName: "editorId", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, buttonTemplate: { classPropertyName: "buttonTemplate", publicName: "buttonTemplate", isSignal: true, isRequired: true, transformFunction: null }, shortHeight: { classPropertyName: "shortHeight", publicName: "shortHeight", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "editor", first: true, predicate: ["editor"], descendants: true, isSignal: true }], ngImport: i0, template: "<cui-editor\r\n #editor\r\n class=\"editor\"\r\n [class.editor_opened]=\"isShowMore()\"\r\n [editorID]=\"editorId()\"\r\n [config]=\"editorConfig()\"\r\n/>\r\n@if (isMoreButtonShown()) {\r\n <button class=\"c-button\" (click)=\"onShow(editor)\">\r\n <ng-container [ngTemplateOutlet]=\"buttonTemplate()\" [ngTemplateOutletContext]=\"{ $implicit: isShowMore }\"></ng-container>\r\n </button>\r\n}\r\n", styles: [":host{--height: 68px;--fullHeight: 500px;display:flex;flex-direction:column;gap:8px}:host .editor{display:block;max-height:var(--height);overflow:hidden}:host .editor ::ng-deep [data-editor]{overflow:hidden}:host .editor_opened{max-height:var(--fullHeight)}:host .editor_opened ::ng-deep [data-editor]{max-height:var(--fullHeight);overflow:hidden auto}.c-button{padding:0}\n"], dependencies: [{ kind: "component", type: CuiEditorComponent, selector: "cui-editor", inputs: ["editorID", "config", "requestSize"], outputs: ["editorEmpty"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7299
|
+
}
|
|
7300
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorReadonlyComponent, decorators: [{
|
|
7301
|
+
type: Component,
|
|
7302
|
+
args: [{ selector: 'cui-editor-readonly', standalone: true, imports: [CuiEditorComponent, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<cui-editor\r\n #editor\r\n class=\"editor\"\r\n [class.editor_opened]=\"isShowMore()\"\r\n [editorID]=\"editorId()\"\r\n [config]=\"editorConfig()\"\r\n/>\r\n@if (isMoreButtonShown()) {\r\n <button class=\"c-button\" (click)=\"onShow(editor)\">\r\n <ng-container [ngTemplateOutlet]=\"buttonTemplate()\" [ngTemplateOutletContext]=\"{ $implicit: isShowMore }\"></ng-container>\r\n </button>\r\n}\r\n", styles: [":host{--height: 68px;--fullHeight: 500px;display:flex;flex-direction:column;gap:8px}:host .editor{display:block;max-height:var(--height);overflow:hidden}:host .editor ::ng-deep [data-editor]{overflow:hidden}:host .editor_opened{max-height:var(--fullHeight)}:host .editor_opened ::ng-deep [data-editor]{max-height:var(--fullHeight);overflow:hidden auto}.c-button{padding:0}\n"] }]
|
|
7303
|
+
}], ctorParameters: () => [] });
|
|
7304
|
+
|
|
7305
|
+
class CuiEditorModalComponent {
|
|
7306
|
+
constructor() {
|
|
7307
|
+
this.isOpen = signal(false);
|
|
7308
|
+
this.isButtonDisabled = signal(false);
|
|
7309
|
+
this.title = input.required();
|
|
7310
|
+
this.buttonTemplate = input();
|
|
7311
|
+
this.config = input.required();
|
|
7312
|
+
this.editorId = input();
|
|
7313
|
+
this.editorCreated = output();
|
|
7314
|
+
this.modalClosed = output();
|
|
7315
|
+
}
|
|
7316
|
+
onModalOpen() {
|
|
7317
|
+
this.isButtonDisabled.set(true);
|
|
7318
|
+
if (this.editorId()) {
|
|
7319
|
+
this.open();
|
|
7320
|
+
return;
|
|
7321
|
+
}
|
|
7322
|
+
this.editorCreated.emit();
|
|
7323
|
+
}
|
|
7324
|
+
open() {
|
|
7325
|
+
this.isOpen.set(true);
|
|
7326
|
+
}
|
|
7327
|
+
close() {
|
|
7328
|
+
this.isButtonDisabled.set(false);
|
|
7329
|
+
this.isOpen.set(false);
|
|
7330
|
+
this.modalClosed.emit();
|
|
7331
|
+
}
|
|
7332
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7333
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CuiEditorModalComponent, isStandalone: true, selector: "cui-editor-modal", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, buttonTemplate: { classPropertyName: "buttonTemplate", publicName: "buttonTemplate", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, editorId: { classPropertyName: "editorId", publicName: "editorId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { editorCreated: "editorCreated", modalClosed: "modalClosed" }, ngImport: i0, template: "@if (buttonTemplate(); as template) {\r\n <button\r\n type=\"button\"\r\n class=\"button\"\r\n (click)=\"onModalOpen()\"\r\n >\r\n <ng-container [ngTemplateOutlet]=\"template\" />\r\n </button>\r\n} @else {\r\n <button\r\n class=\"description\"\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"outlined-gray\"\r\n icon=\"cuiIconRichText\"\r\n size=\"sm\"\r\n (click)=\"onModalOpen()\"\r\n [disabled]=\"isButtonDisabled()\"\r\n >\r\n @if (editorId()) {\r\n <span class=\"description__text _created\">{{ 'Description' }}</span>\r\n <cui-svg\r\n class=\"description__icon\"\r\n icon=\"cuiIconEdit\"\r\n color=\"var(--cui-base-500)\"\r\n />\r\n } @else {\r\n <cui-svg\r\n class=\"description__icon\"\r\n icon=\"cuiIconPlus\"\r\n color=\"var(--cui-light-blue-600)\"\r\n />\r\n <span class=\"description__text\">{{ 'Add description' }}</span>\r\n }\r\n </button>\r\n}\r\n@if (isOpen()) {\r\n <div class=\"wrapper\">\r\n @if (editorId(); as id) {\r\n <header class=\"header\">\r\n <div class=\"info\">\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n icon=\"cuiIconChevronLeft\"\r\n size=\"xxs\"\r\n appearance=\"secondary\"\r\n shape=\"rounded\"\r\n (click)=\"close()\"\r\n ></button>\r\n <h1 class=\"title\">{{ title() }}</h1>\r\n </div>\r\n <div class=\"actions\">\r\n <!-- <cui-loader /> -->\r\n <button\r\n type=\"button\"\r\n cuiButton\r\n size=\"xs\"\r\n (click)=\"close()\"\r\n >\r\n {{ 'Done' }}\r\n </button>\r\n </div>\r\n </header>\r\n\r\n <section class=\"section\">\r\n <cui-editor\r\n #editorComponent\r\n class=\"editor\"\r\n [editorID]=\"id\"\r\n [config]=\"config()\"\r\n />\r\n </section>\r\n }\r\n </div>\r\n}\r\n", styles: [":host ::ng-deep .delete{width:max-content}:host ::ng-deep .delete .c-content{display:flex;align-items:center;gap:4px;color:var(--cui-danger)}:host ::ng-deep .description .c-content{display:flex;align-items:center;gap:4px}.button{padding:0}.description{width:max-content}.description__text{color:var(--cui-light-blue-600)}.description__text._created{color:var(--cui-base-900)}.description__icon{padding:4px}.wrapper{position:fixed;z-index:10;inset:0;background-color:var(--cui-base-0)}.header{display:flex;justify-content:space-between;padding:8px 16px;border-bottom:.5px solid var(--cui-base-200);background:var(--cui-base-0)}.info,.actions{display:flex;gap:12px;align-items:center}.section{padding-right:24px;padding-left:24px;padding-top:24px;height:calc(100% - 50px);overflow:hidden}.title{font-weight:500;font-size:14px;line-height:20px;margin:0}.editor{padding-right:32px;padding-left:32px;padding-top:32px;display:block;margin:0 auto;max-width:750px;height:100%}\n"], dependencies: [{ kind: "component", type: CuiEditorComponent, selector: "cui-editor", inputs: ["editorID", "config", "requestSize"], outputs: ["editorEmpty"] }, { kind: "ngmodule", type: CuiButtonModule }, { kind: "component", type: CuiButtonComponent, selector: "button[cuiButton], a[cuiButton]", inputs: ["shape", "disabled", "isLoaderShown", "icon", "iconRight", "appearance", "size"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: CuiSvgModule }, { kind: "component", type: CuiSvgComponent, selector: "cui-svg[icon]", inputs: ["width", "height", "strokeWidth", "color", "icon"] }] }); }
|
|
7334
|
+
}
|
|
7335
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorModalComponent, decorators: [{
|
|
7336
|
+
type: Component,
|
|
7337
|
+
args: [{ selector: 'cui-editor-modal', imports: [
|
|
7338
|
+
CuiEditorComponent,
|
|
7339
|
+
CuiButtonModule,
|
|
7340
|
+
NgTemplateOutlet,
|
|
7341
|
+
CuiSvgModule
|
|
7342
|
+
], standalone: true, template: "@if (buttonTemplate(); as template) {\r\n <button\r\n type=\"button\"\r\n class=\"button\"\r\n (click)=\"onModalOpen()\"\r\n >\r\n <ng-container [ngTemplateOutlet]=\"template\" />\r\n </button>\r\n} @else {\r\n <button\r\n class=\"description\"\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"outlined-gray\"\r\n icon=\"cuiIconRichText\"\r\n size=\"sm\"\r\n (click)=\"onModalOpen()\"\r\n [disabled]=\"isButtonDisabled()\"\r\n >\r\n @if (editorId()) {\r\n <span class=\"description__text _created\">{{ 'Description' }}</span>\r\n <cui-svg\r\n class=\"description__icon\"\r\n icon=\"cuiIconEdit\"\r\n color=\"var(--cui-base-500)\"\r\n />\r\n } @else {\r\n <cui-svg\r\n class=\"description__icon\"\r\n icon=\"cuiIconPlus\"\r\n color=\"var(--cui-light-blue-600)\"\r\n />\r\n <span class=\"description__text\">{{ 'Add description' }}</span>\r\n }\r\n </button>\r\n}\r\n@if (isOpen()) {\r\n <div class=\"wrapper\">\r\n @if (editorId(); as id) {\r\n <header class=\"header\">\r\n <div class=\"info\">\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n icon=\"cuiIconChevronLeft\"\r\n size=\"xxs\"\r\n appearance=\"secondary\"\r\n shape=\"rounded\"\r\n (click)=\"close()\"\r\n ></button>\r\n <h1 class=\"title\">{{ title() }}</h1>\r\n </div>\r\n <div class=\"actions\">\r\n <!-- <cui-loader /> -->\r\n <button\r\n type=\"button\"\r\n cuiButton\r\n size=\"xs\"\r\n (click)=\"close()\"\r\n >\r\n {{ 'Done' }}\r\n </button>\r\n </div>\r\n </header>\r\n\r\n <section class=\"section\">\r\n <cui-editor\r\n #editorComponent\r\n class=\"editor\"\r\n [editorID]=\"id\"\r\n [config]=\"config()\"\r\n />\r\n </section>\r\n }\r\n </div>\r\n}\r\n", styles: [":host ::ng-deep .delete{width:max-content}:host ::ng-deep .delete .c-content{display:flex;align-items:center;gap:4px;color:var(--cui-danger)}:host ::ng-deep .description .c-content{display:flex;align-items:center;gap:4px}.button{padding:0}.description{width:max-content}.description__text{color:var(--cui-light-blue-600)}.description__text._created{color:var(--cui-base-900)}.description__icon{padding:4px}.wrapper{position:fixed;z-index:10;inset:0;background-color:var(--cui-base-0)}.header{display:flex;justify-content:space-between;padding:8px 16px;border-bottom:.5px solid var(--cui-base-200);background:var(--cui-base-0)}.info,.actions{display:flex;gap:12px;align-items:center}.section{padding-right:24px;padding-left:24px;padding-top:24px;height:calc(100% - 50px);overflow:hidden}.title{font-weight:500;font-size:14px;line-height:20px;margin:0}.editor{padding-right:32px;padding-left:32px;padding-top:32px;display:block;margin:0 auto;max-width:750px;height:100%}\n"] }]
|
|
7343
|
+
}] });
|
|
7344
|
+
|
|
7345
|
+
class CuiEditorBlockComponent {
|
|
7346
|
+
constructor() {
|
|
7347
|
+
this.skipFirstValidation = true;
|
|
7348
|
+
this.editorConfig = signal(null);
|
|
7349
|
+
this.isDescriptionModalOpen = signal(false);
|
|
7350
|
+
this.isDescriptionEmpty = signal(false);
|
|
7351
|
+
this.editorContainer = viewChild('editorContainer', {
|
|
7352
|
+
read: ElementRef
|
|
7353
|
+
});
|
|
7354
|
+
this.title = input.required();
|
|
7355
|
+
this.editorId = input.required();
|
|
7356
|
+
this.config = input.required();
|
|
7357
|
+
this.required = input(false);
|
|
7358
|
+
this.editorEmpty = output();
|
|
7359
|
+
this.initEditorConfig();
|
|
7360
|
+
}
|
|
7361
|
+
onToggleDescriptionModal() {
|
|
7362
|
+
this.isDescriptionModalOpen.update((prev) => !prev);
|
|
7363
|
+
}
|
|
7364
|
+
onDescriptionChange(value) {
|
|
7365
|
+
this.editorEmpty.emit(value);
|
|
7366
|
+
if (this.skipFirstValidation) {
|
|
7367
|
+
this.skipFirstValidation = false;
|
|
7368
|
+
return;
|
|
7369
|
+
}
|
|
7370
|
+
this.isDescriptionEmpty.set(value);
|
|
7371
|
+
}
|
|
7372
|
+
initEditorConfig() {
|
|
7373
|
+
const effectRef = effect(() => {
|
|
7374
|
+
const element = this.editorContainer()?.nativeElement;
|
|
7375
|
+
if (!element) {
|
|
7376
|
+
return;
|
|
7377
|
+
}
|
|
7378
|
+
this.editorConfig.set({ ...this.config(), element });
|
|
7379
|
+
effectRef.destroy();
|
|
7380
|
+
}, { allowSignalWrites: true });
|
|
7381
|
+
}
|
|
7382
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7383
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CuiEditorBlockComponent, isStandalone: true, selector: "cui-editor-block", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, editorId: { classPropertyName: "editorId", publicName: "editorId", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { editorEmpty: "editorEmpty" }, viewQueries: [{ propertyName: "editorContainer", first: true, predicate: ["editorContainer"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t\">\r\n <div class=\"wrapper\">\r\n <span class=\"title\">\r\n {{ t('DESCRIPTION') }}\r\n @if (required()) {\r\n <span class=\"title__required\">*</span>\r\n }\r\n </span>\r\n <ng-template #button>\r\n <button\r\n [cuiTooltip]=\"t('EXPAND_EDITOR_TO_FULLSCREEN')\"\r\n cuiButton\r\n size=\"xxs\"\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n icon=\"cuiIconMaximizeSm\"\r\n (click)=\"onToggleDescriptionModal()\"\r\n ></button>\r\n </ng-template>\r\n <cui-editor-modal\r\n [title]=\"title()\"\r\n [editorId]=\"editorId()\"\r\n [buttonTemplate]=\"button\"\r\n [config]=\"config()\"\r\n (modalClosed)=\"onToggleDescriptionModal()\"\r\n />\r\n </div>\r\n <div\r\n #editorContainer\r\n cuiContentWrapper\r\n class=\"editor\"\r\n [class.editor_invalid]=\"required() && isDescriptionEmpty()\"\r\n >\r\n @if (!isDescriptionModalOpen() && editorConfig()) {\r\n <cui-editor\r\n #editorComponent\r\n [editorID]=\"editorId()\"\r\n [config]=\"editorConfig()!\"\r\n (editorEmpty)=\"onDescriptionChange($event)\"\r\n />\r\n }\r\n </div>\r\n @if (required() && isDescriptionEmpty()) {\r\n <cui-hint hintType=\"error\">{{ t('DESCRIPTION_IS_REQUIRED') }}</cui-hint>\r\n }\r\n</ng-container>\r\n", styles: [":host{padding:16px;display:flex;flex-direction:column;gap:8px;background:var(--cui-base-10);border-radius:8px}.wrapper{display:flex;gap:8px;align-items:center;justify-content:space-between}.editor{padding-top:16px;padding-bottom:16px;display:block;max-height:650px;overflow:auto}.editor_invalid{border:1px solid var(--cui-danger)}.title{font-weight:500;font-size:14px;line-height:20px}.title__required{color:var(--cui-danger)}\n"], dependencies: [{ kind: "ngmodule", type: CuiButtonModule }, { kind: "component", type: CuiButtonComponent, selector: "button[cuiButton], a[cuiButton]", inputs: ["shape", "disabled", "isLoaderShown", "icon", "iconRight", "appearance", "size"] }, { kind: "component", type: CuiEditorModalComponent, selector: "cui-editor-modal", inputs: ["title", "buttonTemplate", "config", "editorId"], outputs: ["editorCreated", "modalClosed"] }, { kind: "component", type: CuiEditorComponent, selector: "cui-editor", inputs: ["editorID", "config", "requestSize"], outputs: ["editorEmpty"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: CuiContentWrapperComponent, selector: "cui-content-wrapper, [cuiContentWrapper]", inputs: ["backgroundColor", "gap"] }, { kind: "directive", type: CuiTooltipDirective, selector: "[cuiTooltip]:not(ng-container):not(ng-template)", inputs: ["cuiTooltipContext", "cuiTooltipAppearance", "cuiTooltip"] }, { kind: "ngmodule", type: CuiHintModule }, { kind: "component", type: CuiHintComponent, selector: "cui-hint", inputs: ["hintType"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7384
|
+
}
|
|
7385
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiEditorBlockComponent, decorators: [{
|
|
7386
|
+
type: Component,
|
|
7387
|
+
args: [{ selector: 'cui-editor-block', imports: [
|
|
7388
|
+
CuiButtonModule,
|
|
7389
|
+
CuiEditorModalComponent,
|
|
7390
|
+
CuiEditorComponent,
|
|
7391
|
+
TranslocoDirective,
|
|
7392
|
+
CuiContentWrapperComponent,
|
|
7393
|
+
CuiTooltip,
|
|
7394
|
+
CuiHintModule
|
|
7395
|
+
], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\r\n <div class=\"wrapper\">\r\n <span class=\"title\">\r\n {{ t('DESCRIPTION') }}\r\n @if (required()) {\r\n <span class=\"title__required\">*</span>\r\n }\r\n </span>\r\n <ng-template #button>\r\n <button\r\n [cuiTooltip]=\"t('EXPAND_EDITOR_TO_FULLSCREEN')\"\r\n cuiButton\r\n size=\"xxs\"\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n icon=\"cuiIconMaximizeSm\"\r\n (click)=\"onToggleDescriptionModal()\"\r\n ></button>\r\n </ng-template>\r\n <cui-editor-modal\r\n [title]=\"title()\"\r\n [editorId]=\"editorId()\"\r\n [buttonTemplate]=\"button\"\r\n [config]=\"config()\"\r\n (modalClosed)=\"onToggleDescriptionModal()\"\r\n />\r\n </div>\r\n <div\r\n #editorContainer\r\n cuiContentWrapper\r\n class=\"editor\"\r\n [class.editor_invalid]=\"required() && isDescriptionEmpty()\"\r\n >\r\n @if (!isDescriptionModalOpen() && editorConfig()) {\r\n <cui-editor\r\n #editorComponent\r\n [editorID]=\"editorId()\"\r\n [config]=\"editorConfig()!\"\r\n (editorEmpty)=\"onDescriptionChange($event)\"\r\n />\r\n }\r\n </div>\r\n @if (required() && isDescriptionEmpty()) {\r\n <cui-hint hintType=\"error\">{{ t('DESCRIPTION_IS_REQUIRED') }}</cui-hint>\r\n }\r\n</ng-container>\r\n", styles: [":host{padding:16px;display:flex;flex-direction:column;gap:8px;background:var(--cui-base-10);border-radius:8px}.wrapper{display:flex;gap:8px;align-items:center;justify-content:space-between}.editor{padding-top:16px;padding-bottom:16px;display:block;max-height:650px;overflow:auto}.editor_invalid{border:1px solid var(--cui-danger)}.title{font-weight:500;font-size:14px;line-height:20px}.title__required{color:var(--cui-danger)}\n"] }]
|
|
7396
|
+
}], ctorParameters: () => [] });
|
|
7397
|
+
|
|
7398
|
+
const cuiXNdjsonInterceptor = (request, next) => {
|
|
7399
|
+
if (request.headers.get('Content-Type') !== 'application/x-ndjson') {
|
|
7400
|
+
return next(request);
|
|
7401
|
+
}
|
|
7402
|
+
return new Observable((observer) => {
|
|
7403
|
+
const controller = new AbortController();
|
|
7404
|
+
const signal = controller.signal;
|
|
7405
|
+
(async () => {
|
|
7406
|
+
try {
|
|
7407
|
+
const response = await fetch(request.urlWithParams, {
|
|
7408
|
+
method: request.method,
|
|
7409
|
+
headers: request.headers.keys().reduce((headers, key) => {
|
|
7410
|
+
headers[key] = request.headers.get(key);
|
|
7411
|
+
return headers;
|
|
7412
|
+
}, {}),
|
|
7413
|
+
body: request.body ? JSON.stringify(request.body) : null,
|
|
7414
|
+
signal
|
|
7415
|
+
});
|
|
7416
|
+
if (!response.ok) {
|
|
7417
|
+
const error = await response.json();
|
|
7418
|
+
observer.error(new HttpErrorResponse({ error }));
|
|
7419
|
+
return;
|
|
7420
|
+
}
|
|
7421
|
+
const reader = response.body.getReader();
|
|
7422
|
+
const decoder = new TextDecoder();
|
|
7423
|
+
let buffer = '';
|
|
7424
|
+
for (;;) {
|
|
7425
|
+
const { done, value } = await reader.read();
|
|
7426
|
+
if (done) {
|
|
7427
|
+
observer.complete();
|
|
7428
|
+
return;
|
|
7429
|
+
}
|
|
7430
|
+
buffer += decoder.decode(value);
|
|
7431
|
+
const lines = buffer.split('\n');
|
|
7432
|
+
buffer = lines.pop() ?? '';
|
|
7433
|
+
lines.forEach((line) => observer.next(JSON.parse(line)));
|
|
7434
|
+
}
|
|
7435
|
+
}
|
|
7436
|
+
catch (error) {
|
|
7437
|
+
observer.error(new HttpErrorResponse({ error }));
|
|
7438
|
+
}
|
|
7439
|
+
})();
|
|
7440
|
+
return () => controller.abort();
|
|
7441
|
+
});
|
|
7442
|
+
};
|
|
7443
|
+
|
|
7444
|
+
const cuiLoaderInterceptor = (request, next) => {
|
|
7445
|
+
const loaderService = inject(CuiLoaderService);
|
|
7446
|
+
if (request.method === 'GET') {
|
|
7447
|
+
return next(request);
|
|
7448
|
+
}
|
|
7449
|
+
loaderService.setLoading();
|
|
7450
|
+
return next(request).pipe(catchError(throwError), finalize(loaderService.handleCompletedRequest.bind(loaderService)));
|
|
7451
|
+
};
|
|
7452
|
+
|
|
7453
|
+
class CuiGeneralControlErrorHintComponent {
|
|
7454
|
+
constructor() {
|
|
7455
|
+
this.control = input.required();
|
|
7456
|
+
this.isVisible = input();
|
|
7457
|
+
}
|
|
7458
|
+
get isInvalid() {
|
|
7459
|
+
return this.isVisible() ?? (this.control().invalid && this.control().dirty);
|
|
7460
|
+
}
|
|
7461
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiGeneralControlErrorHintComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7462
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CuiGeneralControlErrorHintComponent, isStandalone: true, selector: "cui-general-control-error-hint", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null }, isVisible: { classPropertyName: "isVisible", publicName: "isVisible", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\r\n @if (isInvalid) {\r\n @if (control().errors; as errors) {\r\n <cui-hint hintType=\"error\">\r\n @if (errors['required']) {\r\n {{ t('FIELD_IS_REQUIRED') }}\r\n } @else if (errors['maxlength']) {\r\n {{ t('PLEASE_KEEP_FIELD_UNDER_CHARACTERS', { value: errors['maxlength'].requiredLength }) }}\r\n } @else if (errors['extraSpaces']) {\r\n {{ t('MUST_BE_WITHOUT_EXTRA_SPACES') }}\r\n } @else if (errors['min']) {\r\n {{ t('MIN_VALUE_MUST_BE_MORE_THAN', { value: errors['min'].min }) }}\r\n } @else if (errors['max']) {\r\n {{ t('MAX_VALUE_MUST_BE_LESS_THAN', { value: errors['max'].max }) }}\r\n }\r\n </cui-hint>\r\n }\r\n }\r\n</ng-container>\r\n", styles: [":host{display:inline-block}:host:empty{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CuiHintModule }, { kind: "component", type: CuiHintComponent, selector: "cui-hint", inputs: ["hintType"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.Default }); }
|
|
7463
|
+
}
|
|
7464
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiGeneralControlErrorHintComponent, decorators: [{
|
|
7465
|
+
type: Component,
|
|
7466
|
+
args: [{ selector: 'cui-general-control-error-hint', imports: [CuiHintModule, TranslocoDirective], standalone: true, changeDetection: ChangeDetectionStrategy.Default, template: "<ng-container *transloco=\"let t\">\r\n @if (isInvalid) {\r\n @if (control().errors; as errors) {\r\n <cui-hint hintType=\"error\">\r\n @if (errors['required']) {\r\n {{ t('FIELD_IS_REQUIRED') }}\r\n } @else if (errors['maxlength']) {\r\n {{ t('PLEASE_KEEP_FIELD_UNDER_CHARACTERS', { value: errors['maxlength'].requiredLength }) }}\r\n } @else if (errors['extraSpaces']) {\r\n {{ t('MUST_BE_WITHOUT_EXTRA_SPACES') }}\r\n } @else if (errors['min']) {\r\n {{ t('MIN_VALUE_MUST_BE_MORE_THAN', { value: errors['min'].min }) }}\r\n } @else if (errors['max']) {\r\n {{ t('MAX_VALUE_MUST_BE_LESS_THAN', { value: errors['max'].max }) }}\r\n }\r\n </cui-hint>\r\n }\r\n }\r\n</ng-container>\r\n", styles: [":host{display:inline-block}:host:empty{display:none}\n"] }]
|
|
7467
|
+
}] });
|
|
7468
|
+
|
|
7469
|
+
class CuiUtilityInfoComponent {
|
|
7470
|
+
get controls() {
|
|
7471
|
+
return this.form.controls;
|
|
7472
|
+
}
|
|
7473
|
+
get isTitleError() {
|
|
7474
|
+
return this.controls.title.invalid && this.controls.title.dirty;
|
|
7475
|
+
}
|
|
7476
|
+
get isDescriptionError() {
|
|
7477
|
+
return this.controls.description.invalid && this.controls.description.dirty;
|
|
7478
|
+
}
|
|
7479
|
+
constructor() {
|
|
7480
|
+
this.destroy = inject(DestroyRef);
|
|
7481
|
+
this.formBuilder = inject(NonNullableFormBuilder);
|
|
7482
|
+
this.translocoService = inject(TranslocoService);
|
|
7483
|
+
this.frameApiService = inject(CuiFrameApiService);
|
|
7484
|
+
this.cuiAlertService = inject(CuiAlertService);
|
|
7485
|
+
this.cuiIdService = inject(CuiIdService);
|
|
7486
|
+
this.CONTROL_DELAY = 500;
|
|
7487
|
+
this.MAX_FILE_SIZE = 20971520;
|
|
7488
|
+
this.titleId = this.cuiIdService.generate();
|
|
7489
|
+
this.descriptionId = this.cuiIdService.generate();
|
|
7490
|
+
this.form = this.formBuilder.group({
|
|
7491
|
+
title: this.formBuilder.control('', createDefaultValidators({ asyncDelay: this.CONTROL_DELAY })),
|
|
7492
|
+
description: this.formBuilder.control('', createDefaultValidators({ asyncDelay: this.CONTROL_DELAY }))
|
|
7493
|
+
});
|
|
7494
|
+
this.isDescriptionModalOpen = signal(false);
|
|
7495
|
+
this.isDescriptionEmpty = signal(false);
|
|
7496
|
+
this.editorId = signal(null);
|
|
7497
|
+
this.thumbnail = signal(null);
|
|
7498
|
+
this.thumbnailUrl = computed(() => {
|
|
7499
|
+
const thumbnail = this.thumbnail();
|
|
7500
|
+
if (thumbnail?.resource) {
|
|
7501
|
+
return thumbnail.resource;
|
|
7502
|
+
}
|
|
7503
|
+
return this.baseResourceUrl() + thumbnail.fileId;
|
|
7504
|
+
});
|
|
7505
|
+
this.uploadButtonName = computed(() => {
|
|
7506
|
+
const thumbnail = this.thumbnail();
|
|
7507
|
+
if (thumbnail?.name) {
|
|
7508
|
+
return this.translocoService.translate('REPLACE_FILE');
|
|
7509
|
+
}
|
|
7510
|
+
return this.translocoService.translate('UPLOAD_FILE');
|
|
7511
|
+
});
|
|
7512
|
+
this.heading = null;
|
|
7513
|
+
this.title = input.required();
|
|
7514
|
+
this.framerId = input.required();
|
|
7515
|
+
this.baseResourceUrl = input.required();
|
|
7516
|
+
this.config = input.required();
|
|
7517
|
+
this.formChanged = output();
|
|
7518
|
+
this.isFormValidChanged = output();
|
|
7519
|
+
this.initUtilityEffect();
|
|
7520
|
+
}
|
|
7521
|
+
onSelectFile() {
|
|
7522
|
+
const input = document.createElement('input');
|
|
7523
|
+
input.type = 'file';
|
|
7524
|
+
input.accept = 'image/jpg, image/jpeg, image/png, video/mp4';
|
|
7525
|
+
input.onchange = () => {
|
|
7526
|
+
const files = input.files;
|
|
7527
|
+
if (!files?.length) {
|
|
7528
|
+
return;
|
|
7529
|
+
}
|
|
7530
|
+
this.getFile(files);
|
|
7531
|
+
};
|
|
7532
|
+
input.click();
|
|
7533
|
+
}
|
|
7534
|
+
onEditorEmpty(isEmpty) {
|
|
7535
|
+
this.isDescriptionEmpty.set(isEmpty);
|
|
7536
|
+
this.isFormValidChanged.emit(this.checkFormValidation());
|
|
7537
|
+
}
|
|
7538
|
+
onRemoveThumbnail() {
|
|
7539
|
+
const frameId = this.framerId();
|
|
7540
|
+
const fragmentId = this.thumbnail()?.id;
|
|
7541
|
+
if (!frameId || !fragmentId) {
|
|
7542
|
+
return;
|
|
7543
|
+
}
|
|
7544
|
+
this.frameApiService.deleteResource(frameId, fragmentId).subscribe(() => {
|
|
7545
|
+
this.thumbnail.update((prev) => ({ ...prev, fileId: null, name: null, resource: null }));
|
|
7546
|
+
});
|
|
7547
|
+
}
|
|
7548
|
+
onToggleDescriptionModal() {
|
|
7549
|
+
this.isDescriptionModalOpen.update((prev) => !prev);
|
|
7550
|
+
}
|
|
7551
|
+
initUtilityEffect() {
|
|
7552
|
+
const effectRef = effect(() => {
|
|
7553
|
+
const title = this.title();
|
|
7554
|
+
if (!title) {
|
|
7555
|
+
return;
|
|
7556
|
+
}
|
|
7557
|
+
this.initTitleSubscriptions();
|
|
7558
|
+
this.initFrameFragments();
|
|
7559
|
+
effectRef.destroy();
|
|
7560
|
+
});
|
|
7561
|
+
}
|
|
7562
|
+
initTitleSubscriptions() {
|
|
7563
|
+
this.form.patchValue({ title: this.title() });
|
|
7564
|
+
this.form.statusChanges
|
|
7565
|
+
.pipe(takeUntilDestroyed(this.destroy))
|
|
7566
|
+
.subscribe(() => this.isFormValidChanged.emit(this.checkFormValidation()));
|
|
7567
|
+
this.form.valueChanges
|
|
7568
|
+
.pipe(takeUntilDestroyed(this.destroy), startWith(this.form.value), pairwise(), debounceTime(this.CONTROL_DELAY), map(([prev, current]) => this.compareFormValues([prev, current])))
|
|
7569
|
+
.subscribe((value) => {
|
|
7570
|
+
this.formChanged.emit(value);
|
|
7571
|
+
});
|
|
7572
|
+
}
|
|
7573
|
+
initFrameFragments() {
|
|
7574
|
+
const frameId = this.framerId();
|
|
7575
|
+
if (!frameId) {
|
|
7576
|
+
return;
|
|
7577
|
+
}
|
|
7578
|
+
this.frameApiService.getFrame(frameId).subscribe((frame) => {
|
|
7579
|
+
frame.fragments.forEach((fragment) => {
|
|
7580
|
+
if (fragment.type === "J_TEXT" /* FragmentType.jText */) {
|
|
7581
|
+
this.editorId.set(fragment?.id);
|
|
7582
|
+
}
|
|
7583
|
+
if (fragment.type === "RESOURCE_FILE" /* FragmentType.resourceFile */) {
|
|
7584
|
+
this.setResourceFile(fragment);
|
|
7585
|
+
}
|
|
7586
|
+
});
|
|
7587
|
+
});
|
|
7588
|
+
}
|
|
7589
|
+
compareFormValues([prevGroup, currentGruop]) {
|
|
7590
|
+
const keys = Object.keys(currentGruop);
|
|
7591
|
+
const changedFields = {};
|
|
7592
|
+
keys.forEach((key) => {
|
|
7593
|
+
const prev = prevGroup[key];
|
|
7594
|
+
const current = currentGruop[key];
|
|
7595
|
+
if (prev === current) {
|
|
7596
|
+
return;
|
|
7597
|
+
}
|
|
7598
|
+
changedFields[key] = current;
|
|
7599
|
+
});
|
|
7600
|
+
return changedFields;
|
|
7601
|
+
}
|
|
7602
|
+
setResourceFile(resource) {
|
|
7603
|
+
const url = this.baseResourceUrl() + resource.fileId;
|
|
7604
|
+
this.thumbnail.set(resource);
|
|
7605
|
+
if (!url || resource?.name?.split('.').pop() !== 'mp4') {
|
|
7606
|
+
return;
|
|
7607
|
+
}
|
|
7608
|
+
this.getCaptureFromVideo(url);
|
|
7609
|
+
}
|
|
7610
|
+
getFile(files) {
|
|
7611
|
+
const file = files.item(0);
|
|
7612
|
+
if (!file) {
|
|
7613
|
+
return;
|
|
7614
|
+
}
|
|
7615
|
+
if (file.size > this.MAX_FILE_SIZE) {
|
|
7616
|
+
this.cuiAlertService
|
|
7617
|
+
.open(this.translocoService.translate('INVALID_FILE_SIZE'), {
|
|
7618
|
+
status: 'error'
|
|
7619
|
+
})
|
|
7620
|
+
.subscribe();
|
|
7621
|
+
return;
|
|
7622
|
+
}
|
|
7623
|
+
const isVideo = file.name.split('.').at(-1) === 'mp4';
|
|
7624
|
+
const url = URL.createObjectURL(file);
|
|
7625
|
+
if (isVideo) {
|
|
7626
|
+
this.getCaptureFromVideo(url, file);
|
|
7627
|
+
}
|
|
7628
|
+
else {
|
|
7629
|
+
this.thumbnail.update((prev) => ({ ...prev, name: file.name, resource: url }));
|
|
7630
|
+
}
|
|
7631
|
+
this.uploadFile(file);
|
|
7632
|
+
}
|
|
7633
|
+
uploadFile(file) {
|
|
7634
|
+
const frameId = this.framerId();
|
|
7635
|
+
const fragmentId = this.thumbnail()?.id;
|
|
7636
|
+
if (!frameId || !fragmentId) {
|
|
7637
|
+
return;
|
|
7638
|
+
}
|
|
7639
|
+
const formData = new FormData();
|
|
7640
|
+
formData.append('resource', file);
|
|
7641
|
+
this.frameApiService.uploadResource(formData, frameId, fragmentId).subscribe();
|
|
7642
|
+
}
|
|
7643
|
+
getCaptureFromVideo(url, file) {
|
|
7644
|
+
const canvas = document.createElement('canvas');
|
|
7645
|
+
const video = document.createElement('video');
|
|
7646
|
+
video.src = url;
|
|
7647
|
+
video.currentTime = 1;
|
|
7648
|
+
canvas.width = 184;
|
|
7649
|
+
canvas.height = 120;
|
|
7650
|
+
video.onloadeddata = () => {
|
|
7651
|
+
const context = canvas.getContext('2d');
|
|
7652
|
+
if (!context) {
|
|
7653
|
+
return;
|
|
7654
|
+
}
|
|
7655
|
+
context.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
7656
|
+
canvas.toBlob((blob) => {
|
|
7657
|
+
if (!blob) {
|
|
7658
|
+
return;
|
|
7659
|
+
}
|
|
7660
|
+
const videoCaptureUrl = URL.createObjectURL(blob);
|
|
7661
|
+
this.thumbnail.update((prev) => ({
|
|
7662
|
+
...prev,
|
|
7663
|
+
name: (file?.name || prev?.name),
|
|
7664
|
+
resource: videoCaptureUrl
|
|
7665
|
+
}));
|
|
7666
|
+
});
|
|
7667
|
+
};
|
|
7668
|
+
video.load();
|
|
7669
|
+
}
|
|
7670
|
+
checkFormValidation() {
|
|
7671
|
+
console.log(this.isDescriptionEmpty(), this.form.invalid);
|
|
7672
|
+
return !this.isDescriptionEmpty() && !this.form.invalid;
|
|
7673
|
+
}
|
|
7674
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiUtilityInfoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7675
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CuiUtilityInfoComponent, isStandalone: true, selector: "cui-utility-info", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, framerId: { classPropertyName: "framerId", publicName: "framerId", isSignal: true, isRequired: true, transformFunction: null }, baseResourceUrl: { classPropertyName: "baseResourceUrl", publicName: "baseResourceUrl", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { formChanged: "formChanged", isFormValidChanged: "isFormValidChanged" }, ngImport: i0, template: "<ng-container *transloco=\"let t\">\r\n <section class=\"content\">\r\n <cui-form-field>\r\n <label cuiLabel [isRequired]=\"true\" [for]=\"titleId\">\r\n {{ t('TITLE') }}\r\n </label>\r\n <cui-input-text\r\n [cuiTextFieldId]=\"titleId\"\r\n [cuiTextFieldPlaceholder]=\"t('ADD_TITLE')\"\r\n [cuiTextFieldIsError]=\"isTitleError\"\r\n [formControl]=\"form.controls.title\"\r\n />\r\n @if (isTitleError) {\r\n <cui-general-control-error-hint [control]=\"form.controls.title\" [isVisible]=\"true\" />\r\n }\r\n </cui-form-field>\r\n <cui-form-field>\r\n <label cuiLabel [isRequired]=\"true\" [for]=\"descriptionId\">\r\n {{ t('SHORT_DESCRIPTION') }}\r\n </label>\r\n <cui-input-text\r\n [cuiTextFieldId]=\"descriptionId\"\r\n cuiTextFieldPlaceholder=\"{{t('SHORT_DESCRIPTION')}}...\"\r\n [cuiTextFieldIsError]=\"isDescriptionError\"\r\n [formControl]=\"form.controls.description\"\r\n />\r\n @if (isDescriptionError) {\r\n <cui-general-control-error-hint [control]=\"form.controls.description\" [isVisible]=\"true\" />\r\n }\r\n </cui-form-field>\r\n <section class=\"file\">\r\n <span class=\"title\">{{ t('THUMBNAIL') }}</span>\r\n <div class=\"content__upload\">\r\n <div class=\"content__upload-file\">\r\n @if (thumbnail()?.name; as fileId) {\r\n <div class=\"image\">\r\n <span class=\"image__name\">{{ thumbnail()?.name }}</span>\r\n <!-- TODO: ngSrc -->\r\n <img class=\"image__view\" [src]=\"thumbnailUrl()\" height=\"120\" width=\"184\" alt=\"Thumbnail\" />\r\n </div>\r\n }\r\n <button type=\"button\" cuiButton appearance=\"outlined-gray\" size=\"xxs\" icon=\"cuiIconUpload\"\r\n (click)=\"onSelectFile()\">\r\n {{ uploadButtonName() }}\r\n </button>\r\n @if (thumbnail()?.name) {\r\n <button class=\"content__remove-button\" cuiButton appearance=\"link\" size=\"sm\" type=\"button\"\r\n (click)=\"onRemoveThumbnail()\">\r\n {{ t('REMOVE') }}\r\n </button>\r\n }\r\n <span class=\"content__accepted\">\r\n {{ t('ACCEPTED') }}: JPG, JPEG, PNG, MP4 {{ t('UP_TO') }} 20MB\r\n </span>\r\n </div>\r\n </div>\r\n </section>\r\n @if (editorId(); as editorId) {\r\n <cui-editor-block\r\n [title]=\"form.controls.title.value || title()\"\r\n [config]=\"config()\"\r\n [editorId]=\"editorId\"\r\n [required]=\"true\"\r\n (editorEmpty)=\"onEditorEmpty($event)\"\r\n ></cui-editor-block>\r\n }\r\n </section>\r\n</ng-container>\r\n", styles: ["::ng-deep cui-dialog:has(.instruction-description-modal){inset:0;margin:auto;transform:none!important}:host{display:block}.title{font-weight:500;font-size:14px;line-height:20px;display:flex;gap:2px}.title_required{color:var(--cui-danger)}.content{display:flex;flex-direction:column;gap:16px;padding:16px 24px}.content__upload{padding:12px 16px;border-radius:8px;border:1px solid var(--cui-base-200);background:var(--cui-base-10)}.content__accepted{color:var(--cui-base-500)}.content__upload-file{display:flex;align-items:center;gap:8px}.content__upload-file input[type=file]{display:none}.content__remove-button ::ng-deep .c-content{color:var(--cui-danger)!important}.file{display:flex;flex-direction:column;gap:4px}.description_invalid{border:1px solid var(--cui-danger)}.image{position:relative;display:inline-block}.image__view{border-radius:8px;object-fit:cover}.image__name{position:absolute;top:6px;left:14px;color:var(--cui-base-0);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:170px;z-index:1}.image:after{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background-color:#0003;z-index:0;pointer-events:none;border-radius:8px}.button-save{margin-left:auto}.instruction-description-modal{text-transform:none}.empty{padding:16px;color:var(--cui-base-500);text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CuiAccordionModule) }, { kind: "ngmodule", type: i0.forwardRef(() => CuiButtonModule) }, { kind: "component", type: i0.forwardRef(() => CuiButtonComponent), selector: "button[cuiButton], a[cuiButton]", inputs: ["shape", "disabled", "isLoaderShown", "icon", "iconRight", "appearance", "size"] }, { kind: "ngmodule", type: i0.forwardRef(() => CuiFormFieldModule) }, { kind: "component", type: i0.forwardRef(() => CuiFormFieldComponent), selector: "cui-form-field" }, { kind: "ngmodule", type: i0.forwardRef(() => CuiHintModule) }, { kind: "ngmodule", type: i0.forwardRef(() => CuiInputModule) }, { kind: "component", type: i0.forwardRef(() => CuiInputTextComponent), selector: "cui-input-text" }, { kind: "directive", type: i0.forwardRef(() => CuiTextFieldIdDirective), selector: "[cuiTextFieldId]", inputs: ["cuiTextFieldId"] }, { kind: "directive", type: i0.forwardRef(() => CuiTextFieldPlaceholderDirective), selector: "[cuiTextFieldPlaceholder]", inputs: ["cuiTextFieldPlaceholder"] }, { kind: "directive", type: i0.forwardRef(() => CuiTextFieldIsErrorDirective), selector: "[cuiTextFieldIsError]", inputs: ["cuiTextFieldIsError"] }, { kind: "ngmodule", type: i0.forwardRef(() => CuiLabelModule) }, { kind: "component", type: i0.forwardRef(() => CuiLabelComponent), selector: "label[cuiLabel]", inputs: ["isRequired"] }, { kind: "component", type: i0.forwardRef(() => CuiEditorBlockComponent), selector: "cui-editor-block", inputs: ["title", "editorId", "config", "required"], outputs: ["editorEmpty"] }, { kind: "component", type: i0.forwardRef(() => CuiGeneralControlErrorHintComponent), selector: "cui-general-control-error-hint", inputs: ["control", "isVisible"] }, { kind: "ngmodule", type: i0.forwardRef(() => ReactiveFormsModule) }, { kind: "directive", type: i0.forwardRef(() => i2$1.NgControlStatus), selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i0.forwardRef(() => i2$1.FormControlDirective), selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i0.forwardRef(() => TranslocoDirective), selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7676
|
+
}
|
|
7677
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiUtilityInfoComponent, decorators: [{
|
|
7678
|
+
type: Component,
|
|
7679
|
+
args: [{ selector: 'cui-utility-info', imports: [
|
|
7680
|
+
CuiAccordionModule,
|
|
7681
|
+
CuiButtonModule,
|
|
7682
|
+
CuiFormFieldModule,
|
|
7683
|
+
CuiHintModule,
|
|
7684
|
+
CuiInputModule,
|
|
7685
|
+
CuiLabelModule,
|
|
7686
|
+
forwardRef(() => CuiEditorBlockComponent),
|
|
7687
|
+
CuiGeneralControlErrorHintComponent,
|
|
7688
|
+
ReactiveFormsModule,
|
|
7689
|
+
TranslocoDirective,
|
|
7690
|
+
CuiTooltip
|
|
7691
|
+
], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\r\n <section class=\"content\">\r\n <cui-form-field>\r\n <label cuiLabel [isRequired]=\"true\" [for]=\"titleId\">\r\n {{ t('TITLE') }}\r\n </label>\r\n <cui-input-text\r\n [cuiTextFieldId]=\"titleId\"\r\n [cuiTextFieldPlaceholder]=\"t('ADD_TITLE')\"\r\n [cuiTextFieldIsError]=\"isTitleError\"\r\n [formControl]=\"form.controls.title\"\r\n />\r\n @if (isTitleError) {\r\n <cui-general-control-error-hint [control]=\"form.controls.title\" [isVisible]=\"true\" />\r\n }\r\n </cui-form-field>\r\n <cui-form-field>\r\n <label cuiLabel [isRequired]=\"true\" [for]=\"descriptionId\">\r\n {{ t('SHORT_DESCRIPTION') }}\r\n </label>\r\n <cui-input-text\r\n [cuiTextFieldId]=\"descriptionId\"\r\n cuiTextFieldPlaceholder=\"{{t('SHORT_DESCRIPTION')}}...\"\r\n [cuiTextFieldIsError]=\"isDescriptionError\"\r\n [formControl]=\"form.controls.description\"\r\n />\r\n @if (isDescriptionError) {\r\n <cui-general-control-error-hint [control]=\"form.controls.description\" [isVisible]=\"true\" />\r\n }\r\n </cui-form-field>\r\n <section class=\"file\">\r\n <span class=\"title\">{{ t('THUMBNAIL') }}</span>\r\n <div class=\"content__upload\">\r\n <div class=\"content__upload-file\">\r\n @if (thumbnail()?.name; as fileId) {\r\n <div class=\"image\">\r\n <span class=\"image__name\">{{ thumbnail()?.name }}</span>\r\n <!-- TODO: ngSrc -->\r\n <img class=\"image__view\" [src]=\"thumbnailUrl()\" height=\"120\" width=\"184\" alt=\"Thumbnail\" />\r\n </div>\r\n }\r\n <button type=\"button\" cuiButton appearance=\"outlined-gray\" size=\"xxs\" icon=\"cuiIconUpload\"\r\n (click)=\"onSelectFile()\">\r\n {{ uploadButtonName() }}\r\n </button>\r\n @if (thumbnail()?.name) {\r\n <button class=\"content__remove-button\" cuiButton appearance=\"link\" size=\"sm\" type=\"button\"\r\n (click)=\"onRemoveThumbnail()\">\r\n {{ t('REMOVE') }}\r\n </button>\r\n }\r\n <span class=\"content__accepted\">\r\n {{ t('ACCEPTED') }}: JPG, JPEG, PNG, MP4 {{ t('UP_TO') }} 20MB\r\n </span>\r\n </div>\r\n </div>\r\n </section>\r\n @if (editorId(); as editorId) {\r\n <cui-editor-block\r\n [title]=\"form.controls.title.value || title()\"\r\n [config]=\"config()\"\r\n [editorId]=\"editorId\"\r\n [required]=\"true\"\r\n (editorEmpty)=\"onEditorEmpty($event)\"\r\n ></cui-editor-block>\r\n }\r\n </section>\r\n</ng-container>\r\n", styles: ["::ng-deep cui-dialog:has(.instruction-description-modal){inset:0;margin:auto;transform:none!important}:host{display:block}.title{font-weight:500;font-size:14px;line-height:20px;display:flex;gap:2px}.title_required{color:var(--cui-danger)}.content{display:flex;flex-direction:column;gap:16px;padding:16px 24px}.content__upload{padding:12px 16px;border-radius:8px;border:1px solid var(--cui-base-200);background:var(--cui-base-10)}.content__accepted{color:var(--cui-base-500)}.content__upload-file{display:flex;align-items:center;gap:8px}.content__upload-file input[type=file]{display:none}.content__remove-button ::ng-deep .c-content{color:var(--cui-danger)!important}.file{display:flex;flex-direction:column;gap:4px}.description_invalid{border:1px solid var(--cui-danger)}.image{position:relative;display:inline-block}.image__view{border-radius:8px;object-fit:cover}.image__name{position:absolute;top:6px;left:14px;color:var(--cui-base-0);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:170px;z-index:1}.image:after{content:\"\";position:absolute;top:0;left:0;width:100%;height:100%;background-color:#0003;z-index:0;pointer-events:none;border-radius:8px}.button-save{margin-left:auto}.instruction-description-modal{text-transform:none}.empty{padding:16px;color:var(--cui-base-500);text-align:center}\n"] }]
|
|
7692
|
+
}], ctorParameters: () => [] });
|
|
7693
|
+
|
|
7694
|
+
class CuiSelectedCategoryService {
|
|
7695
|
+
constructor() {
|
|
7696
|
+
this.editingIdSignal = signal(null);
|
|
7697
|
+
this.creatingIdSignal = signal(null);
|
|
7698
|
+
this.categorySignal = signal(null);
|
|
7699
|
+
this.editingId = this.editingIdSignal.asReadonly();
|
|
7700
|
+
this.creatingId = this.creatingIdSignal.asReadonly();
|
|
7701
|
+
this.category = this.categorySignal.asReadonly();
|
|
7702
|
+
}
|
|
7703
|
+
setCurrentCategory(category) {
|
|
7704
|
+
this.categorySignal.set(category);
|
|
7705
|
+
}
|
|
7706
|
+
setEditingId(id) {
|
|
7707
|
+
this.editingIdSignal.set(id);
|
|
7708
|
+
this.clearCreatingId();
|
|
7709
|
+
}
|
|
7710
|
+
setCreatingId(id) {
|
|
7711
|
+
this.creatingIdSignal.set(id);
|
|
7712
|
+
this.clearEditingId();
|
|
7713
|
+
}
|
|
7714
|
+
clearEditingId() {
|
|
7715
|
+
this.editingIdSignal.set('');
|
|
7716
|
+
}
|
|
7717
|
+
clearCreatingId() {
|
|
7718
|
+
this.creatingIdSignal.set('');
|
|
7719
|
+
}
|
|
7720
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiSelectedCategoryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
7721
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiSelectedCategoryService, providedIn: 'root' }); }
|
|
7722
|
+
}
|
|
7723
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiSelectedCategoryService, decorators: [{
|
|
7724
|
+
type: Injectable,
|
|
7725
|
+
args: [{
|
|
7726
|
+
providedIn: 'root'
|
|
7727
|
+
}]
|
|
7728
|
+
}] });
|
|
7729
|
+
|
|
7730
|
+
class CuiCategoryFormComponent {
|
|
7731
|
+
get isTitleInvalid() {
|
|
7732
|
+
return this.titleControl.invalid && this.titleControl.dirty;
|
|
7733
|
+
}
|
|
7734
|
+
get isSubmitButtonDisabled() {
|
|
7735
|
+
return this.isDisabled() || this.form.invalid;
|
|
7736
|
+
}
|
|
7737
|
+
constructor() {
|
|
7738
|
+
this.nonNullableFormBuilder = inject(NonNullableFormBuilder);
|
|
7739
|
+
this.form = this.nonNullableFormBuilder.group({
|
|
7740
|
+
title: ['', createDefaultValidators({ asyncDelay: 0 })]
|
|
7741
|
+
});
|
|
7742
|
+
this.titleControl = this.form.controls.title;
|
|
7743
|
+
this.isDisabled = input(false);
|
|
7744
|
+
this.defaultTitle = input('');
|
|
7745
|
+
this.created = output();
|
|
7746
|
+
this.canceled = output();
|
|
7747
|
+
this.input = viewChild.required('input', { read: (ElementRef) });
|
|
7748
|
+
this.initInputDisableStateSubscription();
|
|
7749
|
+
}
|
|
7750
|
+
ngOnInit() {
|
|
7751
|
+
this.initDefaultTitle();
|
|
7752
|
+
this.initInputFocus();
|
|
7753
|
+
}
|
|
7754
|
+
onHostClick(event) {
|
|
7755
|
+
event.stopPropagation();
|
|
7756
|
+
}
|
|
7757
|
+
onSubmit() {
|
|
7758
|
+
if (this.form.invalid) {
|
|
7759
|
+
return;
|
|
7760
|
+
}
|
|
7761
|
+
this.created.emit(this.form.value.title);
|
|
7762
|
+
}
|
|
7763
|
+
onCancel(event) {
|
|
7764
|
+
event.stopPropagation();
|
|
7765
|
+
this.canceled.emit();
|
|
7766
|
+
}
|
|
7767
|
+
initInputDisableStateSubscription() {
|
|
7768
|
+
effect(() => {
|
|
7769
|
+
if (this.isDisabled()) {
|
|
7770
|
+
this.titleControl.disable();
|
|
7771
|
+
return;
|
|
7772
|
+
}
|
|
7773
|
+
this.titleControl.enable();
|
|
7774
|
+
});
|
|
7775
|
+
}
|
|
7776
|
+
initDefaultTitle() {
|
|
7777
|
+
this.form.patchValue({ title: this.defaultTitle() });
|
|
7778
|
+
}
|
|
7779
|
+
initInputFocus() {
|
|
7780
|
+
Promise.resolve().then(() => this.input().nativeElement.focus());
|
|
7781
|
+
}
|
|
7782
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiCategoryFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7783
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "18.2.13", type: CuiCategoryFormComponent, isStandalone: true, selector: "cui-category-form", inputs: { isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null }, defaultTitle: { classPropertyName: "defaultTitle", publicName: "defaultTitle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { created: "created", canceled: "canceled" }, host: { listeners: { "click": "onHostClick($event)" } }, viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t\">\r\n <form\r\n [formGroup]=\"form\"\r\n class=\"form\"\r\n (ngSubmit)=\"onSubmit()\"\r\n >\r\n <div class=\"input\">\r\n <input\r\n #input\r\n cuiGhostInput\r\n formControlName=\"title\"\r\n type=\"text\"\r\n placeholder=\"{{ t('ADD_CATEGORY_NAME') }}...\"\r\n [isError]=\"isTitleInvalid\"\r\n (keyup)=\"$event.preventDefault()\"\r\n />\r\n <cui-general-control-error-hint [control]=\"titleControl\" />\r\n </div>\r\n <button\r\n cuiIconButton\r\n type=\"submit\"\r\n icon=\"cuiIconCheck\"\r\n color=\"var(--cui-success)\"\r\n [disabled]=\"isSubmitButtonDisabled\"\r\n class=\"button\"\r\n ></button>\r\n </form>\r\n <button\r\n cuiIconButton\r\n type=\"button\"\r\n icon=\"cuiIconXCircle\"\r\n color=\"var(--cui-danger)\"\r\n (click)=\"onCancel($event)\"\r\n [disabled]=\"isDisabled()\"\r\n class=\"button\"\r\n ></button>\r\n</ng-container>\r\n", styles: [":host{padding-top:2px;padding-bottom:2px;display:flex;gap:4px;flex-grow:1}.form,.input{flex-grow:1}.form{display:flex;gap:4px}.input{display:flex;flex-direction:column;gap:4px;align-items:flex-start}.button{width:28px}.button:disabled{opacity:.5}\n"], dependencies: [{ kind: "ngmodule", type: CuiFormFieldModule }, { kind: "ngmodule", type: CuiHintModule }, { kind: "ngmodule", type: CuiIconButtonModule }, { kind: "component", type: CuiIconButtonComponent, selector: "button[cuiIconButton][icon], a[cuiIconButton][icon]", inputs: ["icon", "color", "hoverColor"] }, { kind: "component", type: CuiGeneralControlErrorHintComponent, selector: "cui-general-control-error-hint", inputs: ["control", "isVisible"] }, { kind: "component", type: CuiGhostInputComponent, selector: "input [cuiGhostInput]", inputs: ["isError"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7784
|
+
}
|
|
7785
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiCategoryFormComponent, decorators: [{
|
|
7786
|
+
type: Component,
|
|
7787
|
+
args: [{ selector: 'cui-category-form', imports: [
|
|
7788
|
+
CuiFormFieldModule,
|
|
7789
|
+
CuiHintModule,
|
|
7790
|
+
CuiIconButtonModule,
|
|
7791
|
+
CuiGeneralControlErrorHintComponent,
|
|
7792
|
+
CuiGhostInputComponent,
|
|
7793
|
+
ReactiveFormsModule,
|
|
7794
|
+
TranslocoDirective
|
|
7795
|
+
], standalone: true, host: {
|
|
7796
|
+
'(click)': 'onHostClick($event)'
|
|
7797
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *transloco=\"let t\">\r\n <form\r\n [formGroup]=\"form\"\r\n class=\"form\"\r\n (ngSubmit)=\"onSubmit()\"\r\n >\r\n <div class=\"input\">\r\n <input\r\n #input\r\n cuiGhostInput\r\n formControlName=\"title\"\r\n type=\"text\"\r\n placeholder=\"{{ t('ADD_CATEGORY_NAME') }}...\"\r\n [isError]=\"isTitleInvalid\"\r\n (keyup)=\"$event.preventDefault()\"\r\n />\r\n <cui-general-control-error-hint [control]=\"titleControl\" />\r\n </div>\r\n <button\r\n cuiIconButton\r\n type=\"submit\"\r\n icon=\"cuiIconCheck\"\r\n color=\"var(--cui-success)\"\r\n [disabled]=\"isSubmitButtonDisabled\"\r\n class=\"button\"\r\n ></button>\r\n </form>\r\n <button\r\n cuiIconButton\r\n type=\"button\"\r\n icon=\"cuiIconXCircle\"\r\n color=\"var(--cui-danger)\"\r\n (click)=\"onCancel($event)\"\r\n [disabled]=\"isDisabled()\"\r\n class=\"button\"\r\n ></button>\r\n</ng-container>\r\n", styles: [":host{padding-top:2px;padding-bottom:2px;display:flex;gap:4px;flex-grow:1}.form,.input{flex-grow:1}.form{display:flex;gap:4px}.input{display:flex;flex-direction:column;gap:4px;align-items:flex-start}.button{width:28px}.button:disabled{opacity:.5}\n"] }]
|
|
7798
|
+
}], ctorParameters: () => [] });
|
|
7799
|
+
|
|
7800
|
+
class CuiCreateCategoryItemComponent {
|
|
7801
|
+
constructor() {
|
|
7802
|
+
this.created = output();
|
|
7803
|
+
this.canceled = output();
|
|
7804
|
+
this.isDisabled = input(false);
|
|
7805
|
+
}
|
|
7806
|
+
onSubmit(title) {
|
|
7807
|
+
this.created.emit(title);
|
|
7808
|
+
}
|
|
7809
|
+
onCancel() {
|
|
7810
|
+
this.canceled.emit();
|
|
7811
|
+
}
|
|
7812
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiCreateCategoryItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7813
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: CuiCreateCategoryItemComponent, isStandalone: true, selector: "cui-create-category-item", inputs: { isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { created: "created", canceled: "canceled" }, ngImport: i0, template: "<cui-svg\r\n icon=\"cuiIconFolder\"\r\n color=\"var(--cui-base-500)\"\r\n class=\"icon\"\r\n/>\r\n<cui-category-form\r\n [isDisabled]=\"isDisabled()\"\r\n (created)=\"onSubmit($event)\"\r\n (canceled)=\"onCancel()\"\r\n/>\r\n", styles: [":host{padding-right:4px;padding-left:4px;display:flex;gap:4px;align-items:flex-start;min-height:32px}.icon{padding:6px 2px}\n"], dependencies: [{ kind: "ngmodule", type: CuiSvgModule }, { kind: "component", type: CuiSvgComponent, selector: "cui-svg[icon]", inputs: ["width", "height", "strokeWidth", "color", "icon"] }, { kind: "component", type: CuiCategoryFormComponent, selector: "cui-category-form", inputs: ["isDisabled", "defaultTitle"], outputs: ["created", "canceled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7814
|
+
}
|
|
7815
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiCreateCategoryItemComponent, decorators: [{
|
|
7816
|
+
type: Component,
|
|
7817
|
+
args: [{ selector: 'cui-create-category-item', imports: [CuiSvgModule, CuiCategoryFormComponent], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<cui-svg\r\n icon=\"cuiIconFolder\"\r\n color=\"var(--cui-base-500)\"\r\n class=\"icon\"\r\n/>\r\n<cui-category-form\r\n [isDisabled]=\"isDisabled()\"\r\n (created)=\"onSubmit($event)\"\r\n (canceled)=\"onCancel()\"\r\n/>\r\n", styles: [":host{padding-right:4px;padding-left:4px;display:flex;gap:4px;align-items:flex-start;min-height:32px}.icon{padding:6px 2px}\n"] }]
|
|
7818
|
+
}] });
|
|
7819
|
+
|
|
7820
|
+
class CuiCategoryItemComponent {
|
|
7821
|
+
constructor() {
|
|
7822
|
+
this.treeStructNavigatorApiService = inject(CuiTreeStructNavigatorApiService);
|
|
7823
|
+
this.selectedCategoryService = inject(CuiSelectedCategoryService);
|
|
7824
|
+
this.isStageCreationLoading = signal(false);
|
|
7825
|
+
this.stageStorageChildren = signal([]);
|
|
7826
|
+
this.areChildrenOpened = signal(false);
|
|
7827
|
+
this.openCloseButtonIcon = computed(() => this.areChildrenOpened() ? 'cuiIconChevronDown' : 'cuiIconChevronRight');
|
|
7828
|
+
this.doChildrenExist = computed(() => this.stageStorage().children.length || this.stageStorageChildren().length);
|
|
7829
|
+
this.isOpenCloseButtonHidden = computed(() => !this.doChildrenExist());
|
|
7830
|
+
this.stageStorageIcon = computed(() => this.areChildrenOpened() && this.doChildrenExist() ? 'cuiIconFolderOpen' : 'cuiIconFolder');
|
|
7831
|
+
this.isSubcategoryCreating = signal(false);
|
|
7832
|
+
this.isSubcategoryCreationLoading = signal(false);
|
|
7833
|
+
this.alignItems = computed(() => (this.isTitleEdit() ? 'flex-start' : 'center'));
|
|
7834
|
+
this.isTitleEdit = computed(() => this.selectedCategoryService.editingId() === this.stageStorage().id);
|
|
7835
|
+
this.isCreateCategoryControlVisible = computed(() => (this.selectedCategoryService.creatingId() === this.stageStorage().id && this.isSubcategoryCreating()) ||
|
|
7836
|
+
this.isSubcategoryCreationLoading());
|
|
7837
|
+
this.stageStorage = input.required();
|
|
7838
|
+
this.categoryTitle = signal('');
|
|
7839
|
+
this.category = computed(() => ({
|
|
7840
|
+
...this.stageStorage(),
|
|
7841
|
+
title: this.categoryTitle() || this.stageStorage().title
|
|
7842
|
+
}));
|
|
7843
|
+
this.initStageStorageChildren();
|
|
7844
|
+
}
|
|
7845
|
+
onSelectCategory() {
|
|
7846
|
+
this.selectedCategoryService.setCurrentCategory(this.category());
|
|
7847
|
+
}
|
|
7848
|
+
onToggleChildren(event) {
|
|
7849
|
+
event.stopPropagation();
|
|
7850
|
+
this.areChildrenOpened.update((value) => !value);
|
|
7851
|
+
if (this.areChildrenOpened()) {
|
|
7852
|
+
return;
|
|
7853
|
+
}
|
|
7854
|
+
this.isSubcategoryCreating.set(false);
|
|
7855
|
+
}
|
|
7856
|
+
onTitleChanged(title) {
|
|
7857
|
+
this.onCancelTitleEdit();
|
|
7858
|
+
if (title === this.category().title) {
|
|
7859
|
+
return;
|
|
7860
|
+
}
|
|
7861
|
+
this.treeStructNavigatorApiService.updateTitle(this.stageStorage().id, title).subscribe(() => {
|
|
7862
|
+
this.categoryTitle.set(title);
|
|
7863
|
+
if (this.category().id === this.selectedCategoryService.category()?.id) {
|
|
7864
|
+
this.selectedCategoryService.setCurrentCategory(this.category());
|
|
7865
|
+
}
|
|
7866
|
+
});
|
|
7867
|
+
}
|
|
7868
|
+
onStartTitleEdit(event) {
|
|
7869
|
+
event?.stopPropagation();
|
|
7870
|
+
this.selectedCategoryService.setEditingId(this.stageStorage().id);
|
|
7871
|
+
this.onCreatingSubcategoryCanceled();
|
|
7872
|
+
}
|
|
7873
|
+
onCancelTitleEdit() {
|
|
7874
|
+
this.selectedCategoryService.clearEditingId();
|
|
7875
|
+
}
|
|
7876
|
+
onStartCreatingSubcategory(event) {
|
|
7877
|
+
event.stopPropagation();
|
|
7878
|
+
this.isSubcategoryCreating.set(true);
|
|
7879
|
+
this.areChildrenOpened.set(true);
|
|
7880
|
+
this.selectedCategoryService.setCreatingId(this.stageStorage().id);
|
|
7881
|
+
}
|
|
7882
|
+
onCreateNewSubcategoryCategory(title) {
|
|
7883
|
+
this.isSubcategoryCreating.set(false);
|
|
7884
|
+
this.isSubcategoryCreationLoading.set(true);
|
|
7885
|
+
this.treeStructNavigatorApiService
|
|
7886
|
+
.createStageStorageToParent(this.stageStorage().id, title)
|
|
7887
|
+
.pipe(finalize(this.isSubcategoryCreationLoading.set.bind(this.isSubcategoryCreationLoading, false)))
|
|
7888
|
+
.subscribe((stateStorage) => {
|
|
7889
|
+
this.stageStorageChildren.update((value) => [...value, stateStorage]);
|
|
7890
|
+
});
|
|
7891
|
+
}
|
|
7892
|
+
onCreatingSubcategoryCanceled() {
|
|
7893
|
+
this.isSubcategoryCreating.set(false);
|
|
7894
|
+
this.selectedCategoryService.clearCreatingId();
|
|
7895
|
+
}
|
|
7896
|
+
initStageStorageChildren() {
|
|
7897
|
+
effect(() => {
|
|
7898
|
+
if (!this.areChildrenOpened() || this.stageStorageChildren().length) {
|
|
7899
|
+
return;
|
|
7900
|
+
}
|
|
7901
|
+
const stageStorage = this.stageStorage();
|
|
7902
|
+
const stageStorageChildren = stageStorage.children;
|
|
7903
|
+
if (!stageStorageChildren.length) {
|
|
7904
|
+
return;
|
|
7905
|
+
}
|
|
7906
|
+
if (typeof stageStorageChildren[0] !== 'string') {
|
|
7907
|
+
this.stageStorageChildren.set(stageStorageChildren);
|
|
7908
|
+
return;
|
|
7909
|
+
}
|
|
7910
|
+
this.treeStructNavigatorApiService.getStageStoragesByParent(stageStorage.id).subscribe((storage) => {
|
|
7911
|
+
this.stageStorageChildren.update((prevStageStorages) => prevStageStorages ? [...prevStageStorages, storage] : [storage]);
|
|
7912
|
+
});
|
|
7913
|
+
}, { allowSignalWrites: true });
|
|
7914
|
+
}
|
|
7915
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiCategoryItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7916
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CuiCategoryItemComponent, isStandalone: true, selector: "cui-category-item", inputs: { stageStorage: { classPropertyName: "stageStorage", publicName: "stageStorage", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<ng-container *cuiLet=\"category() as stage\">\r\n <button\r\n type=\"button\"\r\n [style.align-items]=\"alignItems()\"\r\n [disabled]=\"isStageCreationLoading()\"\r\n class=\"category\"\r\n (click)=\"onSelectCategory()\"\r\n >\r\n <button\r\n type=\"button\"\r\n ccFlexContainerDirective\r\n class=\"category__open-close-button\"\r\n [class.category__open-close-button_hidden]=\"isOpenCloseButtonHidden()\"\r\n (click)=\"onToggleChildren($event)\"\r\n >\r\n <cui-svg\r\n [icon]=\"openCloseButtonIcon()\"\r\n color=\"var(--cui-base-500)\"\r\n />\r\n </button>\r\n <cui-svg\r\n [icon]=\"stageStorageIcon()\"\r\n color=\"var(--cui-base-500)\"\r\n class=\"icon\"\r\n />\r\n @if (isTitleEdit()) {\r\n <cui-category-form\r\n [defaultTitle]=\"stage.title\"\r\n (created)=\"onTitleChanged($event)\"\r\n (canceled)=\"onCancelTitleEdit()\"\r\n />\r\n } @else {\r\n <span class=\"category__title\">{{ stage.title }}</span>\r\n\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconEdit\"\r\n class=\"category__add-subcategory-button\"\r\n (click)=\"onStartTitleEdit($event)\"\r\n ></button>\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconPlus\"\r\n class=\"category__add-subcategory-button\"\r\n (click)=\"onStartCreatingSubcategory($event)\"\r\n ></button>\r\n }\r\n </button>\r\n <div\r\n [hidden]=\"!areChildrenOpened()\"\r\n class=\"list-wrapper\"\r\n >\r\n <cui-categories-list [stageStorages]=\"stageStorageChildren()\" />\r\n @if (isCreateCategoryControlVisible()) {\r\n <cui-create-category-item\r\n class=\"create-category\"\r\n [isDisabled]=\"isSubcategoryCreationLoading()\"\r\n (created)=\"onCreateNewSubcategoryCategory($event)\"\r\n (canceled)=\"onCreatingSubcategoryCanceled()\"\r\n />\r\n }\r\n </div>\r\n</ng-container>\r\n", styles: [".category{display:flex;gap:4px;padding:2px 4px;width:100%;min-height:32px;border-radius:8px}@media (hover: hover){.category:hover{background:var(--cui-base-10)}}.category:active{background:var(--cui-base-10)}.category__open-close-button{padding:2px;border-radius:4px;margin:4px 0}@media (hover: hover){.category__open-close-button:hover{background:var(--cui-base-100)}}.category__open-close-button:active{background:var(--cui-base-100)}.category__open-close-button_hidden{visibility:hidden}.category__title{flex:1;text-align:start;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.category__add-subcategory-button{--cui-base-50: var(--cui-base-200)}.list-wrapper{padding-left:8px}.create-category{margin-left:24px}.icon{padding-right:2px;padding-left:2px;height:28px}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CuiButtonModule) }, { kind: "component", type: i0.forwardRef(() => CuiButtonComponent), selector: "button[cuiButton], a[cuiButton]", inputs: ["shape", "disabled", "isLoaderShown", "icon", "iconRight", "appearance", "size"] }, { kind: "ngmodule", type: i0.forwardRef(() => CuiIconButtonModule) }, { kind: "directive", type: i0.forwardRef(() => CuiLetDirective), selector: "[cuiLet]", inputs: ["cuiLet"] }, { kind: "ngmodule", type: i0.forwardRef(() => CuiSvgModule) }, { kind: "component", type: i0.forwardRef(() => CuiSvgComponent), selector: "cui-svg[icon]", inputs: ["width", "height", "strokeWidth", "color", "icon"] }, { kind: "component", type: i0.forwardRef(() => CuiCategoryFormComponent), selector: "cui-category-form", inputs: ["isDisabled", "defaultTitle"], outputs: ["created", "canceled"] }, { kind: "component", type: i0.forwardRef(() => CuiCreateCategoryItemComponent), selector: "cui-create-category-item", inputs: ["isDisabled"], outputs: ["created", "canceled"] }, { kind: "component", type: i0.forwardRef(() => CuiCategoriesListComponent), selector: "cui-categories-list", inputs: ["stageStorages"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7917
|
+
}
|
|
7918
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiCategoryItemComponent, decorators: [{
|
|
7919
|
+
type: Component,
|
|
7920
|
+
args: [{ selector: 'cui-category-item', imports: [
|
|
7921
|
+
CuiButtonModule,
|
|
7922
|
+
CuiIconButtonModule,
|
|
7923
|
+
CuiLetDirective,
|
|
7924
|
+
CuiSvgModule,
|
|
7925
|
+
CuiCategoryFormComponent,
|
|
7926
|
+
CuiCreateCategoryItemComponent,
|
|
7927
|
+
forwardRef(() => CuiCategoriesListComponent)
|
|
7928
|
+
], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *cuiLet=\"category() as stage\">\r\n <button\r\n type=\"button\"\r\n [style.align-items]=\"alignItems()\"\r\n [disabled]=\"isStageCreationLoading()\"\r\n class=\"category\"\r\n (click)=\"onSelectCategory()\"\r\n >\r\n <button\r\n type=\"button\"\r\n ccFlexContainerDirective\r\n class=\"category__open-close-button\"\r\n [class.category__open-close-button_hidden]=\"isOpenCloseButtonHidden()\"\r\n (click)=\"onToggleChildren($event)\"\r\n >\r\n <cui-svg\r\n [icon]=\"openCloseButtonIcon()\"\r\n color=\"var(--cui-base-500)\"\r\n />\r\n </button>\r\n <cui-svg\r\n [icon]=\"stageStorageIcon()\"\r\n color=\"var(--cui-base-500)\"\r\n class=\"icon\"\r\n />\r\n @if (isTitleEdit()) {\r\n <cui-category-form\r\n [defaultTitle]=\"stage.title\"\r\n (created)=\"onTitleChanged($event)\"\r\n (canceled)=\"onCancelTitleEdit()\"\r\n />\r\n } @else {\r\n <span class=\"category__title\">{{ stage.title }}</span>\r\n\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconEdit\"\r\n class=\"category__add-subcategory-button\"\r\n (click)=\"onStartTitleEdit($event)\"\r\n ></button>\r\n <button\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconPlus\"\r\n class=\"category__add-subcategory-button\"\r\n (click)=\"onStartCreatingSubcategory($event)\"\r\n ></button>\r\n }\r\n </button>\r\n <div\r\n [hidden]=\"!areChildrenOpened()\"\r\n class=\"list-wrapper\"\r\n >\r\n <cui-categories-list [stageStorages]=\"stageStorageChildren()\" />\r\n @if (isCreateCategoryControlVisible()) {\r\n <cui-create-category-item\r\n class=\"create-category\"\r\n [isDisabled]=\"isSubcategoryCreationLoading()\"\r\n (created)=\"onCreateNewSubcategoryCategory($event)\"\r\n (canceled)=\"onCreatingSubcategoryCanceled()\"\r\n />\r\n }\r\n </div>\r\n</ng-container>\r\n", styles: [".category{display:flex;gap:4px;padding:2px 4px;width:100%;min-height:32px;border-radius:8px}@media (hover: hover){.category:hover{background:var(--cui-base-10)}}.category:active{background:var(--cui-base-10)}.category__open-close-button{padding:2px;border-radius:4px;margin:4px 0}@media (hover: hover){.category__open-close-button:hover{background:var(--cui-base-100)}}.category__open-close-button:active{background:var(--cui-base-100)}.category__open-close-button_hidden{visibility:hidden}.category__title{flex:1;text-align:start;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.category__add-subcategory-button{--cui-base-50: var(--cui-base-200)}.list-wrapper{padding-left:8px}.create-category{margin-left:24px}.icon{padding-right:2px;padding-left:2px;height:28px}\n"] }]
|
|
7929
|
+
}], ctorParameters: () => [] });
|
|
7930
|
+
|
|
7931
|
+
class CuiCategoriesListComponent {
|
|
7932
|
+
constructor() {
|
|
7933
|
+
this.stageStorages = input.required();
|
|
7934
|
+
}
|
|
7935
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiCategoriesListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7936
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CuiCategoriesListComponent, isStandalone: true, selector: "cui-categories-list", inputs: { stageStorages: { classPropertyName: "stageStorages", publicName: "stageStorages", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@for (stageStorage of stageStorages(); track stageStorage.id) {\r\n <cui-category-item [stageStorage]=\"stageStorage\" />\r\n}\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: i0.forwardRef(() => CuiIconButtonModule) }, { kind: "ngmodule", type: i0.forwardRef(() => CuiSvgModule) }, { kind: "component", type: i0.forwardRef(() => CuiCategoryItemComponent), selector: "cui-category-item", inputs: ["stageStorage"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7937
|
+
}
|
|
7938
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiCategoriesListComponent, decorators: [{
|
|
7939
|
+
type: Component,
|
|
7940
|
+
args: [{ selector: 'cui-categories-list', imports: [CuiIconButtonModule, CuiSvgModule, forwardRef(() => CuiCategoryItemComponent)], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "@for (stageStorage of stageStorages(); track stageStorage.id) {\r\n <cui-category-item [stageStorage]=\"stageStorage\" />\r\n}\r\n", styles: [":host{display:block}\n"] }]
|
|
7941
|
+
}] });
|
|
7942
|
+
|
|
7943
|
+
class CuiCategoriesComponent {
|
|
7944
|
+
constructor() {
|
|
7945
|
+
this.treeStructNavigatorApiService = inject(CuiTreeStructNavigatorApiService);
|
|
7946
|
+
this.selectedCategoryService = inject(CuiSelectedCategoryService);
|
|
7947
|
+
this.stageStorages = signal(null);
|
|
7948
|
+
this.isCategoryCreating = signal(false);
|
|
7949
|
+
this.isCategoryCreationLoading = signal(false);
|
|
7950
|
+
this.isCreateCategoryControlVisible = computed(() => (this.selectedCategoryService.creatingId() === this.treeStructType() && this.isCategoryCreating()) ||
|
|
7951
|
+
this.isCategoryCreationLoading());
|
|
7952
|
+
this.dropdown = viewChild.required('dropdown');
|
|
7953
|
+
this.treeStructType = input.required();
|
|
7954
|
+
this.buttonId = input();
|
|
7955
|
+
this.disabled = input(false, { transform: booleanAttribute });
|
|
7956
|
+
this.initSelectCategoryEffect();
|
|
7957
|
+
}
|
|
7958
|
+
onOpenStageStorages() {
|
|
7959
|
+
this.selectedCategoryService.clearCreatingId();
|
|
7960
|
+
this.selectedCategoryService.clearEditingId();
|
|
7961
|
+
if (this.stageStorages()?.length) {
|
|
7962
|
+
return;
|
|
7963
|
+
}
|
|
7964
|
+
this.treeStructNavigatorApiService.getStageStorages(this.treeStructType()).subscribe((stageStorage) => {
|
|
7965
|
+
this.stageStorages.update((prevStageStorages) => prevStageStorages ? [...prevStageStorages, stageStorage] : [stageStorage]);
|
|
7966
|
+
});
|
|
7967
|
+
}
|
|
7968
|
+
onStartCreatingNewCategory() {
|
|
7969
|
+
this.isCategoryCreating.set(true);
|
|
7970
|
+
this.selectedCategoryService.setCreatingId(this.treeStructType());
|
|
7971
|
+
}
|
|
7972
|
+
onCreateNewCategory(title) {
|
|
7973
|
+
this.isCategoryCreating.set(false);
|
|
7974
|
+
this.selectedCategoryService.clearCreatingId();
|
|
7975
|
+
this.isCategoryCreationLoading.set(true);
|
|
7976
|
+
this.treeStructNavigatorApiService
|
|
7977
|
+
.createStageStorage(title, this.treeStructType())
|
|
7978
|
+
.pipe(finalize(this.isCategoryCreationLoading.set.bind(this, false)))
|
|
7979
|
+
.subscribe((stateStorage) => this.stageStorages.update((value) => [...(value || []), stateStorage]));
|
|
7980
|
+
}
|
|
7981
|
+
onCreatingCategoryCanceled() {
|
|
7982
|
+
this.isCategoryCreating.set(false);
|
|
7983
|
+
this.selectedCategoryService.clearCreatingId();
|
|
7984
|
+
}
|
|
7985
|
+
initSelectCategoryEffect() {
|
|
7986
|
+
effect(() => {
|
|
7987
|
+
this.selectedCategoryService.category();
|
|
7988
|
+
this.dropdown().close();
|
|
7989
|
+
}, { allowSignalWrites: true });
|
|
7990
|
+
}
|
|
7991
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiCategoriesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7992
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: CuiCategoriesComponent, isStandalone: true, selector: "cui-categories", inputs: { treeStructType: { classPropertyName: "treeStructType", publicName: "treeStructType", isSignal: true, isRequired: true, transformFunction: null }, buttonId: { classPropertyName: "buttonId", publicName: "buttonId", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true, isSignal: true }], ngImport: i0, template: "<button\r\n [attr.id]=\"buttonId()\"\r\n #dropdown=\"cuiDropdown\"\r\n [cuiDropdown]=\"dropdownContent\"\r\n orientation=\"stretch\"\r\n type=\"button\"\r\n class=\"target\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"onOpenStageStorages()\"\r\n>\r\n <ng-content />\r\n</button>\r\n\r\n<ng-template #dropdownContent>\r\n <cui-dropdown-wrapper\r\n *transloco=\"let t\"\r\n [title]=\"t('SELECT_OR_CREATE_CATEGORY')\"\r\n width=\"100%\"\r\n class=\"dropdown-wrapper\"\r\n >\r\n <ng-container *cuiLet=\"stageStorages() as stageStorages\">\r\n @if (stageStorages && stageStorages?.length) {\r\n <cui-categories-list [stageStorages]=\"stageStorages\" />\r\n }\r\n @if (isCreateCategoryControlVisible()) {\r\n <cui-create-category-item\r\n class=\"create-category\"\r\n [isDisabled]=\"isCategoryCreationLoading()\"\r\n (created)=\"onCreateNewCategory($event)\"\r\n (canceled)=\"onCreatingCategoryCanceled()\"\r\n />\r\n } @else if (!stageStorages?.length) {\r\n <cui-empty-state\r\n class=\"empty\"\r\n [subtitle]=\"t('NO_CATEGORY_TO_VIEW_YET')\"\r\n />\r\n }\r\n </ng-container>\r\n <button\r\n ccDropdownFooterContent\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconPlus\"\r\n (click)=\"onStartCreatingNewCategory()\"\r\n >\r\n {{ t('NEW_CATEGORY') }}\r\n </button>\r\n </cui-dropdown-wrapper>\r\n</ng-template>\r\n", styles: ["::ng-deep .dropdown-wrapper .scrollable-content{flex:1;display:flex;flex-direction:column}.target{display:block;padding:0;width:100%;border-radius:8px;border:1px solid transparent}.target:focus{box-shadow:0 0 0 2px var(--cui-focus);border:1px solid var(--cui-info)}.target:disabled{cursor:default}.create-category{margin-left:24px}.empty{margin:auto}.dropdown-wrapper{display:block;height:350px}\n"], dependencies: [{ kind: "ngmodule", type: CuiButtonModule }, { kind: "component", type: CuiButtonComponent, selector: "button[cuiButton], a[cuiButton]", inputs: ["shape", "disabled", "isLoaderShown", "icon", "iconRight", "appearance", "size"] }, { kind: "directive", type: CuiLetDirective, selector: "[cuiLet]", inputs: ["cuiLet"] }, { kind: "directive", type: CuiDropdownDirective, selector: "[cuiDropdown]", inputs: ["cuiDropdown", "orientation"], outputs: ["isOpened"], exportAs: ["cuiDropdown"] }, { kind: "component", type: CuiDropdownWrapperComponent, selector: "cui-dropdown-wrapper", inputs: ["title", "width"] }, { kind: "component", type: CuiEmptyStateComponent, selector: "cui-empty-state, [cuiEmptyState]", inputs: ["title", "subtitle"] }, { kind: "component", type: CuiCreateCategoryItemComponent, selector: "cui-create-category-item", inputs: ["isDisabled"], outputs: ["created", "canceled"] }, { kind: "component", type: CuiCategoriesListComponent, selector: "cui-categories-list", inputs: ["stageStorages"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7993
|
+
}
|
|
7994
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CuiCategoriesComponent, decorators: [{
|
|
7995
|
+
type: Component,
|
|
7996
|
+
args: [{ selector: 'cui-categories', imports: [
|
|
7997
|
+
CuiButtonModule,
|
|
7998
|
+
CuiLetDirective,
|
|
7999
|
+
CuiDropdownDirective,
|
|
8000
|
+
CuiDropdownWrapperComponent,
|
|
8001
|
+
CuiEmptyStateComponent,
|
|
8002
|
+
CuiCreateCategoryItemComponent,
|
|
8003
|
+
CuiCategoriesListComponent,
|
|
8004
|
+
TranslocoDirective
|
|
8005
|
+
], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\r\n [attr.id]=\"buttonId()\"\r\n #dropdown=\"cuiDropdown\"\r\n [cuiDropdown]=\"dropdownContent\"\r\n orientation=\"stretch\"\r\n type=\"button\"\r\n class=\"target\"\r\n [disabled]=\"disabled()\"\r\n (click)=\"onOpenStageStorages()\"\r\n>\r\n <ng-content />\r\n</button>\r\n\r\n<ng-template #dropdownContent>\r\n <cui-dropdown-wrapper\r\n *transloco=\"let t\"\r\n [title]=\"t('SELECT_OR_CREATE_CATEGORY')\"\r\n width=\"100%\"\r\n class=\"dropdown-wrapper\"\r\n >\r\n <ng-container *cuiLet=\"stageStorages() as stageStorages\">\r\n @if (stageStorages && stageStorages?.length) {\r\n <cui-categories-list [stageStorages]=\"stageStorages\" />\r\n }\r\n @if (isCreateCategoryControlVisible()) {\r\n <cui-create-category-item\r\n class=\"create-category\"\r\n [isDisabled]=\"isCategoryCreationLoading()\"\r\n (created)=\"onCreateNewCategory($event)\"\r\n (canceled)=\"onCreatingCategoryCanceled()\"\r\n />\r\n } @else if (!stageStorages?.length) {\r\n <cui-empty-state\r\n class=\"empty\"\r\n [subtitle]=\"t('NO_CATEGORY_TO_VIEW_YET')\"\r\n />\r\n }\r\n </ng-container>\r\n <button\r\n ccDropdownFooterContent\r\n cuiButton\r\n type=\"button\"\r\n appearance=\"ghost\"\r\n size=\"xxs\"\r\n icon=\"cuiIconPlus\"\r\n (click)=\"onStartCreatingNewCategory()\"\r\n >\r\n {{ t('NEW_CATEGORY') }}\r\n </button>\r\n </cui-dropdown-wrapper>\r\n</ng-template>\r\n", styles: ["::ng-deep .dropdown-wrapper .scrollable-content{flex:1;display:flex;flex-direction:column}.target{display:block;padding:0;width:100%;border-radius:8px;border:1px solid transparent}.target:focus{box-shadow:0 0 0 2px var(--cui-focus);border:1px solid var(--cui-info)}.target:disabled{cursor:default}.create-category{margin-left:24px}.empty{margin:auto}.dropdown-wrapper{display:block;height:350px}\n"] }]
|
|
8006
|
+
}], ctorParameters: () => [] });
|
|
4005
8007
|
|
|
4006
8008
|
/**
|
|
4007
8009
|
* Generated bundle index. Do not edit.
|
|
4008
8010
|
*/
|
|
4009
8011
|
|
|
4010
|
-
export { AngularOutsideLoaderService, CUI_ALERTS, CUI_ALERT_CONTEXT, CUI_ALERT_DEFAULT_OPTIONS, CUI_ALERT_OPTIONS, CUI_ANIMATIONS_DEFAULT_DURATION, CUI_BANNER_DEFAULT_OPTIONS, CUI_BANNER_OPTIONS, CUI_BUTTON_DEFAULT_OPTIONS, CUI_BUTTON_OPTIONS, CUI_DEFAULT_THEME, CUI_DIALOGS, CUI_DIALOG_CONTEXT, CUI_DIALOG_DEFAULT_OPTIONS, CUI_DIALOG_OPTIONS, CUI_INPUT_TIME_DEFAULT_OPTIONS, CUI_INPUT_TIME_OPTIONS, CUI_NOTIFICATION_DEFAULT_OPTIONS, CUI_NOTIFICATION_ICONS, CUI_NOTIFICATION_ICON_OPTIONS, CUI_NOTIFICATION_ICON_OPTIONS_DEFAULT_MODE, CUI_NOTIFICATION_ICON_OPTIONS_LIGHT_MODE, CUI_NOTIFICATION_OPTIONS, CUI_ROOT_SELECTOR, CUI_TAB_ACTIVATE, CUI_TEXT_FIELD_CONTROLLER, CUI_TEXT_FIELD_ICON_LEFT, CUI_TEXT_FIELD_ID, CUI_TEXT_FIELD_IS_ERROR, CUI_TEXT_FIELD_PLACEHOLDER, CUI_TEXT_FIELD_SIZE, CUI_TEXT_FILED_CONTROLLER_PROVIDER, CUI_THEME, CUI_THEME_STORAGE_DEFAULT_KEY, CUI_THEME_STORAGE_KEY, CUI_TOOLTIP_COMPONENT, CUI_TOOLTIP_DEFAULT_OPTIONS, CUI_TOOLTIP_DIRECTIONS, CUI_TOOLTIP_OPTIONS, CUI_TOOLTIP_PROVIDERS, CuiAccordionComponent, CuiAccordionDirective, CuiAccordionItemComponent, CuiAccordionModule, CuiAlertComponent, CuiAlertModule, CuiAlertService, CuiAlertsComponent, CuiBadgeComponent, CuiBadgeModule, CuiBannerComponent, CuiBannerModule, CuiBreadcrumbComponent, CuiBreadcrumbsComponent, CuiBreadcrumbsModule, CuiButtonComponent, CuiButtonGroupComponent, CuiButtonGroupModule, CuiButtonModule, CuiCardWrapperComponent, CuiCheckboxComponent, CuiCheckboxModule, CuiContextMenuComponent, CuiContextMenuModule, CuiDialogActionsComponent, CuiDialogComponent, CuiDialogHeaderComponent, CuiDialogModule, CuiDialogService, CuiDialogsComponent, CuiDropdownDirective, CuiDropdownWrapperComponent, CuiFormFieldComponent, CuiFormFieldModule, CuiHintComponent, CuiHintModule, CuiIconButtonComponent, CuiIconButtonModule, CuiInputModule, CuiInputNumberComponent, CuiInputNumberModule, CuiInputPasswordComponent, CuiInputPasswordModule, CuiInputTextComponent, CuiInputTimeComponent, CuiInputTimeModule, CuiLabelComponent, CuiLabelModule, CuiLayoutComponent, CuiLetterBoxComponent, CuiNotificationComponent, CuiNotificationModule, CuiPositionService, CuiRadioComponent, CuiRadioModule, CuiRenderDynamicComponentsComponent, CuiRenderDynamicComponentsService, CuiRootComponent, CuiRootModule, CuiSelectComponent, CuiSelectModule, CuiSidebarContainerComponent, CuiSidebarHeaderComponent, CuiSidebarNavigationComponent, CuiSidebarNavigationContainerComponent, CuiSidebarNavigationItemComponent, CuiSidebarService, CuiSvgComponent, CuiSvgModule, CuiTabComponent, CuiTabsComponent, CuiTabsModule, CuiTextFieldController, CuiTextFieldControllerModule, CuiTextFieldIconLeftDirective, CuiTextFieldIdDirective, CuiTextFieldIsErrorDirective, CuiTextFieldPlaceholderDirective, CuiTextFieldSizeDirective, CuiTextareaComponent, CuiTextareaModule, CuiThemeService, CuiToggleComponent, CuiToggleModule, CuiTooltip, CuiTooltipComponent, CuiTooltipDescribe, CuiTooltipDirective, CuiTooltipDriver, CuiTooltipHost, CuiTooltipHover, CuiTooltipManual, CuiTooltipOptionsDirective, CuiTooltipOverflow, CuiTooltipPointer, CuiTooltipPosition, CuiTooltipService, CuiTooltipUnstyled, CuiTooltipUnstyledComponent, CuiTooltips,
|
|
8012
|
+
export { AngularOutsideLoaderService, CUI_ALERTS, CUI_ALERT_CONTEXT, CUI_ALERT_DEFAULT_OPTIONS, CUI_ALERT_OPTIONS, CUI_ANIMATIONS_DEFAULT_DURATION, CUI_BANNER_DEFAULT_OPTIONS, CUI_BANNER_OPTIONS, CUI_BUTTON_DEFAULT_OPTIONS, CUI_BUTTON_OPTIONS, CUI_DEFAULT_THEME, CUI_DIALOGS, CUI_DIALOG_CONTEXT, CUI_DIALOG_DEFAULT_OPTIONS, CUI_DIALOG_OPTIONS, CUI_INPUT_TIME_DEFAULT_OPTIONS, CUI_INPUT_TIME_OPTIONS, CUI_NOTIFICATION_DEFAULT_OPTIONS, CUI_NOTIFICATION_ICONS, CUI_NOTIFICATION_ICON_OPTIONS, CUI_NOTIFICATION_ICON_OPTIONS_DEFAULT_MODE, CUI_NOTIFICATION_ICON_OPTIONS_LIGHT_MODE, CUI_NOTIFICATION_OPTIONS, CUI_ROOT_SELECTOR, CUI_TAB_ACTIVATE, CUI_TEXT_FIELD_CONTROLLER, CUI_TEXT_FIELD_ICON_LEFT, CUI_TEXT_FIELD_ID, CUI_TEXT_FIELD_IS_ERROR, CUI_TEXT_FIELD_PLACEHOLDER, CUI_TEXT_FIELD_SIZE, CUI_TEXT_FILED_CONTROLLER_PROVIDER, CUI_THEME, CUI_THEME_STORAGE_DEFAULT_KEY, CUI_THEME_STORAGE_KEY, CUI_TOOLTIP_COMPONENT, CUI_TOOLTIP_DEFAULT_OPTIONS, CUI_TOOLTIP_DIRECTIONS, CUI_TOOLTIP_OPTIONS, CUI_TOOLTIP_PROVIDERS, CuiAccordionComponent, CuiAccordionDirective, CuiAccordionItemComponent, CuiAccordionModule, CuiAlertComponent, CuiAlertModule, CuiAlertService, CuiAlertsComponent, CuiAttachesTool, CuiBadgeComponent, CuiBadgeModule, CuiBannerComponent, CuiBannerModule, CuiBreadcrumbComponent, CuiBreadcrumbsComponent, CuiBreadcrumbsModule, CuiButtonComponent, CuiButtonGroupComponent, CuiButtonGroupModule, CuiButtonModule, CuiCardWrapperComponent, CuiCategoriesComponent, CuiCheckboxComponent, CuiCheckboxModule, CuiContentWrapperComponent, CuiContextMenuComponent, CuiContextMenuModule, CuiDialogActionsComponent, CuiDialogComponent, CuiDialogHeaderComponent, CuiDialogModule, CuiDialogService, CuiDialogsComponent, CuiDropdownDirective, CuiDropdownWrapperComponent, CuiEditorBlockComponent, CuiEditorComponent, CuiEditorModalComponent, CuiEditorReadonlyComponent, CuiEditorTranslations, CuiEmptyStateComponent, CuiFileUploaderStatus, CuiFormFieldComponent, CuiFormFieldModule, CuiGhostInputComponent, CuiHeaderTool, CuiHintComponent, CuiHintModule, CuiIconButtonComponent, CuiIconButtonModule, CuiImageTool, CuiInputModule, CuiInputNumberComponent, CuiInputNumberModule, CuiInputPasswordComponent, CuiInputPasswordModule, CuiInputTextComponent, CuiInputTimeComponent, CuiInputTimeModule, CuiLabelComponent, CuiLabelModule, CuiLayoutComponent, CuiLetterBoxComponent, CuiLinkMarker, CuiListTool, CuiLoaderService, CuiLoadingState, CuiNotificationComponent, CuiNotificationModule, CuiPositionService, CuiRadioComponent, CuiRadioModule, CuiRenderDynamicComponentsComponent, CuiRenderDynamicComponentsService, CuiRoleMarker, CuiRootComponent, CuiRootModule, CuiSelectComponent, CuiSelectModule, CuiSelectedCategoryService, CuiSidebarContainerComponent, CuiSidebarHeaderComponent, CuiSidebarNavigationComponent, CuiSidebarNavigationContainerComponent, CuiSidebarNavigationItemComponent, CuiSidebarService, CuiSvgComponent, CuiSvgModule, CuiTabComponent, CuiTabsComponent, CuiTabsModule, CuiTextFieldController, CuiTextFieldControllerModule, CuiTextFieldIconLeftDirective, CuiTextFieldIdDirective, CuiTextFieldIsErrorDirective, CuiTextFieldPlaceholderDirective, CuiTextFieldSizeDirective, CuiTextareaComponent, CuiTextareaModule, CuiThemeService, CuiToggleComponent, CuiToggleModule, CuiToolMarker, CuiTooltip, CuiTooltipComponent, CuiTooltipDescribe, CuiTooltipDirective, CuiTooltipDriver, CuiTooltipHost, CuiTooltipHover, CuiTooltipManual, CuiTooltipOptionsDirective, CuiTooltipOverflow, CuiTooltipPointer, CuiTooltipPosition, CuiTooltipService, CuiTooltipUnstyled, CuiTooltipUnstyledComponent, CuiTooltips, CuiUtilityInfoComponent, CuiVideoTool, CuiVisualViewportService, createDefaultValidators, cuiGetDuration, cuiIsObscured, cuiLoaderInterceptor, cuiOverrideOptions, cuiProvideEditor, cuiRemoveSpaces, cuiReplace, cuiToAnimationOptions, cuiTooltipOptionsProvider, cuiXNdjsonInterceptor };
|
|
4011
8013
|
//# sourceMappingURL=cuby-ui-core.mjs.map
|