UNPKG

omii-ui

Version:

使用OMII开发的WebComponents库,样式采用bootstrap。可以作为标准的esmodule使用

327 lines (313 loc) 9.35 kB
const { h, classNames, extractClass } = omii; import uiBase from "../uiBase"; import css from "./index.scss"; import { getCSSStyleSheets } from "../css"; //min.js let min = true; let root = new URL(`./tinymce/`, import.meta.url).href; let jsFile = `./tinymce.js`; export default class extends uiBase { static css = [() => getCSSStyleSheets("reboot", "scrollbar"), css]; static propTypes = { value: String, placeholder: String, required: Boolean, inline: Boolean, readonly: Boolean, }; static defaultProps = { //编辑器引擎 value: "", isEmpty(value) { if (typeof value != "string") { return true; } return value == ""; }, relativeUrls: null, width: null, height: null, minWidth: null, minHeight: null, maxWidth: null, maxHeight: null, resize: true, placeholder: "...", readonly: false, required: false, language: "zh-Hans", directionality: null, plugins: "preview importcss searchreplace autolink autosave save directionality code visualblocks visualchars fullscreen image link media template codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help charmap quickbars emoticons", toolbar: "undo redo searchreplace | bold italic underline strikethrough subscript superscript | fontfamily fontsize blocks styles lineheight | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | forecolor backcolor removeformat | pagebreak hr insertdatetime | selectall cut copy paste pastetext |charmap emoticons | quickimage quicktable |insertfile image media table template link unlink anchor codesample | ltr rtl | visualblocks wordcount code fullscreen preview print", toolbarSticky: true, toolbarMode: "wrap", menu: null, menubar: false, inline: false, contentCss: null, contentStyle: null, blockFormats: "Div=div;Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6;Preformatted=pre", fontFamilyFormats: "宋体=宋体;仿宋=仿宋;楷体=楷体;微软雅黑=微软雅黑;黑体=黑体;隶书=隶书;Andale Mono=andale mono,times; Arial=arial,helvetica,sans-serif; Arial Black=arial black,avant garde; Book Antiqua=book antiqua,palatino; Comic Sans MS=comic sans ms,sans-serif; Courier New=courier new,courier; Georgia=georgia,palatino; Helvetica=helvetica; Impact=impact,chicago; Symbol=symbol; Tahoma=tahoma,arial,helvetica,sans-serif; Terminal=terminal,monaco; Times New Roman=times new roman,times; Trebuchet MS=trebuchet ms,geneva; Verdana=verdana,geneva; Webdings=webdings; Wingdings=wingdings,zapf dingbats", fontSizeFormats: null, lineHeightFormats: null, indentation: null, indentUseMargin: false, styleFormatsMerge: true, styleFormats: null, colorCols: 5, colorMap: null, imagesUploadUrl: null, imagesUploadHandler: null, imagesUploadBasePath: null, imagesUploadCredentials: false, imagesReuseFilename: false, imagesFileTypes: null, imageList: null, imageAdvtab: true, imageUploadtab: false, imageDimensions: true, imageTitle: true, imagePrependUrl: null, imageBatch: false, automaticUploads: true, filePickerTypes: null, filePickerCallback: null, templates: null, importcssAppend: true, importcssGroups: [ { title: "Table styles", filter: /^(td|tr)\./ }, // td.class and tr.class { title: "Block styles", filter: /^(div|p)\./ }, // div.class and p.class { title: "Other styles" }, // The rest ], }; static get min() { return min; } static set min(value) { min = value; } static get root() { return root; } static set root(value) { root = value; } static get jsFile() { return jsFile; } static set jsFile(value) { jsFile = value; } static async use() { return await import(new URL(this.jsFile, this.root).href); } get value() { return this.$props.value; } set value(value) { this.$props.value = value; if (this.editor && this.#ready) { try { this.editor.setContent(value); } catch (exc) { console.log("editor not init"); } } //这里不能fire change,这样容易引起循环调用 //监控change的控件可能会继续调用update //this.fire("change", { value }); } #editor; get editor() { return this.#editor; } #css; css() { return this.#css; } get validity() { const { required, isEmpty } = this.$props; const result = { valid: true, }; if (required && isEmpty(this.value)) { result.valid = false; result.valueMissing = true; } return result; } //已经检查过有效性 #checked = false; /** * 验证 * @returns {boolean} */ checkValidity() { this.#checked = true; const valid = this.validity.valid; if (!valid) { this.classList.add("is-invalid"); } else { this.classList.remove("is-invalid"); } return valid; } /** * 获取编辑器Id */ get editorId() { return `editor${this.elementId}`; } #ready = false; async installed() { // console.log("tiny installed"); //允许验证 this.dataset.validate = true; await this.constructor.use(); const $editor = this.$(`#${this.editorId}`); const { menu, menubar, toolbar, plugins, language, toolbarMode, baseUrl, inline, readonly, contentStyle, contentCss, fontFamilyFormats, blockFormats, fontSizeFormats, lineHeightFormats, indentUseMargin, indentation, styleFormats, styleFormatsMerge, colorCols, colorMap, imagesUploadUrl, imagesUploadHandler, imagesUploadBasePath, imagesUploadCredentials, imagesReuseFilename, imagesFileTypes, imageList, imageBatch, imageAdvtab, imageUploadtab, imageDimensions, imageTitle, imagePrependUrl, relativeUrls, automaticUploads, filePickerTypes, filePickerCallback, templates, importcssGroups, importcssAppend, width, height, minWidth, minHeight, maxWidth, maxHeight, resize, placeholder, setup, ...options } = this.$props; tinymce.init({ target: $editor, promotion: false, base_url: baseUrl ?? this.constructor.root, menu, menubar, toolbar, toolbar_mode: toolbarMode, plugins, language, inline, readonly, extended_valid_elements: "oi-icon[name|color|size]", custom_elements: "oi-icon", content_css: contentCss, content_style: contentStyle, font_family_formats: fontFamilyFormats, block_formats: blockFormats, font_size_formats: fontSizeFormats, line_height_formats: lineHeightFormats, indent_use_margin: indentUseMargin, indentation, style_formats: styleFormats, style_formats_merge: styleFormatsMerge, color_cols: colorCols, color_map: colorMap, images_upload_url: imagesUploadUrl, images_upload_handler: imagesUploadHandler, images_upload_base_path: imagesUploadBasePath, images_upload_credentials: imagesUploadCredentials, images_reuse_filename: imagesReuseFilename, images_file_types: imagesFileTypes, image_list: imageList, image_advtab: imageAdvtab, image_uploadtab: imageUploadtab, image_dimensions: imageDimensions, image_title: imageTitle, image_prepend_url: imagePrependUrl, automatic_uploads: automaticUploads, file_picker_types: filePickerTypes, file_picker_callback: filePickerCallback, importcss_groups: importcssGroups, templates, importcss_append: importcssAppend, width, height, min_width: minWidth, min_height: minHeight, max_width: maxWidth, max_height: maxHeight, relative_urls: relativeUrls, resize, placeholder, ...options, setup: (editor) => { this.#editor = editor; this.fire("setup", { editor }); editor.on("init", (e) => { this.#ready = true; this.fire("ready"); }); editor.on("blur", (e) => { console.log("editor blur"); }); editor.on("change", (e) => { this.$props.value = editor.getContent(); this.fire("change", { value: this.value }); }); }, }); } render() { const { inline } = this.$props; return inline ? ( <div> <div class="editor" id={this.editorId}> {this.value} </div> </div> ) : ( <textarea class="editor" id={this.editorId} value={this.value} placeholder={this.placeholder} ></textarea> ); } }