@seniorsistemas/angular-components 19.5.5 → 19.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/accordion/README.md +95 -59
- package/calendar-mask/lib/calendar-mask/calendar-mask.directive.d.ts +4 -0
- package/datepicker/README.md +175 -0
- package/datepicker/index.d.ts +5 -0
- package/datepicker/lib/datepicker/date.utils.d.ts +21 -0
- package/datepicker/lib/datepicker/datepicker.component.d.ts +254 -0
- package/datepicker/lib/datepicker/models/index.d.ts +16 -0
- package/datepicker/public-api.d.ts +2 -0
- package/dynamic-form/dynamic-form/components/lookup/lookup.component.d.ts +3 -1
- package/dynamic-form/dynamic-form/components/lookup/models/lookup-alert-config.d.ts +5 -0
- package/dynamic-form/dynamic-form/form-field/configurations/fields/calendar-field.d.ts +119 -24
- package/dynamic-form/dynamic-form/form-field/configurations/fields/lookup-field.d.ts +6 -0
- package/dynamic-form/dynamic-form/form-field/fields/calendar/calendar-field.component.d.ts +6 -23
- package/dynamic-form/public-api.d.ts +1 -0
- package/editor/README.md +229 -0
- package/editor/index.d.ts +5 -0
- package/editor/lib/editor/editor.component.d.ts +127 -0
- package/editor/lib/editor/link-dialog/link-dialog.component.d.ts +18 -0
- package/editor/lib/editor/models/index.d.ts +12 -0
- package/editor/lib/editor/toolbar-button/editor-toolbar-button.component.d.ts +10 -0
- package/editor/public-api.d.ts +2 -0
- package/esm2022/calendar-mask/lib/calendar-mask/calendar-mask.directive.mjs +5 -1
- package/esm2022/datepicker/lib/datepicker/date.utils.mjs +182 -0
- package/esm2022/datepicker/lib/datepicker/datepicker.component.mjs +1062 -0
- package/esm2022/datepicker/lib/datepicker/models/index.mjs +2 -0
- package/esm2022/datepicker/public-api.mjs +2 -0
- package/esm2022/datepicker/seniorsistemas-angular-components-datepicker.mjs +5 -0
- package/esm2022/dynamic-form/dynamic-form/components/lookup/lookup.component.mjs +11 -5
- package/esm2022/dynamic-form/dynamic-form/components/lookup/models/lookup-alert-config.mjs +2 -0
- package/esm2022/dynamic-form/dynamic-form/form-field/configurations/fields/calendar-field.mjs +1 -1
- package/esm2022/dynamic-form/dynamic-form/form-field/configurations/fields/lookup-field.mjs +1 -1
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/autocomplete/autocomplete-field.component.mjs +2 -2
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/calendar/calendar-field.component.mjs +23 -116
- package/esm2022/dynamic-form/dynamic-form/form-field/fields/lookup/lookup-field.component.mjs +3 -3
- package/esm2022/dynamic-form/public-api.mjs +1 -1
- package/esm2022/editor/lib/editor/editor.component.mjs +375 -0
- package/esm2022/editor/lib/editor/link-dialog/link-dialog.component.mjs +48 -0
- package/esm2022/editor/lib/editor/models/index.mjs +3 -0
- package/esm2022/editor/lib/editor/toolbar-button/editor-toolbar-button.component.mjs +17 -0
- package/esm2022/editor/public-api.mjs +3 -0
- package/esm2022/editor/seniorsistemas-angular-components-editor.mjs +5 -0
- package/esm2022/inline-edit/lib/inline-edit/components/fields/inline-edit-calendar/inline-edit-calendar.component.mjs +22 -12
- package/esm2022/inline-edit/lib/inline-edit/inline-edit.module.mjs +5 -5
- package/esm2022/lib/locale/fallback.mjs +82 -3
- package/esm2022/optional-fields/editor/editor-field/editor-field.component.mjs +5 -6
- package/esm2022/optional-fields/editor/editor-field.mjs +1 -1
- package/esm2022/panel/lib/panel/panel.component.mjs +7 -3
- package/esm2022/select/lib/select/select.component.mjs +4 -8
- package/esm2022/shared/lib/accessibility/datepicker-no-period-tab.directive.mjs +5 -1
- package/fesm2022/seniorsistemas-angular-components-calendar-mask.mjs +4 -0
- package/fesm2022/seniorsistemas-angular-components-calendar-mask.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-datepicker.mjs +1250 -0
- package/fesm2022/seniorsistemas-angular-components-datepicker.mjs.map +1 -0
- package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs +49 -135
- package/fesm2022/seniorsistemas-angular-components-dynamic-form.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-editor.mjs +437 -0
- package/fesm2022/seniorsistemas-angular-components-editor.mjs.map +1 -0
- package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs +24 -15
- package/fesm2022/seniorsistemas-angular-components-inline-edit.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-optional-fields-editor.mjs +4 -5
- package/fesm2022/seniorsistemas-angular-components-optional-fields-editor.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-panel.mjs +6 -2
- package/fesm2022/seniorsistemas-angular-components-panel.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-select.mjs +3 -7
- package/fesm2022/seniorsistemas-angular-components-select.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components-shared.mjs +4 -0
- package/fesm2022/seniorsistemas-angular-components-shared.mjs.map +1 -1
- package/fesm2022/seniorsistemas-angular-components.mjs +81 -2
- package/fesm2022/seniorsistemas-angular-components.mjs.map +1 -1
- package/inline-edit/lib/inline-edit/components/fields/inline-edit-calendar/inline-edit-calendar.component.d.ts +6 -4
- package/inline-edit/lib/inline-edit/inline-edit.module.d.ts +2 -2
- package/loading-state/README.md +57 -17
- package/optional-fields/editor/editor-field.d.ts +9 -6
- package/package.json +74 -8
- package/panel/README.md +12 -1
- package/panel/lib/panel/panel.component.d.ts +3 -1
- package/schematics/collection.json +4 -0
- package/schematics/migrations/migrate-p-datepicker/index.d.ts +2 -0
- package/schematics/migrations/migrate-p-datepicker/index.js +141 -0
- package/schematics/migrations/migrate-p-datepicker/index.js.map +1 -0
- package/schematics/migrations/migrate-p-datepicker/index.test.d.ts +1 -0
- package/schematics/migrations/migrate-p-datepicker/index.test.js +392 -0
- package/schematics/migrations/migrate-p-datepicker/index.test.js.map +1 -0
- package/schematics/migrations.json +10 -0
- package/schematics/utils/ast-utils.d.ts +28 -0
- package/schematics/utils/ast-utils.js +116 -0
- package/schematics/utils/ast-utils.js.map +1 -0
- package/schematics/utils/ast-utils.test.d.ts +1 -0
- package/schematics/utils/ast-utils.test.js +138 -0
- package/schematics/utils/ast-utils.test.js.map +1 -0
- package/schematics/utils/workspace-utils.d.ts +6 -0
- package/schematics/utils/workspace-utils.js +37 -0
- package/schematics/utils/workspace-utils.js.map +1 -0
- package/schematics/utils/workspace-utils.test.d.ts +1 -0
- package/schematics/utils/workspace-utils.test.js +152 -0
- package/schematics/utils/workspace-utils.test.js.map +1 -0
- package/shared/lib/accessibility/datepicker-no-period-tab.directive.d.ts +4 -0
- package/stats-card/README.md +80 -45
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
import { NgClass, NgStyle } from '@angular/common';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { inject, Component, input, output, ChangeDetectionStrategy, ChangeDetectorRef, DestroyRef, viewChild, effect, forwardRef } from '@angular/core';
|
|
4
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
|
+
import { FormGroup, FormControl, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
6
|
+
import { take } from 'rxjs/operators';
|
|
7
|
+
import * as i1 from '@ngx-translate/core';
|
|
8
|
+
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
|
9
|
+
import { ActiveDialog, DialogComponent, DialogService } from '@seniorsistemas/angular-components/dialog';
|
|
10
|
+
import { Editor } from '@tiptap/core';
|
|
11
|
+
export { Extension } from '@tiptap/core';
|
|
12
|
+
import { Color } from '@tiptap/extension-color';
|
|
13
|
+
import Highlight from '@tiptap/extension-highlight';
|
|
14
|
+
import Image from '@tiptap/extension-image';
|
|
15
|
+
import Placeholder from '@tiptap/extension-placeholder';
|
|
16
|
+
import Subscript from '@tiptap/extension-subscript';
|
|
17
|
+
import Superscript from '@tiptap/extension-superscript';
|
|
18
|
+
import TextAlign from '@tiptap/extension-text-align';
|
|
19
|
+
import { TextStyle } from '@tiptap/extension-text-style';
|
|
20
|
+
import Underline from '@tiptap/extension-underline';
|
|
21
|
+
import StarterKit from '@tiptap/starter-kit';
|
|
22
|
+
import * as i3 from '@seniorsistemas/angular-components/button';
|
|
23
|
+
import { ButtonModule } from '@seniorsistemas/angular-components/button';
|
|
24
|
+
import * as i2 from '@seniorsistemas/angular-components/dynamic-form';
|
|
25
|
+
import { DynamicFormModule } from '@seniorsistemas/angular-components/dynamic-form';
|
|
26
|
+
import * as i4 from '@seniorsistemas/angular-components/template';
|
|
27
|
+
import { TemplateModule } from '@seniorsistemas/angular-components/template';
|
|
28
|
+
|
|
29
|
+
class LinkDialogComponent {
|
|
30
|
+
activeDialog = inject(ActiveDialog);
|
|
31
|
+
translateService = inject(TranslateService);
|
|
32
|
+
initialUrl = '';
|
|
33
|
+
form = new FormGroup({ url: new FormControl('') });
|
|
34
|
+
configs = [];
|
|
35
|
+
ngOnInit() {
|
|
36
|
+
this.form.setValue({ url: this.initialUrl });
|
|
37
|
+
this.configs = [
|
|
38
|
+
{
|
|
39
|
+
type: 'row',
|
|
40
|
+
fields: [
|
|
41
|
+
{
|
|
42
|
+
type: 'string',
|
|
43
|
+
name: 'url',
|
|
44
|
+
label: this.translateService.instant('platform.angular_components.editor_link_url_label'),
|
|
45
|
+
placeholder: this.translateService.instant('platform.angular_components.editor_link_url_placeholder'),
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
confirm() {
|
|
52
|
+
this.activeDialog.close(this.form.value.url?.trim() ?? '');
|
|
53
|
+
}
|
|
54
|
+
cancel() {
|
|
55
|
+
this.activeDialog.dismiss();
|
|
56
|
+
}
|
|
57
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LinkDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
58
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: LinkDialogComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<s-dialog [header]=\"'platform.angular_components.editor_insert_link' | translate\">\n <ng-template sTemplate=\"body\">\n <s-dynamic-form [form]=\"form\" [configs]=\"configs\" />\n </ng-template>\n <ng-template sTemplate=\"footer\">\n <div style=\"display:flex; justify-content:flex-end; gap:8px; width:100%\">\n <s-button\n [label]=\"'platform.angular_components.cancel' | translate\"\n priority=\"secondary\"\n (clicked)=\"cancel()\"\n />\n <s-button\n [label]=\"'platform.angular_components.editor_confirm' | translate\"\n priority=\"primary\"\n (clicked)=\"confirm()\"\n />\n </div>\n </ng-template>\n</s-dialog>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "component", type: DialogComponent, selector: "s-dialog", inputs: ["header", "visible", "size", "contentClassName", "escapeOnEsc", "destroyClickOutside", "closeAriaLabel"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: DynamicFormModule }, { kind: "component", type: i2.DynamicFormComponent, selector: "s-dynamic-form", inputs: ["id", "configs", "fields", "form", "errorMessages"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i3.ButtonComponent, selector: "s-button", inputs: ["id", "label", "tooltip", "tooltipPosition", "iconClass", "rightIconClass", "caret", "styleClass", "baseZIndex", "disabled", "auxiliary", "type", "priority", "menuOptions", "size", "slide", "animation", "badge", "iconColor", "menuAriaLabel", "ariaLabel"], outputs: ["clicked"] }, { kind: "ngmodule", type: TemplateModule }, { kind: "directive", type: i4.TemplateDirective, selector: "[sTemplate]", inputs: ["sTemplate"] }] });
|
|
59
|
+
}
|
|
60
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LinkDialogComponent, decorators: [{
|
|
61
|
+
type: Component,
|
|
62
|
+
args: [{ standalone: true, imports: [ReactiveFormsModule, TranslateModule, DialogComponent, DynamicFormModule, ButtonModule, TemplateModule], template: "<s-dialog [header]=\"'platform.angular_components.editor_insert_link' | translate\">\n <ng-template sTemplate=\"body\">\n <s-dynamic-form [form]=\"form\" [configs]=\"configs\" />\n </ng-template>\n <ng-template sTemplate=\"footer\">\n <div style=\"display:flex; justify-content:flex-end; gap:8px; width:100%\">\n <s-button\n [label]=\"'platform.angular_components.cancel' | translate\"\n priority=\"secondary\"\n (clicked)=\"cancel()\"\n />\n <s-button\n [label]=\"'platform.angular_components.editor_confirm' | translate\"\n priority=\"primary\"\n (clicked)=\"confirm()\"\n />\n </div>\n </ng-template>\n</s-dialog>\n" }]
|
|
63
|
+
}] });
|
|
64
|
+
|
|
65
|
+
class EditorToolbarButtonComponent {
|
|
66
|
+
icon = input.required();
|
|
67
|
+
label = input.required();
|
|
68
|
+
active = input(false);
|
|
69
|
+
disabled = input(false);
|
|
70
|
+
clicked = output();
|
|
71
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EditorToolbarButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
72
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.14", type: EditorToolbarButtonComponent, isStandalone: true, selector: "s-editor-toolbar-button", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, host: { styleAttribute: "display: contents" }, ngImport: i0, template: "<button\n type=\"button\"\n class=\"inline-flex items-center justify-center w-7 h-7 p-0 border-0 bg-transparent rounded cursor-pointer text-base leading-none transition-colors duration-150 disabled:opacity-[.35] disabled:cursor-not-allowed\"\n [ngClass]=\"{\n 'bg-[#ebebfa]': active(),\n 'text-[#5c5ce6]': active(),\n 'hover:bg-[#ddddf7]': active(),\n 'text-[#3d3d4d]': !active(),\n 'enabled:hover:bg-[#e8e8f0]': !active(),\n 'enabled:hover:text-[#1e1e2e]': !active()\n }\"\n [disabled]=\"disabled()\"\n [title]=\"label()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-pressed]=\"active()\"\n (click)=\"clicked.emit()\"\n>\n <i [class]=\"icon()\"></i>\n</button>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
73
|
+
}
|
|
74
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EditorToolbarButtonComponent, decorators: [{
|
|
75
|
+
type: Component,
|
|
76
|
+
args: [{ selector: 's-editor-toolbar-button', standalone: true, imports: [NgClass], host: { style: 'display: contents' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n type=\"button\"\n class=\"inline-flex items-center justify-center w-7 h-7 p-0 border-0 bg-transparent rounded cursor-pointer text-base leading-none transition-colors duration-150 disabled:opacity-[.35] disabled:cursor-not-allowed\"\n [ngClass]=\"{\n 'bg-[#ebebfa]': active(),\n 'text-[#5c5ce6]': active(),\n 'hover:bg-[#ddddf7]': active(),\n 'text-[#3d3d4d]': !active(),\n 'enabled:hover:bg-[#e8e8f0]': !active(),\n 'enabled:hover:text-[#1e1e2e]': !active()\n }\"\n [disabled]=\"disabled()\"\n [title]=\"label()\"\n [attr.aria-label]=\"label()\"\n [attr.aria-pressed]=\"active()\"\n (click)=\"clicked.emit()\"\n>\n <i [class]=\"icon()\"></i>\n</button>\n" }]
|
|
77
|
+
}] });
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @description Componente de editor de texto rico (WYSIWYG) construído sobre o Tiptap/ProseMirror.
|
|
81
|
+
* Substitui o `p-editor` do PrimeNG sem dependência externa de licença comercial.
|
|
82
|
+
* Implementa {@link ControlValueAccessor} para integração com Angular Forms.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```html
|
|
86
|
+
* <s-editor
|
|
87
|
+
* formControlName="descricao"
|
|
88
|
+
* [readonly]="false"
|
|
89
|
+
* (textChange)="onTextChange($event)" />
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
class EditorComponent {
|
|
93
|
+
cdr = inject(ChangeDetectorRef);
|
|
94
|
+
dialogService = inject(DialogService);
|
|
95
|
+
translateService = inject(TranslateService);
|
|
96
|
+
destroyRef = inject(DestroyRef);
|
|
97
|
+
/**
|
|
98
|
+
* @description Coloca o editor em modo somente leitura.
|
|
99
|
+
* @default false
|
|
100
|
+
*/
|
|
101
|
+
readonly = input(false);
|
|
102
|
+
/**
|
|
103
|
+
* @description Lista de formatos habilitados na toolbar. Quando vazio, todos os formatos são exibidos.
|
|
104
|
+
*/
|
|
105
|
+
formats = input();
|
|
106
|
+
/**
|
|
107
|
+
* @description Texto de dica exibido quando o editor está vazio.
|
|
108
|
+
*/
|
|
109
|
+
placeholder = input();
|
|
110
|
+
/**
|
|
111
|
+
* @description Estilos inline aplicados ao container do editor.
|
|
112
|
+
*/
|
|
113
|
+
style = input();
|
|
114
|
+
/**
|
|
115
|
+
* @description Classes CSS adicionais aplicadas ao container do editor.
|
|
116
|
+
*/
|
|
117
|
+
styleClass = input();
|
|
118
|
+
/**
|
|
119
|
+
* @description Extensões Tiptap adicionais para estender o comportamento padrão do editor.
|
|
120
|
+
*/
|
|
121
|
+
extensions = input([]);
|
|
122
|
+
/**
|
|
123
|
+
* @description Emitido quando o editor é inicializado e está pronto para uso.
|
|
124
|
+
*/
|
|
125
|
+
editorInit = output();
|
|
126
|
+
/**
|
|
127
|
+
* @description Emitido sempre que o conteúdo do editor é alterado.
|
|
128
|
+
*/
|
|
129
|
+
textChange = output();
|
|
130
|
+
/**
|
|
131
|
+
* @description Emitido quando a seleção de texto no editor muda.
|
|
132
|
+
*/
|
|
133
|
+
selectionChange = output();
|
|
134
|
+
editorContainer = viewChild.required('editorContainer');
|
|
135
|
+
imageInput = viewChild.required('imageInput');
|
|
136
|
+
editor;
|
|
137
|
+
_formDisabled = false;
|
|
138
|
+
_currentPlaceholder = '';
|
|
139
|
+
activeStates = {
|
|
140
|
+
isBold: false,
|
|
141
|
+
isItalic: false,
|
|
142
|
+
isUnderline: false,
|
|
143
|
+
isStrike: false,
|
|
144
|
+
isBulletList: false,
|
|
145
|
+
isOrderedList: false,
|
|
146
|
+
isBlockquote: false,
|
|
147
|
+
isCode: false,
|
|
148
|
+
isSubscript: false,
|
|
149
|
+
isSuperscript: false,
|
|
150
|
+
isAlignLeft: false,
|
|
151
|
+
isAlignCenter: false,
|
|
152
|
+
isAlignRight: false,
|
|
153
|
+
currentHeading: 0,
|
|
154
|
+
currentColor: '#000000',
|
|
155
|
+
currentHighlight: 'transparent',
|
|
156
|
+
canUndo: false,
|
|
157
|
+
canRedo: false,
|
|
158
|
+
};
|
|
159
|
+
_value = '';
|
|
160
|
+
_onChange = () => { };
|
|
161
|
+
_onTouched = () => { };
|
|
162
|
+
constructor() {
|
|
163
|
+
effect(() => {
|
|
164
|
+
if (this.editor) {
|
|
165
|
+
this.editor.setEditable(!this.readonly() && !this._formDisabled);
|
|
166
|
+
this.cdr.markForCheck();
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
effect(() => {
|
|
170
|
+
this._currentPlaceholder = this.placeholder() ?? '';
|
|
171
|
+
this.editor?.view.dispatch(this.editor.state.tr);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
ngAfterViewInit() {
|
|
175
|
+
this.initEditor();
|
|
176
|
+
}
|
|
177
|
+
ngOnDestroy() {
|
|
178
|
+
this.editor?.destroy();
|
|
179
|
+
}
|
|
180
|
+
writeValue(value) {
|
|
181
|
+
this._value = value ?? '';
|
|
182
|
+
if (this.editor) {
|
|
183
|
+
this.editor.chain().setMeta('addToHistory', false).setContent(this._value, { emitUpdate: false }).run();
|
|
184
|
+
this.cdr.markForCheck();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
registerOnChange(fn) {
|
|
188
|
+
this._onChange = fn;
|
|
189
|
+
}
|
|
190
|
+
registerOnTouched(fn) {
|
|
191
|
+
this._onTouched = fn;
|
|
192
|
+
}
|
|
193
|
+
setDisabledState(isDisabled) {
|
|
194
|
+
this._formDisabled = isDisabled;
|
|
195
|
+
this.editor?.setEditable(!isDisabled && !this.readonly());
|
|
196
|
+
this.cdr.markForCheck();
|
|
197
|
+
}
|
|
198
|
+
isFormatAllowed(format) {
|
|
199
|
+
const formats = this.formats();
|
|
200
|
+
return !formats?.length || formats.includes(format);
|
|
201
|
+
}
|
|
202
|
+
hasAnyFormatBeforeUndoRedo() {
|
|
203
|
+
const formatsBeforeUndoRedo = [
|
|
204
|
+
'header', 'bold', 'italic', 'underline', 'strike', 'subscript', 'superscript',
|
|
205
|
+
'color', 'highlight', 'list', 'align', 'blockquote', 'code-block', 'link', 'image',
|
|
206
|
+
];
|
|
207
|
+
return formatsBeforeUndoRedo.some(f => this.isFormatAllowed(f));
|
|
208
|
+
}
|
|
209
|
+
toggleBold() {
|
|
210
|
+
this.editor?.chain().focus().toggleBold().run();
|
|
211
|
+
}
|
|
212
|
+
toggleItalic() {
|
|
213
|
+
this.editor?.chain().focus().toggleItalic().run();
|
|
214
|
+
}
|
|
215
|
+
toggleUnderline() {
|
|
216
|
+
this.editor?.chain().focus().toggleUnderline().run();
|
|
217
|
+
}
|
|
218
|
+
toggleStrike() {
|
|
219
|
+
this.editor?.chain().focus().toggleStrike().run();
|
|
220
|
+
}
|
|
221
|
+
toggleBulletList() {
|
|
222
|
+
this.editor?.chain().focus().toggleBulletList().run();
|
|
223
|
+
}
|
|
224
|
+
toggleOrderedList() {
|
|
225
|
+
this.editor?.chain().focus().toggleOrderedList().run();
|
|
226
|
+
}
|
|
227
|
+
toggleBlockquote() {
|
|
228
|
+
this.editor?.chain().focus().toggleBlockquote().run();
|
|
229
|
+
}
|
|
230
|
+
toggleCode() {
|
|
231
|
+
this.editor?.chain().focus().toggleCode().run();
|
|
232
|
+
}
|
|
233
|
+
toggleSubscript() {
|
|
234
|
+
this.editor?.chain().focus().toggleSubscript().run();
|
|
235
|
+
}
|
|
236
|
+
toggleSuperscript() {
|
|
237
|
+
this.editor?.chain().focus().toggleSuperscript().run();
|
|
238
|
+
}
|
|
239
|
+
setTextAlign(align) {
|
|
240
|
+
this.editor?.chain().focus().setTextAlign(align).run();
|
|
241
|
+
}
|
|
242
|
+
setColor(color) {
|
|
243
|
+
this.editor?.chain().focus().setColor(color).run();
|
|
244
|
+
}
|
|
245
|
+
setHighlight(color) {
|
|
246
|
+
this.editor?.chain().focus().setHighlight({ color }).run();
|
|
247
|
+
}
|
|
248
|
+
clearFormatting() {
|
|
249
|
+
this.editor?.chain().focus().clearNodes().unsetAllMarks().run();
|
|
250
|
+
}
|
|
251
|
+
onHeadingChange(event) {
|
|
252
|
+
const level = parseInt(event.target.value);
|
|
253
|
+
if (isNaN(level) || level === 0) {
|
|
254
|
+
this.editor?.chain().focus().setParagraph().run();
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
this.editor?.chain().focus().setHeading({ level }).run();
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
setLink() {
|
|
261
|
+
const existingUrl = this.editor?.getAttributes('link')['href'] ?? '';
|
|
262
|
+
const ref = this.dialogService.open(LinkDialogComponent, { size: 'sm' });
|
|
263
|
+
ref.componentInstance.initialUrl = existingUrl;
|
|
264
|
+
ref.closed
|
|
265
|
+
.pipe(take(1), takeUntilDestroyed(this.destroyRef))
|
|
266
|
+
.subscribe((url) => {
|
|
267
|
+
if (url === '') {
|
|
268
|
+
this.editor?.chain().focus().extendMarkRange('link').unsetLink().run();
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
this.editor?.chain().focus().extendMarkRange('link').setLink({ href: url }).run();
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
setImage() {
|
|
276
|
+
this.imageInput().nativeElement.click();
|
|
277
|
+
}
|
|
278
|
+
onImageFileSelected(event) {
|
|
279
|
+
const input = event.target;
|
|
280
|
+
const file = input.files?.[0];
|
|
281
|
+
if (!file)
|
|
282
|
+
return;
|
|
283
|
+
const reader = new FileReader();
|
|
284
|
+
reader.onload = (e) => {
|
|
285
|
+
const src = e.target?.result;
|
|
286
|
+
this.editor?.chain().focus().setImage({ src }).run();
|
|
287
|
+
input.value = '';
|
|
288
|
+
this.cdr.markForCheck();
|
|
289
|
+
};
|
|
290
|
+
reader.readAsDataURL(file);
|
|
291
|
+
}
|
|
292
|
+
undo() {
|
|
293
|
+
this.editor?.chain().focus().undo().run();
|
|
294
|
+
}
|
|
295
|
+
redo() {
|
|
296
|
+
this.editor?.chain().focus().redo().run();
|
|
297
|
+
}
|
|
298
|
+
onToolbarKeydown(event) {
|
|
299
|
+
if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key))
|
|
300
|
+
return;
|
|
301
|
+
event.preventDefault();
|
|
302
|
+
const toolbar = event.currentTarget;
|
|
303
|
+
const focusable = this.getToolbarFocusable(toolbar);
|
|
304
|
+
if (!focusable.length)
|
|
305
|
+
return;
|
|
306
|
+
const currentIndex = focusable.findIndex(el => el === document.activeElement);
|
|
307
|
+
let nextIndex;
|
|
308
|
+
switch (event.key) {
|
|
309
|
+
case 'ArrowRight':
|
|
310
|
+
nextIndex = (currentIndex + 1) % focusable.length;
|
|
311
|
+
break;
|
|
312
|
+
case 'ArrowLeft':
|
|
313
|
+
nextIndex = (currentIndex - 1 + focusable.length) % focusable.length;
|
|
314
|
+
break;
|
|
315
|
+
case 'Home':
|
|
316
|
+
nextIndex = 0;
|
|
317
|
+
break;
|
|
318
|
+
default:
|
|
319
|
+
nextIndex = focusable.length - 1;
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
focusable.forEach((el, i) => el.setAttribute('tabindex', i === nextIndex ? '0' : '-1'));
|
|
323
|
+
focusable[nextIndex].focus();
|
|
324
|
+
}
|
|
325
|
+
onToolbarFocusIn(event) {
|
|
326
|
+
const target = event.target;
|
|
327
|
+
const toolbar = event.currentTarget;
|
|
328
|
+
const focusable = this.getToolbarFocusable(toolbar);
|
|
329
|
+
if (focusable.includes(target)) {
|
|
330
|
+
focusable.forEach(el => el.setAttribute('tabindex', el === target ? '0' : '-1'));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
getToolbarFocusable(toolbar) {
|
|
334
|
+
return Array.from(toolbar.querySelectorAll('button:not([disabled]), select, label[tabindex]'));
|
|
335
|
+
}
|
|
336
|
+
initEditor() {
|
|
337
|
+
this.editor = new Editor({
|
|
338
|
+
element: this.editorContainer().nativeElement,
|
|
339
|
+
extensions: [
|
|
340
|
+
StarterKit.configure({
|
|
341
|
+
link: { openOnClick: false },
|
|
342
|
+
underline: false,
|
|
343
|
+
}),
|
|
344
|
+
Underline,
|
|
345
|
+
Image,
|
|
346
|
+
TextAlign.configure({ types: ['heading', 'paragraph'] }),
|
|
347
|
+
TextStyle,
|
|
348
|
+
Color,
|
|
349
|
+
Highlight.configure({ multicolor: true }),
|
|
350
|
+
Placeholder.configure({ placeholder: () => this._currentPlaceholder }),
|
|
351
|
+
Subscript,
|
|
352
|
+
Superscript,
|
|
353
|
+
...this.extensions(),
|
|
354
|
+
],
|
|
355
|
+
content: this._value,
|
|
356
|
+
editable: !this.readonly(),
|
|
357
|
+
editorProps: {
|
|
358
|
+
attributes: {
|
|
359
|
+
role: 'textbox',
|
|
360
|
+
'aria-multiline': 'true',
|
|
361
|
+
'aria-label': this.translateService.instant('platform.angular_components.editor_content_area'),
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
onUpdate: ({ editor }) => {
|
|
365
|
+
const html = editor.getHTML();
|
|
366
|
+
const text = editor.getText();
|
|
367
|
+
this._value = html;
|
|
368
|
+
this._onChange(html);
|
|
369
|
+
this.textChange.emit({ htmlValue: html, textValue: text });
|
|
370
|
+
this.syncActiveStates();
|
|
371
|
+
this.cdr.markForCheck();
|
|
372
|
+
},
|
|
373
|
+
onBlur: () => {
|
|
374
|
+
this._onTouched();
|
|
375
|
+
},
|
|
376
|
+
onSelectionUpdate: ({ editor }) => {
|
|
377
|
+
this.syncActiveStates();
|
|
378
|
+
const { from, to, empty } = editor.state.selection;
|
|
379
|
+
this.selectionChange.emit({ from, to, empty });
|
|
380
|
+
this.cdr.markForCheck();
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
this.syncActiveStates();
|
|
384
|
+
this.cdr.markForCheck();
|
|
385
|
+
this.editorInit.emit(this.editor);
|
|
386
|
+
}
|
|
387
|
+
syncActiveStates() {
|
|
388
|
+
if (!this.editor)
|
|
389
|
+
return;
|
|
390
|
+
const e = this.editor;
|
|
391
|
+
this.activeStates = {
|
|
392
|
+
isBold: e.isActive('bold'),
|
|
393
|
+
isItalic: e.isActive('italic'),
|
|
394
|
+
isUnderline: e.isActive('underline'),
|
|
395
|
+
isStrike: e.isActive('strike'),
|
|
396
|
+
isBulletList: e.isActive('bulletList'),
|
|
397
|
+
isOrderedList: e.isActive('orderedList'),
|
|
398
|
+
isBlockquote: e.isActive('blockquote'),
|
|
399
|
+
isCode: e.isActive('code'),
|
|
400
|
+
isSubscript: e.isActive('subscript'),
|
|
401
|
+
isSuperscript: e.isActive('superscript'),
|
|
402
|
+
isAlignLeft: e.isActive({ textAlign: 'left' }),
|
|
403
|
+
isAlignCenter: e.isActive({ textAlign: 'center' }),
|
|
404
|
+
isAlignRight: e.isActive({ textAlign: 'right' }),
|
|
405
|
+
currentHeading: [1, 2, 3].find((level) => e.isActive('heading', { level })) ?? 0,
|
|
406
|
+
currentColor: e.getAttributes('textStyle')['color'] || '#000000',
|
|
407
|
+
currentHighlight: e.getAttributes('highlight')['color'] || 'transparent',
|
|
408
|
+
canUndo: e.can().undo(),
|
|
409
|
+
canRedo: e.can().redo(),
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
413
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: EditorComponent, isStandalone: true, selector: "s-editor", inputs: { readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, formats: { classPropertyName: "formats", publicName: "formats", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, extensions: { classPropertyName: "extensions", publicName: "extensions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { editorInit: "editorInit", textChange: "textChange", selectionChange: "selectionChange" }, providers: [
|
|
414
|
+
{
|
|
415
|
+
provide: NG_VALUE_ACCESSOR,
|
|
416
|
+
useExisting: forwardRef(() => EditorComponent),
|
|
417
|
+
multi: true,
|
|
418
|
+
},
|
|
419
|
+
], viewQueries: [{ propertyName: "editorContainer", first: true, predicate: ["editorContainer"], descendants: true, isSignal: true }, { propertyName: "imageInput", first: true, predicate: ["imageInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"rounded bg-white flex flex-col border border-grayscale-30 transition-[border-color,box-shadow] duration-150 focus-within:border-[#5c5ce6] focus-within:shadow-[0_0_0_2px_rgba(92,92,230,0.15)]\"\n [ngClass]=\"styleClass()\"\n [ngStyle]=\"style()\"\n [class.s-editor--readonly]=\"readonly()\"\n>\n @if (!readonly()) {\n <div\n class=\"rounded-t flex flex-wrap items-center gap-0.5 border-b border-grayscale-30 bg-[#f9f9fb] px-2 py-1.5\"\n role=\"toolbar\"\n [attr.aria-label]=\"'platform.angular_components.editor_toolbar' | translate\"\n (keydown)=\"onToolbarKeydown($event)\"\n (focusin)=\"onToolbarFocusIn($event)\"\n >\n @if (isFormatAllowed('header')) {\n <select\n class=\"rounded bg-white h-7 cursor-pointer border border-grayscale-30 px-1.5 text-[13px] text-[#3d3d4d] outline-none transition-colors duration-150 focus:border-[#5c5ce6]\"\n (change)=\"onHeadingChange($event)\"\n [attr.aria-label]=\"'platform.angular_components.editor_heading_level' | translate\"\n >\n <option\n [value]=\"0\"\n [selected]=\"activeStates.currentHeading === 0\"\n >\n {{ 'platform.angular_components.editor_heading_normal' | translate }}\n </option>\n <option\n [value]=\"1\"\n [selected]=\"activeStates.currentHeading === 1\"\n >\n {{ 'platform.angular_components.editor_heading_1' | translate }}\n </option>\n <option\n [value]=\"2\"\n [selected]=\"activeStates.currentHeading === 2\"\n >\n {{ 'platform.angular_components.editor_heading_2' | translate }}\n </option>\n <option\n [value]=\"3\"\n [selected]=\"activeStates.currentHeading === 3\"\n >\n {{ 'platform.angular_components.editor_heading_3' | translate }}\n </option>\n </select>\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n }\n\n @if (isFormatAllowed('bold')) {\n <s-editor-toolbar-button\n icon=\"fa fa-bold\"\n [label]=\"'platform.angular_components.editor_bold' | translate\"\n [active]=\"activeStates.isBold\"\n (clicked)=\"toggleBold()\"\n />\n }\n\n @if (isFormatAllowed('italic')) {\n <s-editor-toolbar-button\n icon=\"fa fa-italic\"\n [label]=\"'platform.angular_components.editor_italic' | translate\"\n [active]=\"activeStates.isItalic\"\n (clicked)=\"toggleItalic()\"\n />\n }\n\n @if (isFormatAllowed('underline')) {\n <s-editor-toolbar-button\n icon=\"fa fa-underline\"\n [label]=\"'platform.angular_components.editor_underline' | translate\"\n [active]=\"activeStates.isUnderline\"\n (clicked)=\"toggleUnderline()\"\n />\n }\n\n @if (isFormatAllowed('strike')) {\n <s-editor-toolbar-button\n icon=\"fa fa-strikethrough\"\n [label]=\"'platform.angular_components.editor_strikethrough' | translate\"\n [active]=\"activeStates.isStrike\"\n (clicked)=\"toggleStrike()\"\n />\n }\n\n @if (isFormatAllowed('subscript')) {\n <s-editor-toolbar-button\n icon=\"fa fa-subscript\"\n [label]=\"'platform.angular_components.editor_subscript' | translate\"\n [active]=\"activeStates.isSubscript\"\n (clicked)=\"toggleSubscript()\"\n />\n }\n\n @if (isFormatAllowed('superscript')) {\n <s-editor-toolbar-button\n icon=\"fa fa-superscript\"\n [label]=\"'platform.angular_components.editor_superscript' | translate\"\n [active]=\"activeStates.isSuperscript\"\n (clicked)=\"toggleSuperscript()\"\n />\n }\n\n @if (isFormatAllowed('color')) {\n <label\n tabindex=\"0\"\n class=\"relative flex h-7 w-7 cursor-pointer items-center justify-center rounded bg-white transition-colors duration-150 hover:bg-[#f0f0f8]\"\n [attr.title]=\"'platform.angular_components.editor_text_color' | translate\"\n [attr.aria-label]=\"'platform.angular_components.editor_text_color' | translate\"\n (keydown.enter)=\"$event.preventDefault(); colorInput.click()\"\n (keydown.space)=\"$event.preventDefault(); colorInput.click()\"\n >\n <span class=\"flex flex-col items-center gap-px\">\n <i class=\"fa fa-font text-[11px] text-[#3d3d4d]\"></i>\n <span\n class=\"h-[3px] w-3.5 rounded-sm\"\n [style.background-color]=\"activeStates.currentColor\"\n ></span>\n </span>\n <input\n #colorInput\n type=\"color\"\n class=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n [value]=\"activeStates.currentColor\"\n (input)=\"setColor($any($event.target).value)\"\n />\n </label>\n }\n\n @if (isFormatAllowed('highlight')) {\n <label\n tabindex=\"0\"\n class=\"relative flex h-7 w-7 cursor-pointer items-center justify-center rounded bg-white transition-colors duration-150 hover:bg-[#f0f0f8]\"\n [attr.title]=\"'platform.angular_components.editor_background_color' | translate\"\n [attr.aria-label]=\"'platform.angular_components.editor_background_color' | translate\"\n (keydown.enter)=\"$event.preventDefault(); highlightInput.click()\"\n (keydown.space)=\"$event.preventDefault(); highlightInput.click()\"\n >\n <span class=\"flex flex-col items-center gap-px\">\n <i class=\"fa fa-highlighter text-[11px] text-[#3d3d4d]\"></i>\n <span\n class=\"h-[3px] w-3.5 rounded-sm\"\n [style.background-color]=\"activeStates.currentHighlight === 'transparent' ? '#ffff00' : activeStates.currentHighlight\"\n ></span>\n </span>\n <input\n #highlightInput\n type=\"color\"\n class=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n [value]=\"activeStates.currentHighlight === 'transparent' ? '#ffff00' : activeStates.currentHighlight\"\n (input)=\"setHighlight($any($event.target).value)\"\n />\n </label>\n }\n\n @if (isFormatAllowed('list')) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n <s-editor-toolbar-button\n icon=\"fa fa-list-ul\"\n [label]=\"'platform.angular_components.editor_bullet_list' | translate\"\n [active]=\"activeStates.isBulletList\"\n (clicked)=\"toggleBulletList()\"\n />\n <s-editor-toolbar-button\n icon=\"fa fa-list-ol\"\n [label]=\"'platform.angular_components.editor_ordered_list' | translate\"\n [active]=\"activeStates.isOrderedList\"\n (clicked)=\"toggleOrderedList()\"\n />\n }\n\n @if (isFormatAllowed('align')) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n <s-editor-toolbar-button\n icon=\"fa fa-align-left\"\n [label]=\"'platform.angular_components.editor_align_left' | translate\"\n [active]=\"activeStates.isAlignLeft\"\n (clicked)=\"setTextAlign('left')\"\n />\n <s-editor-toolbar-button\n icon=\"fa fa-align-center\"\n [label]=\"'platform.angular_components.editor_align_center' | translate\"\n [active]=\"activeStates.isAlignCenter\"\n (clicked)=\"setTextAlign('center')\"\n />\n <s-editor-toolbar-button\n icon=\"fa fa-align-right\"\n [label]=\"'platform.angular_components.editor_align_right' | translate\"\n [active]=\"activeStates.isAlignRight\"\n (clicked)=\"setTextAlign('right')\"\n />\n }\n\n @if (isFormatAllowed('blockquote')) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n <s-editor-toolbar-button\n icon=\"fa fa-quote-right\"\n [label]=\"'platform.angular_components.editor_blockquote' | translate\"\n [active]=\"activeStates.isBlockquote\"\n (clicked)=\"toggleBlockquote()\"\n />\n }\n\n @if (isFormatAllowed('code-block')) {\n <s-editor-toolbar-button\n icon=\"fa fa-code\"\n [label]=\"'platform.angular_components.editor_inline_code' | translate\"\n [active]=\"activeStates.isCode\"\n (clicked)=\"toggleCode()\"\n />\n }\n\n @if (isFormatAllowed('link')) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n <s-editor-toolbar-button\n icon=\"fa fa-link\"\n [label]=\"'platform.angular_components.editor_insert_link' | translate\"\n (clicked)=\"setLink()\"\n />\n }\n\n @if (isFormatAllowed('image')) {\n <s-editor-toolbar-button\n icon=\"fa fa-image\"\n [label]=\"'platform.angular_components.editor_insert_image' | translate\"\n (clicked)=\"setImage()\"\n />\n }\n\n @if (hasAnyFormatBeforeUndoRedo()) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n }\n\n <s-editor-toolbar-button\n icon=\"fa fa-undo\"\n [label]=\"('platform.angular_components.editor_undo' | translate) + ' (Ctrl+Z)'\"\n [disabled]=\"!activeStates.canUndo\"\n (clicked)=\"undo()\"\n />\n <s-editor-toolbar-button\n icon=\"fa fa-redo\"\n [label]=\"('platform.angular_components.editor_redo' | translate) + ' (Ctrl+Y)'\"\n [disabled]=\"!activeStates.canRedo\"\n (clicked)=\"redo()\"\n />\n\n @if (isFormatAllowed('clean')) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n <s-editor-toolbar-button\n icon=\"fa fa-remove-format\"\n [label]=\"'platform.angular_components.editor_clear_formatting' | translate\"\n (clicked)=\"clearFormatting()\"\n />\n }\n </div>\n }\n\n <div\n #editorContainer\n class=\"s-editor-content flex-1\"\n ></div>\n <input\n #imageInput\n type=\"file\"\n accept=\"image/*\"\n style=\"display: none\"\n aria-hidden=\"true\"\n (change)=\"onImageFileSelected($event)\"\n />\n</div>\n", styles: [".s-editor--readonly ::ng-deep .ProseMirror{cursor:default}.s-editor-content ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:#9ca3af;pointer-events:none;float:left;height:0}.s-editor-content ::ng-deep .ProseMirror{padding:12px 16px;min-height:150px;outline:none!important;color:#1e1e2e;font-size:14px;line-height:1.6}.s-editor-content ::ng-deep .ProseMirror>*+*{margin-top:.5em}.s-editor-content ::ng-deep .ProseMirror p{margin:0}.s-editor-content ::ng-deep .ProseMirror h1{font-size:1.75em;font-weight:700;line-height:1.2;margin:.75em 0 .25em}.s-editor-content ::ng-deep .ProseMirror h1:first-child{margin-top:0}.s-editor-content ::ng-deep .ProseMirror h2{font-size:1.4em;font-weight:600;line-height:1.3;margin:.75em 0 .25em}.s-editor-content ::ng-deep .ProseMirror h2:first-child{margin-top:0}.s-editor-content ::ng-deep .ProseMirror h3{font-size:1.15em;font-weight:600;line-height:1.4;margin:.75em 0 .25em}.s-editor-content ::ng-deep .ProseMirror h3:first-child{margin-top:0}.s-editor-content ::ng-deep .ProseMirror ul{list-style:disc;padding-left:1.5em}.s-editor-content ::ng-deep .ProseMirror ol{list-style:decimal;padding-left:1.5em}.s-editor-content ::ng-deep .ProseMirror li{margin:.2em 0}.s-editor-content ::ng-deep .ProseMirror li p{margin:0}.s-editor-content ::ng-deep .ProseMirror blockquote{border-left:3px solid #5c5ce6;padding-left:1em;margin:.75em 0;color:#6b6b80;font-style:italic}.s-editor-content ::ng-deep .ProseMirror code{background:#f0f0f8;border-radius:3px;padding:.15em .4em;font-family:Courier New,Courier,monospace;font-size:.875em;color:#c026d3}.s-editor-content ::ng-deep .ProseMirror pre{background:#1e1e2e;color:#cdd6f4;border-radius:6px;padding:1em 1.25em;overflow-x:auto;font-family:Courier New,Courier,monospace;font-size:.875em;line-height:1.5}.s-editor-content ::ng-deep .ProseMirror pre code{background:none;padding:0;color:inherit;font-size:inherit}.s-editor-content ::ng-deep .ProseMirror a{color:#5c5ce6;text-decoration:underline;cursor:pointer}.s-editor-content ::ng-deep .ProseMirror a:hover{color:#4040b0}.s-editor-content ::ng-deep .ProseMirror img{max-width:100%;height:auto;border-radius:4px;display:block}.s-editor-content ::ng-deep .ProseMirror hr{border:none;border-top:2px solid #e8e8f0;margin:1em 0}.s-editor-content ::ng-deep .ProseMirror sub{font-size:.75em;vertical-align:sub}.s-editor-content ::ng-deep .ProseMirror sup{font-size:.75em;vertical-align:super}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "component", type: EditorToolbarButtonComponent, selector: "s-editor-toolbar-button", inputs: ["icon", "label", "active", "disabled"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
420
|
+
}
|
|
421
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EditorComponent, decorators: [{
|
|
422
|
+
type: Component,
|
|
423
|
+
args: [{ selector: 's-editor', standalone: true, imports: [NgClass, NgStyle, TranslateModule, EditorToolbarButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
424
|
+
{
|
|
425
|
+
provide: NG_VALUE_ACCESSOR,
|
|
426
|
+
useExisting: forwardRef(() => EditorComponent),
|
|
427
|
+
multi: true,
|
|
428
|
+
},
|
|
429
|
+
], template: "<div\n class=\"rounded bg-white flex flex-col border border-grayscale-30 transition-[border-color,box-shadow] duration-150 focus-within:border-[#5c5ce6] focus-within:shadow-[0_0_0_2px_rgba(92,92,230,0.15)]\"\n [ngClass]=\"styleClass()\"\n [ngStyle]=\"style()\"\n [class.s-editor--readonly]=\"readonly()\"\n>\n @if (!readonly()) {\n <div\n class=\"rounded-t flex flex-wrap items-center gap-0.5 border-b border-grayscale-30 bg-[#f9f9fb] px-2 py-1.5\"\n role=\"toolbar\"\n [attr.aria-label]=\"'platform.angular_components.editor_toolbar' | translate\"\n (keydown)=\"onToolbarKeydown($event)\"\n (focusin)=\"onToolbarFocusIn($event)\"\n >\n @if (isFormatAllowed('header')) {\n <select\n class=\"rounded bg-white h-7 cursor-pointer border border-grayscale-30 px-1.5 text-[13px] text-[#3d3d4d] outline-none transition-colors duration-150 focus:border-[#5c5ce6]\"\n (change)=\"onHeadingChange($event)\"\n [attr.aria-label]=\"'platform.angular_components.editor_heading_level' | translate\"\n >\n <option\n [value]=\"0\"\n [selected]=\"activeStates.currentHeading === 0\"\n >\n {{ 'platform.angular_components.editor_heading_normal' | translate }}\n </option>\n <option\n [value]=\"1\"\n [selected]=\"activeStates.currentHeading === 1\"\n >\n {{ 'platform.angular_components.editor_heading_1' | translate }}\n </option>\n <option\n [value]=\"2\"\n [selected]=\"activeStates.currentHeading === 2\"\n >\n {{ 'platform.angular_components.editor_heading_2' | translate }}\n </option>\n <option\n [value]=\"3\"\n [selected]=\"activeStates.currentHeading === 3\"\n >\n {{ 'platform.angular_components.editor_heading_3' | translate }}\n </option>\n </select>\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n }\n\n @if (isFormatAllowed('bold')) {\n <s-editor-toolbar-button\n icon=\"fa fa-bold\"\n [label]=\"'platform.angular_components.editor_bold' | translate\"\n [active]=\"activeStates.isBold\"\n (clicked)=\"toggleBold()\"\n />\n }\n\n @if (isFormatAllowed('italic')) {\n <s-editor-toolbar-button\n icon=\"fa fa-italic\"\n [label]=\"'platform.angular_components.editor_italic' | translate\"\n [active]=\"activeStates.isItalic\"\n (clicked)=\"toggleItalic()\"\n />\n }\n\n @if (isFormatAllowed('underline')) {\n <s-editor-toolbar-button\n icon=\"fa fa-underline\"\n [label]=\"'platform.angular_components.editor_underline' | translate\"\n [active]=\"activeStates.isUnderline\"\n (clicked)=\"toggleUnderline()\"\n />\n }\n\n @if (isFormatAllowed('strike')) {\n <s-editor-toolbar-button\n icon=\"fa fa-strikethrough\"\n [label]=\"'platform.angular_components.editor_strikethrough' | translate\"\n [active]=\"activeStates.isStrike\"\n (clicked)=\"toggleStrike()\"\n />\n }\n\n @if (isFormatAllowed('subscript')) {\n <s-editor-toolbar-button\n icon=\"fa fa-subscript\"\n [label]=\"'platform.angular_components.editor_subscript' | translate\"\n [active]=\"activeStates.isSubscript\"\n (clicked)=\"toggleSubscript()\"\n />\n }\n\n @if (isFormatAllowed('superscript')) {\n <s-editor-toolbar-button\n icon=\"fa fa-superscript\"\n [label]=\"'platform.angular_components.editor_superscript' | translate\"\n [active]=\"activeStates.isSuperscript\"\n (clicked)=\"toggleSuperscript()\"\n />\n }\n\n @if (isFormatAllowed('color')) {\n <label\n tabindex=\"0\"\n class=\"relative flex h-7 w-7 cursor-pointer items-center justify-center rounded bg-white transition-colors duration-150 hover:bg-[#f0f0f8]\"\n [attr.title]=\"'platform.angular_components.editor_text_color' | translate\"\n [attr.aria-label]=\"'platform.angular_components.editor_text_color' | translate\"\n (keydown.enter)=\"$event.preventDefault(); colorInput.click()\"\n (keydown.space)=\"$event.preventDefault(); colorInput.click()\"\n >\n <span class=\"flex flex-col items-center gap-px\">\n <i class=\"fa fa-font text-[11px] text-[#3d3d4d]\"></i>\n <span\n class=\"h-[3px] w-3.5 rounded-sm\"\n [style.background-color]=\"activeStates.currentColor\"\n ></span>\n </span>\n <input\n #colorInput\n type=\"color\"\n class=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n [value]=\"activeStates.currentColor\"\n (input)=\"setColor($any($event.target).value)\"\n />\n </label>\n }\n\n @if (isFormatAllowed('highlight')) {\n <label\n tabindex=\"0\"\n class=\"relative flex h-7 w-7 cursor-pointer items-center justify-center rounded bg-white transition-colors duration-150 hover:bg-[#f0f0f8]\"\n [attr.title]=\"'platform.angular_components.editor_background_color' | translate\"\n [attr.aria-label]=\"'platform.angular_components.editor_background_color' | translate\"\n (keydown.enter)=\"$event.preventDefault(); highlightInput.click()\"\n (keydown.space)=\"$event.preventDefault(); highlightInput.click()\"\n >\n <span class=\"flex flex-col items-center gap-px\">\n <i class=\"fa fa-highlighter text-[11px] text-[#3d3d4d]\"></i>\n <span\n class=\"h-[3px] w-3.5 rounded-sm\"\n [style.background-color]=\"activeStates.currentHighlight === 'transparent' ? '#ffff00' : activeStates.currentHighlight\"\n ></span>\n </span>\n <input\n #highlightInput\n type=\"color\"\n class=\"absolute inset-0 h-full w-full cursor-pointer opacity-0\"\n [value]=\"activeStates.currentHighlight === 'transparent' ? '#ffff00' : activeStates.currentHighlight\"\n (input)=\"setHighlight($any($event.target).value)\"\n />\n </label>\n }\n\n @if (isFormatAllowed('list')) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n <s-editor-toolbar-button\n icon=\"fa fa-list-ul\"\n [label]=\"'platform.angular_components.editor_bullet_list' | translate\"\n [active]=\"activeStates.isBulletList\"\n (clicked)=\"toggleBulletList()\"\n />\n <s-editor-toolbar-button\n icon=\"fa fa-list-ol\"\n [label]=\"'platform.angular_components.editor_ordered_list' | translate\"\n [active]=\"activeStates.isOrderedList\"\n (clicked)=\"toggleOrderedList()\"\n />\n }\n\n @if (isFormatAllowed('align')) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n <s-editor-toolbar-button\n icon=\"fa fa-align-left\"\n [label]=\"'platform.angular_components.editor_align_left' | translate\"\n [active]=\"activeStates.isAlignLeft\"\n (clicked)=\"setTextAlign('left')\"\n />\n <s-editor-toolbar-button\n icon=\"fa fa-align-center\"\n [label]=\"'platform.angular_components.editor_align_center' | translate\"\n [active]=\"activeStates.isAlignCenter\"\n (clicked)=\"setTextAlign('center')\"\n />\n <s-editor-toolbar-button\n icon=\"fa fa-align-right\"\n [label]=\"'platform.angular_components.editor_align_right' | translate\"\n [active]=\"activeStates.isAlignRight\"\n (clicked)=\"setTextAlign('right')\"\n />\n }\n\n @if (isFormatAllowed('blockquote')) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n <s-editor-toolbar-button\n icon=\"fa fa-quote-right\"\n [label]=\"'platform.angular_components.editor_blockquote' | translate\"\n [active]=\"activeStates.isBlockquote\"\n (clicked)=\"toggleBlockquote()\"\n />\n }\n\n @if (isFormatAllowed('code-block')) {\n <s-editor-toolbar-button\n icon=\"fa fa-code\"\n [label]=\"'platform.angular_components.editor_inline_code' | translate\"\n [active]=\"activeStates.isCode\"\n (clicked)=\"toggleCode()\"\n />\n }\n\n @if (isFormatAllowed('link')) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n <s-editor-toolbar-button\n icon=\"fa fa-link\"\n [label]=\"'platform.angular_components.editor_insert_link' | translate\"\n (clicked)=\"setLink()\"\n />\n }\n\n @if (isFormatAllowed('image')) {\n <s-editor-toolbar-button\n icon=\"fa fa-image\"\n [label]=\"'platform.angular_components.editor_insert_image' | translate\"\n (clicked)=\"setImage()\"\n />\n }\n\n @if (hasAnyFormatBeforeUndoRedo()) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n }\n\n <s-editor-toolbar-button\n icon=\"fa fa-undo\"\n [label]=\"('platform.angular_components.editor_undo' | translate) + ' (Ctrl+Z)'\"\n [disabled]=\"!activeStates.canUndo\"\n (clicked)=\"undo()\"\n />\n <s-editor-toolbar-button\n icon=\"fa fa-redo\"\n [label]=\"('platform.angular_components.editor_redo' | translate) + ' (Ctrl+Y)'\"\n [disabled]=\"!activeStates.canRedo\"\n (clicked)=\"redo()\"\n />\n\n @if (isFormatAllowed('clean')) {\n <span class=\"mx-1 inline-block h-5 w-px shrink-0 bg-[#d1d1dc]\"></span>\n <s-editor-toolbar-button\n icon=\"fa fa-remove-format\"\n [label]=\"'platform.angular_components.editor_clear_formatting' | translate\"\n (clicked)=\"clearFormatting()\"\n />\n }\n </div>\n }\n\n <div\n #editorContainer\n class=\"s-editor-content flex-1\"\n ></div>\n <input\n #imageInput\n type=\"file\"\n accept=\"image/*\"\n style=\"display: none\"\n aria-hidden=\"true\"\n (change)=\"onImageFileSelected($event)\"\n />\n</div>\n", styles: [".s-editor--readonly ::ng-deep .ProseMirror{cursor:default}.s-editor-content ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:#9ca3af;pointer-events:none;float:left;height:0}.s-editor-content ::ng-deep .ProseMirror{padding:12px 16px;min-height:150px;outline:none!important;color:#1e1e2e;font-size:14px;line-height:1.6}.s-editor-content ::ng-deep .ProseMirror>*+*{margin-top:.5em}.s-editor-content ::ng-deep .ProseMirror p{margin:0}.s-editor-content ::ng-deep .ProseMirror h1{font-size:1.75em;font-weight:700;line-height:1.2;margin:.75em 0 .25em}.s-editor-content ::ng-deep .ProseMirror h1:first-child{margin-top:0}.s-editor-content ::ng-deep .ProseMirror h2{font-size:1.4em;font-weight:600;line-height:1.3;margin:.75em 0 .25em}.s-editor-content ::ng-deep .ProseMirror h2:first-child{margin-top:0}.s-editor-content ::ng-deep .ProseMirror h3{font-size:1.15em;font-weight:600;line-height:1.4;margin:.75em 0 .25em}.s-editor-content ::ng-deep .ProseMirror h3:first-child{margin-top:0}.s-editor-content ::ng-deep .ProseMirror ul{list-style:disc;padding-left:1.5em}.s-editor-content ::ng-deep .ProseMirror ol{list-style:decimal;padding-left:1.5em}.s-editor-content ::ng-deep .ProseMirror li{margin:.2em 0}.s-editor-content ::ng-deep .ProseMirror li p{margin:0}.s-editor-content ::ng-deep .ProseMirror blockquote{border-left:3px solid #5c5ce6;padding-left:1em;margin:.75em 0;color:#6b6b80;font-style:italic}.s-editor-content ::ng-deep .ProseMirror code{background:#f0f0f8;border-radius:3px;padding:.15em .4em;font-family:Courier New,Courier,monospace;font-size:.875em;color:#c026d3}.s-editor-content ::ng-deep .ProseMirror pre{background:#1e1e2e;color:#cdd6f4;border-radius:6px;padding:1em 1.25em;overflow-x:auto;font-family:Courier New,Courier,monospace;font-size:.875em;line-height:1.5}.s-editor-content ::ng-deep .ProseMirror pre code{background:none;padding:0;color:inherit;font-size:inherit}.s-editor-content ::ng-deep .ProseMirror a{color:#5c5ce6;text-decoration:underline;cursor:pointer}.s-editor-content ::ng-deep .ProseMirror a:hover{color:#4040b0}.s-editor-content ::ng-deep .ProseMirror img{max-width:100%;height:auto;border-radius:4px;display:block}.s-editor-content ::ng-deep .ProseMirror hr{border:none;border-top:2px solid #e8e8f0;margin:1em 0}.s-editor-content ::ng-deep .ProseMirror sub{font-size:.75em;vertical-align:sub}.s-editor-content ::ng-deep .ProseMirror sup{font-size:.75em;vertical-align:super}\n"] }]
|
|
430
|
+
}], ctorParameters: () => [] });
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Generated bundle index. Do not edit.
|
|
434
|
+
*/
|
|
435
|
+
|
|
436
|
+
export { EditorComponent };
|
|
437
|
+
//# sourceMappingURL=seniorsistemas-angular-components-editor.mjs.map
|