ngx-tinymce
Version:
Angular for tinymce
246 lines (240 loc) • 10.7 kB
JavaScript
import * as i0 from '@angular/core';
import { inject, signal, input, booleanAttribute, TemplateRef, numberAttribute, output, afterNextRender, effect, forwardRef, ChangeDetectionStrategy, ViewEncapsulation, Component, makeEnvironmentProviders } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { NuLazyService } from '@ng-util/lazy';
import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
class TinymceOptions {
/** 指定tinymce目录路径,默认:`./assets/tinymce/` */
baseURL = './assets/tinymce/';
/** 指定tinymce文件名,默认:`tinymce.min.js` */
fileName = 'tinymce.min.js';
/** 默认配置项,对全局 Tinymce 有效 */
config;
/** 延迟加载(单位:毫秒),默认:`0` */
delay;
}
const isSSR = !(typeof document === 'object' && !!document);
/**
* Angular for tinymce, You can modify the global configuration via `provideTinymce`
*/
class TinymceComponent {
defConfig = inject(TinymceOptions, { optional: true });
lazySrv = inject(NuLazyService);
doc = inject(DOCUMENT);
_instance;
value = '';
load = signal(true, { ...(ngDevMode ? { debugName: "load" } : {}) });
id = `_tinymce-${Math.random().toString(36).substring(2)}`;
onChange;
onTouched;
config = input(null, { ...(ngDevMode ? { debugName: "config" } : {}) });
placeholder = input('', { ...(ngDevMode ? { debugName: "placeholder" } : {}) });
inline = input(false, { ...(ngDevMode ? { debugName: "inline" } : {}), transform: booleanAttribute });
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : {}), transform: booleanAttribute });
_disabled = signal(false, { ...(ngDevMode ? { debugName: "_disabled" } : {}) });
_loading = signal(null, { ...(ngDevMode ? { debugName: "_loading" } : {}) });
_loadingTpl = signal(null, { ...(ngDevMode ? { debugName: "_loadingTpl" } : {}) });
loading = input(null, { ...(ngDevMode ? { debugName: "loading" } : {}), transform: (value) => {
if (value instanceof TemplateRef) {
this._loading.set(null);
this._loadingTpl.set(value);
}
else {
this._loading.set(value);
}
return value;
} });
/** 延迟初始化 */
delay = input(0, { ...(ngDevMode ? { debugName: "delay" } : {}), transform: numberAttribute });
ready = output();
get instance() {
return this._instance;
}
constructor() {
afterNextRender(() => {
if (isSSR) {
return;
}
// 已经存在对象无须进入懒加载模式
if (this.win.tinymce) {
this.initDelay();
return;
}
const { defConfig } = this;
const baseURL = defConfig && defConfig.baseURL;
const fileName = defConfig && defConfig.fileName;
const url = (baseURL ?? './assets/tinymce/') + (fileName ?? 'tinymce.min.js');
this.lazySrv.monitor(url).subscribe(() => this.initDelay());
this.lazySrv.load(url);
});
effect(() => {
const cfg = this.config();
if (!this._instance)
return;
this.destroy();
if (cfg)
this.initDelay();
});
}
get win() {
return this.doc.defaultView ?? window;
}
initDelay() {
if (isSSR) {
return;
}
setTimeout(() => this.init(), Math.max(0, this.delay()));
}
init() {
const win = this.win;
if (!win.tinymce) {
throw new Error('tinymce js文件加载失败');
}
const { defConfig, config, id, inline } = this;
if (this._instance) {
return;
}
if (defConfig?.baseURL) {
let url = '' + defConfig.baseURL;
if (url.endsWith('/')) {
url = url.substring(0, url.length - 1);
}
win.tinymce.baseURL = url;
}
const userOptions = { ...defConfig?.config, ...config() };
const options = {
selector: `#` + id,
inline: inline(),
...defConfig?.config,
...config(),
setup: (editor) => {
this._instance = editor;
if (this.onChange) {
editor.on('change keyup', () => {
this.value = editor.getContent();
this.onChange(this.value);
});
}
if (typeof userOptions.setup === 'function') {
userOptions.setup(editor);
}
},
init_instance_callback: (editor) => {
if (editor && this.value) {
editor.setContent(this.value);
}
this.setDisabled();
if (typeof userOptions.init_instance_callback === 'function') {
userOptions.init_instance_callback(editor);
}
this.ready.emit(editor);
},
};
if (userOptions.auto_focus) {
options.auto_focus = id;
}
win.tinymce.init(options);
this.load.set(false);
}
destroy() {
if (this._instance == null) {
return;
}
this._instance.off();
this._instance.remove();
this._instance = null;
}
setDisabled() {
if (!this._instance) {
return;
}
const mode = this.disabled() || this._disabled() ? 'readonly' : 'design';
// Compatible with 5
const setMode5 = this._instance.setMode;
if (typeof setMode5 === 'function') {
setMode5(mode);
}
else {
this._instance.mode.set(mode);
}
}
ngOnDestroy() {
this.destroy();
}
writeValue(value) {
// value should be NOT NULL
this.value = value ?? '';
this._instance?.setContent(this.value);
}
registerOnChange(fn) {
this.onChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
setDisabledState(isDisabled) {
this._disabled.set(isDisabled);
this.setDisabled();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: TinymceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.1", type: TinymceComponent, isStandalone: true, selector: "tinymce", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, inline: { classPropertyName: "inline", publicName: "inline", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { ready: "ready" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TinymceComponent),
multi: true,
},
], exportAs: ["tinymce"], ngImport: i0, template: `
(inline()) {
<div [attr.id]="id"><ng-content /></div>
} {
<textarea [attr.id]="id" [attr.placeholder]="placeholder()" class="tinymce-selector"></textarea>
} (load()) {
<div class="loading">
(_loading()) {
{{ _loading() }}
} {
<ng-template [ngTemplateOutlet]="_loadingTpl()" />
}
</div>
}
`, isInline: true, styles: ["tinymce .tinymce-selector{display:none}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.1", ngImport: i0, type: TinymceComponent, decorators: [{
type: Component,
args: [{ selector: 'tinymce', exportAs: 'tinymce', template: `
(inline()) {
<div [attr.id]="id"><ng-content /></div>
} {
<textarea [attr.id]="id" [attr.placeholder]="placeholder()" class="tinymce-selector"></textarea>
} (load()) {
<div class="loading">
(_loading()) {
{{ _loading() }}
} {
<ng-template [ngTemplateOutlet]="_loadingTpl()" />
}
</div>
}
`, imports: [NgTemplateOutlet], providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TinymceComponent),
multi: true,
},
], preserveWhitespaces: false, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: ["tinymce .tinymce-selector{display:none}\n"] }]
}], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], inline: [{ type: i0.Input, args: [{ isSignal: true, alias: "inline", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], ready: [{ type: i0.Output, args: ["ready"] }] } });
/**
* Sets up providers necessary to config for the Tinymce.
* @example
* bootstrapApplication(AppComponent, {
* providers: [provideTinymce({baseURL: '//cdn.tiny.cloud/1/no-api-key/tinymce/6/'})]
* });
*/
function provideTinymce(options) {
return makeEnvironmentProviders([{ provide: TinymceOptions, useValue: options }]);
}
/**
* Generated bundle index. Do not edit.
*/
export { TinymceComponent, TinymceOptions, provideTinymce };
//# sourceMappingURL=ngx-tinymce.mjs.map