399 lines
17 KiB
JavaScript
399 lines
17 KiB
JavaScript
|
import * as i1 from '@angular/common';
|
|||
|
import { isPlatformServer, CommonModule } from '@angular/common';
|
|||
|
import * as i0 from '@angular/core';
|
|||
|
import { forwardRef, EventEmitter, afterNextRender, PLATFORM_ID, Component, ChangeDetectionStrategy, ViewEncapsulation, Inject, Input, Output, ContentChildren, ContentChild, NgModule } from '@angular/core';
|
|||
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|||
|
import { Header, PrimeTemplate, SharedModule } from 'primeng/api';
|
|||
|
import { DomHandler } from 'primeng/dom';
|
|||
|
|
|||
|
const EDITOR_VALUE_ACCESSOR = {
|
|||
|
provide: NG_VALUE_ACCESSOR,
|
|||
|
useExisting: forwardRef(() => Editor),
|
|||
|
multi: true
|
|||
|
};
|
|||
|
/**
|
|||
|
* Editor groups a collection of contents in tabs.
|
|||
|
* @group Components
|
|||
|
*/
|
|||
|
class Editor {
|
|||
|
el;
|
|||
|
platformId;
|
|||
|
/**
|
|||
|
* Inline style of the container.
|
|||
|
* @group Props
|
|||
|
*/
|
|||
|
style;
|
|||
|
/**
|
|||
|
* Style class of the container.
|
|||
|
* @group Props
|
|||
|
*/
|
|||
|
styleClass;
|
|||
|
/**
|
|||
|
* Placeholder text to show when editor is empty.
|
|||
|
* @group Props
|
|||
|
*/
|
|||
|
placeholder;
|
|||
|
/**
|
|||
|
* Whitelist of formats to display, see here for available options.
|
|||
|
* @group Props
|
|||
|
*/
|
|||
|
formats;
|
|||
|
/**
|
|||
|
* Modules configuration of Editor, see here for available options.
|
|||
|
* @group Props
|
|||
|
*/
|
|||
|
modules;
|
|||
|
/**
|
|||
|
* DOM Element or a CSS selector for a DOM Element, within which the editor’s p elements (i.e. tooltips, etc.) should be confined. Currently, it only considers left and right boundaries.
|
|||
|
* @group Props
|
|||
|
*/
|
|||
|
bounds;
|
|||
|
/**
|
|||
|
* DOM Element or a CSS selector for a DOM Element, specifying which container has the scrollbars (i.e. overflow-y: auto), if is has been changed from the default ql-editor with custom CSS. Necessary to fix scroll jumping bugs when Quill is set to auto grow its height, and another ancestor container is responsible from the scrolling..
|
|||
|
* @group Props
|
|||
|
*/
|
|||
|
scrollingContainer;
|
|||
|
/**
|
|||
|
* Shortcut for debug. Note debug is a static method and will affect other instances of Quill editors on the page. Only warning and error messages are enabled by default.
|
|||
|
* @group Props
|
|||
|
*/
|
|||
|
debug;
|
|||
|
/**
|
|||
|
* Whether to instantiate the editor to read-only mode.
|
|||
|
* @group Props
|
|||
|
*/
|
|||
|
get readonly() {
|
|||
|
return this._readonly;
|
|||
|
}
|
|||
|
set readonly(val) {
|
|||
|
this._readonly = val;
|
|||
|
if (this.quill) {
|
|||
|
if (this._readonly)
|
|||
|
this.quill.disable();
|
|||
|
else
|
|||
|
this.quill.enable();
|
|||
|
}
|
|||
|
}
|
|||
|
/**
|
|||
|
* Callback to invoke when the quill modules are loaded.
|
|||
|
* @param {EditorInitEvent} event - custom event.
|
|||
|
* @group Emits
|
|||
|
*/
|
|||
|
onInit = new EventEmitter();
|
|||
|
/**
|
|||
|
* Callback to invoke when text of editor changes.
|
|||
|
* @param {EditorTextChangeEvent} event - custom event.
|
|||
|
* @group Emits
|
|||
|
*/
|
|||
|
onTextChange = new EventEmitter();
|
|||
|
/**
|
|||
|
* Callback to invoke when selection of the text changes.
|
|||
|
* @param {EditorSelectionChangeEvent} event - custom event.
|
|||
|
* @group Emits
|
|||
|
*/
|
|||
|
onSelectionChange = new EventEmitter();
|
|||
|
templates;
|
|||
|
toolbar;
|
|||
|
value;
|
|||
|
delayedCommand = null;
|
|||
|
_readonly = false;
|
|||
|
onModelChange = () => { };
|
|||
|
onModelTouched = () => { };
|
|||
|
quill;
|
|||
|
dynamicQuill;
|
|||
|
headerTemplate;
|
|||
|
get isAttachedQuillEditorToDOM() {
|
|||
|
return this.quillElements?.editorElement?.isConnected;
|
|||
|
}
|
|||
|
quillElements;
|
|||
|
constructor(el, platformId) {
|
|||
|
this.el = el;
|
|||
|
this.platformId = platformId;
|
|||
|
/**
|
|||
|
* Read or write the DOM once, when initializing non-Angular (Quill) library.
|
|||
|
*/
|
|||
|
afterNextRender(() => {
|
|||
|
this.initQuillElements();
|
|||
|
this.initQuillEditor();
|
|||
|
});
|
|||
|
}
|
|||
|
ngAfterContentInit() {
|
|||
|
this.templates.forEach((item) => {
|
|||
|
switch (item.getType()) {
|
|||
|
case 'header':
|
|||
|
this.headerTemplate = item.template;
|
|||
|
break;
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
writeValue(value) {
|
|||
|
this.value = value;
|
|||
|
if (this.quill) {
|
|||
|
if (value) {
|
|||
|
const command = () => {
|
|||
|
this.quill.setContents(this.quill.clipboard.convert(this.value));
|
|||
|
};
|
|||
|
if (this.isAttachedQuillEditorToDOM) {
|
|||
|
command();
|
|||
|
}
|
|||
|
else {
|
|||
|
this.delayedCommand = command;
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
const command = () => {
|
|||
|
this.quill.setText('');
|
|||
|
};
|
|||
|
if (this.isAttachedQuillEditorToDOM) {
|
|||
|
command();
|
|||
|
}
|
|||
|
else {
|
|||
|
this.delayedCommand = command;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
registerOnChange(fn) {
|
|||
|
this.onModelChange = fn;
|
|||
|
}
|
|||
|
registerOnTouched(fn) {
|
|||
|
this.onModelTouched = fn;
|
|||
|
}
|
|||
|
getQuill() {
|
|||
|
return this.quill;
|
|||
|
}
|
|||
|
initQuillEditor() {
|
|||
|
if (isPlatformServer(this.platformId)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
/**
|
|||
|
* Importing Quill at top level, throws `document is undefined` error during when
|
|||
|
* building for SSR, so this dynamically loads quill when it's in browser module.
|
|||
|
*/
|
|||
|
if (!this.dynamicQuill) {
|
|||
|
import('quill')
|
|||
|
.then((quillModule) => {
|
|||
|
this.dynamicQuill = quillModule.default;
|
|||
|
this.createQuillEditor();
|
|||
|
})
|
|||
|
.catch((e) => console.error(e.message));
|
|||
|
}
|
|||
|
else {
|
|||
|
this.createQuillEditor();
|
|||
|
}
|
|||
|
}
|
|||
|
createQuillEditor() {
|
|||
|
this.initQuillElements();
|
|||
|
const { toolbarElement, editorElement } = this.quillElements;
|
|||
|
let defaultModule = { toolbar: toolbarElement };
|
|||
|
let modules = this.modules ? { ...defaultModule, ...this.modules } : defaultModule;
|
|||
|
this.quill = new this.dynamicQuill(editorElement, {
|
|||
|
modules: modules,
|
|||
|
placeholder: this.placeholder,
|
|||
|
readOnly: this.readonly,
|
|||
|
theme: 'snow',
|
|||
|
formats: this.formats,
|
|||
|
bounds: this.bounds,
|
|||
|
debug: this.debug,
|
|||
|
scrollingContainer: this.scrollingContainer
|
|||
|
});
|
|||
|
if (this.value) {
|
|||
|
this.quill.setContents(this.quill.clipboard.convert(this.value));
|
|||
|
}
|
|||
|
this.quill.on('text-change', (delta, oldContents, source) => {
|
|||
|
if (source === 'user') {
|
|||
|
let html = DomHandler.findSingle(editorElement, '.ql-editor').innerHTML;
|
|||
|
let text = this.quill.getText().trim();
|
|||
|
if (html === '<p><br></p>') {
|
|||
|
html = null;
|
|||
|
}
|
|||
|
this.onTextChange.emit({
|
|||
|
htmlValue: html,
|
|||
|
textValue: text,
|
|||
|
delta: delta,
|
|||
|
source: source
|
|||
|
});
|
|||
|
this.onModelChange(html);
|
|||
|
this.onModelTouched();
|
|||
|
}
|
|||
|
});
|
|||
|
this.quill.on('selection-change', (range, oldRange, source) => {
|
|||
|
this.onSelectionChange.emit({
|
|||
|
range: range,
|
|||
|
oldRange: oldRange,
|
|||
|
source: source
|
|||
|
});
|
|||
|
});
|
|||
|
this.onInit.emit({
|
|||
|
editor: this.quill
|
|||
|
});
|
|||
|
}
|
|||
|
initQuillElements() {
|
|||
|
if (!this.quillElements) {
|
|||
|
this.quillElements = {
|
|||
|
editorElement: DomHandler.findSingle(this.el.nativeElement, 'div.p-editor-content'),
|
|||
|
toolbarElement: DomHandler.findSingle(this.el.nativeElement, 'div.p-editor-toolbar')
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: Editor, deps: [{ token: i0.ElementRef }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
|
|||
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.7", type: Editor, selector: "p-editor", inputs: { style: "style", styleClass: "styleClass", placeholder: "placeholder", formats: "formats", modules: "modules", bounds: "bounds", scrollingContainer: "scrollingContainer", debug: "debug", readonly: "readonly" }, outputs: { onInit: "onInit", onTextChange: "onTextChange", onSelectionChange: "onSelectionChange" }, host: { classAttribute: "p-element" }, providers: [EDITOR_VALUE_ACCESSOR], queries: [{ propertyName: "toolbar", first: true, predicate: Header, descendants: true }, { propertyName: "templates", predicate: PrimeTemplate }], ngImport: i0, template: `
|
|||
|
<div [ngClass]="'p-editor-container'" [class]="styleClass">
|
|||
|
<div class="p-editor-toolbar" *ngIf="toolbar || headerTemplate">
|
|||
|
<ng-content select="p-header"></ng-content>
|
|||
|
<ng-container *ngTemplateOutlet="headerTemplate"></ng-container>
|
|||
|
</div>
|
|||
|
<div class="p-editor-toolbar" *ngIf="!toolbar && !headerTemplate">
|
|||
|
<span class="ql-formats">
|
|||
|
<select class="ql-header">
|
|||
|
<option value="1">Heading</option>
|
|||
|
<option value="2">Subheading</option>
|
|||
|
<option selected>Normal</option>
|
|||
|
</select>
|
|||
|
<select class="ql-font">
|
|||
|
<option selected>Sans Serif</option>
|
|||
|
<option value="serif">Serif</option>
|
|||
|
<option value="monospace">Monospace</option>
|
|||
|
</select>
|
|||
|
</span>
|
|||
|
<span class="ql-formats">
|
|||
|
<button class="ql-bold" aria-label="Bold" type="button"></button>
|
|||
|
<button class="ql-italic" aria-label="Italic" type="button"></button>
|
|||
|
<button class="ql-underline" aria-label="Underline" type="button"></button>
|
|||
|
</span>
|
|||
|
<span class="ql-formats">
|
|||
|
<select class="ql-color"></select>
|
|||
|
<select class="ql-background"></select>
|
|||
|
</span>
|
|||
|
<span class="ql-formats">
|
|||
|
<button class="ql-list" value="ordered" aria-label="Ordered List" type="button"></button>
|
|||
|
<button class="ql-list" value="bullet" aria-label="Unordered List" type="button"></button>
|
|||
|
<select class="ql-align">
|
|||
|
<option selected></option>
|
|||
|
<option value="center">center</option>
|
|||
|
<option value="right">right</option>
|
|||
|
<option value="justify">justify</option>
|
|||
|
</select>
|
|||
|
</span>
|
|||
|
<span class="ql-formats">
|
|||
|
<button class="ql-link" aria-label="Insert Link" type="button"></button>
|
|||
|
<button class="ql-image" aria-label="Insert Image" type="button"></button>
|
|||
|
<button class="ql-code-block" aria-label="Insert Code Block" type="button"></button>
|
|||
|
</span>
|
|||
|
<span class="ql-formats">
|
|||
|
<button class="ql-clean" aria-label="Remove Styles" type="button"></button>
|
|||
|
</span>
|
|||
|
</div>
|
|||
|
<div class="p-editor-content" [ngStyle]="style"></div>
|
|||
|
</div>
|
|||
|
`, isInline: true, styles: [".p-editor-container .p-editor-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options .ql-picker-item{width:auto;height:auto}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|||
|
}
|
|||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: Editor, decorators: [{
|
|||
|
type: Component,
|
|||
|
args: [{ selector: 'p-editor', template: `
|
|||
|
<div [ngClass]="'p-editor-container'" [class]="styleClass">
|
|||
|
<div class="p-editor-toolbar" *ngIf="toolbar || headerTemplate">
|
|||
|
<ng-content select="p-header"></ng-content>
|
|||
|
<ng-container *ngTemplateOutlet="headerTemplate"></ng-container>
|
|||
|
</div>
|
|||
|
<div class="p-editor-toolbar" *ngIf="!toolbar && !headerTemplate">
|
|||
|
<span class="ql-formats">
|
|||
|
<select class="ql-header">
|
|||
|
<option value="1">Heading</option>
|
|||
|
<option value="2">Subheading</option>
|
|||
|
<option selected>Normal</option>
|
|||
|
</select>
|
|||
|
<select class="ql-font">
|
|||
|
<option selected>Sans Serif</option>
|
|||
|
<option value="serif">Serif</option>
|
|||
|
<option value="monospace">Monospace</option>
|
|||
|
</select>
|
|||
|
</span>
|
|||
|
<span class="ql-formats">
|
|||
|
<button class="ql-bold" aria-label="Bold" type="button"></button>
|
|||
|
<button class="ql-italic" aria-label="Italic" type="button"></button>
|
|||
|
<button class="ql-underline" aria-label="Underline" type="button"></button>
|
|||
|
</span>
|
|||
|
<span class="ql-formats">
|
|||
|
<select class="ql-color"></select>
|
|||
|
<select class="ql-background"></select>
|
|||
|
</span>
|
|||
|
<span class="ql-formats">
|
|||
|
<button class="ql-list" value="ordered" aria-label="Ordered List" type="button"></button>
|
|||
|
<button class="ql-list" value="bullet" aria-label="Unordered List" type="button"></button>
|
|||
|
<select class="ql-align">
|
|||
|
<option selected></option>
|
|||
|
<option value="center">center</option>
|
|||
|
<option value="right">right</option>
|
|||
|
<option value="justify">justify</option>
|
|||
|
</select>
|
|||
|
</span>
|
|||
|
<span class="ql-formats">
|
|||
|
<button class="ql-link" aria-label="Insert Link" type="button"></button>
|
|||
|
<button class="ql-image" aria-label="Insert Image" type="button"></button>
|
|||
|
<button class="ql-code-block" aria-label="Insert Code Block" type="button"></button>
|
|||
|
</span>
|
|||
|
<span class="ql-formats">
|
|||
|
<button class="ql-clean" aria-label="Remove Styles" type="button"></button>
|
|||
|
</span>
|
|||
|
</div>
|
|||
|
<div class="p-editor-content" [ngStyle]="style"></div>
|
|||
|
</div>
|
|||
|
`, providers: [EDITOR_VALUE_ACCESSOR], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|||
|
class: 'p-element'
|
|||
|
}, styles: [".p-editor-container .p-editor-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options .ql-picker-item{width:auto;height:auto}\n"] }]
|
|||
|
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: undefined, decorators: [{
|
|||
|
type: Inject,
|
|||
|
args: [PLATFORM_ID]
|
|||
|
}] }], propDecorators: { style: [{
|
|||
|
type: Input
|
|||
|
}], styleClass: [{
|
|||
|
type: Input
|
|||
|
}], placeholder: [{
|
|||
|
type: Input
|
|||
|
}], formats: [{
|
|||
|
type: Input
|
|||
|
}], modules: [{
|
|||
|
type: Input
|
|||
|
}], bounds: [{
|
|||
|
type: Input
|
|||
|
}], scrollingContainer: [{
|
|||
|
type: Input
|
|||
|
}], debug: [{
|
|||
|
type: Input
|
|||
|
}], readonly: [{
|
|||
|
type: Input
|
|||
|
}], onInit: [{
|
|||
|
type: Output
|
|||
|
}], onTextChange: [{
|
|||
|
type: Output
|
|||
|
}], onSelectionChange: [{
|
|||
|
type: Output
|
|||
|
}], templates: [{
|
|||
|
type: ContentChildren,
|
|||
|
args: [PrimeTemplate]
|
|||
|
}], toolbar: [{
|
|||
|
type: ContentChild,
|
|||
|
args: [Header]
|
|||
|
}] } });
|
|||
|
class EditorModule {
|
|||
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: EditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|||
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.7", ngImport: i0, type: EditorModule, declarations: [Editor], imports: [CommonModule], exports: [Editor, SharedModule] });
|
|||
|
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: EditorModule, imports: [CommonModule, SharedModule] });
|
|||
|
}
|
|||
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: EditorModule, decorators: [{
|
|||
|
type: NgModule,
|
|||
|
args: [{
|
|||
|
imports: [CommonModule],
|
|||
|
exports: [Editor, SharedModule],
|
|||
|
declarations: [Editor]
|
|||
|
}]
|
|||
|
}] });
|
|||
|
|
|||
|
/**
|
|||
|
* Generated bundle index. Do not edit.
|
|||
|
*/
|
|||
|
|
|||
|
export { EDITOR_VALUE_ACCESSOR, Editor, EditorModule };
|
|||
|
//# sourceMappingURL=primeng-editor.mjs.map
|