添加插入表情及特殊符号菜单
This commit is contained in:
@@ -55,6 +55,9 @@ import { Link } from "./menus/toolbar/insert/Link.ts";
|
|||||||
import { Image } from "./menus/toolbar/insert/Image.ts";
|
import { Image } from "./menus/toolbar/insert/Image.ts";
|
||||||
import { Video } from "./menus/toolbar/insert/Video.ts";
|
import { Video } from "./menus/toolbar/insert/Video.ts";
|
||||||
import { Audio } from "./menus/toolbar/insert/Audio.ts";
|
import { Audio } from "./menus/toolbar/insert/Audio.ts";
|
||||||
|
import { HardBreak } from "./menus/toolbar/insert/HardBreak.ts";
|
||||||
|
import { Emoji } from "./menus/toolbar/insert/Emoji.ts";
|
||||||
|
import { Symbol } from "./menus/toolbar/insert/Symbol.ts";
|
||||||
|
|
||||||
// 注册组件
|
// 注册组件
|
||||||
defineCustomElement('uai-editor-header', Header);
|
defineCustomElement('uai-editor-header', Header);
|
||||||
@@ -111,3 +114,6 @@ defineCustomElement('uai-editor-insert-menu-link', Link);
|
|||||||
defineCustomElement('uai-editor-insert-menu-image', Image);
|
defineCustomElement('uai-editor-insert-menu-image', Image);
|
||||||
defineCustomElement('uai-editor-insert-menu-video', Video);
|
defineCustomElement('uai-editor-insert-menu-video', Video);
|
||||||
defineCustomElement('uai-editor-insert-menu-audio', Audio);
|
defineCustomElement('uai-editor-insert-menu-audio', Audio);
|
||||||
|
defineCustomElement('uai-editor-insert-menu-hard-break', HardBreak);
|
||||||
|
defineCustomElement('uai-editor-insert-menu-emoji', Emoji);
|
||||||
|
defineCustomElement('uai-editor-insert-menu-symbol', Symbol);
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ import { Link } from "./insert/Link.ts";
|
|||||||
import { Image } from "./insert/Image.ts";
|
import { Image } from "./insert/Image.ts";
|
||||||
import { Video } from "./insert/Video.ts";
|
import { Video } from "./insert/Video.ts";
|
||||||
import { Audio } from "./insert/Audio.ts";
|
import { Audio } from "./insert/Audio.ts";
|
||||||
|
import { HardBreak } from "./insert/HardBreak.ts";
|
||||||
|
import { Emoji } from "./insert/Emoji.ts";
|
||||||
|
import { Symbol } from "./insert/Symbol.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 传统菜单栏
|
* 传统菜单栏
|
||||||
@@ -111,6 +114,9 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
|
|||||||
insertMenuImage!: Image;
|
insertMenuImage!: Image;
|
||||||
insertMenuVideo!: Video;
|
insertMenuVideo!: Video;
|
||||||
insertMenuAudio!: Audio;
|
insertMenuAudio!: Audio;
|
||||||
|
insertMenuHardBreak!: HardBreak;
|
||||||
|
insertMenuEmoji!: Emoji;
|
||||||
|
insertMenuSymbol!: Symbol;
|
||||||
|
|
||||||
constructor(defaultToolbarMenus: Record<string, any>[]) {
|
constructor(defaultToolbarMenus: Record<string, any>[]) {
|
||||||
super();
|
super();
|
||||||
@@ -292,6 +298,15 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
|
|||||||
|
|
||||||
this.insertMenuAudio = new Audio({ menuType: "button", enable: true, header: "classic", hideText: false });
|
this.insertMenuAudio = new Audio({ menuType: "button", enable: true, header: "classic", hideText: false });
|
||||||
this.eventComponents.push(this.insertMenuAudio);
|
this.eventComponents.push(this.insertMenuAudio);
|
||||||
|
|
||||||
|
this.insertMenuHardBreak = new HardBreak({ menuType: "button", enable: true, header: "classic", hideText: false });
|
||||||
|
this.eventComponents.push(this.insertMenuHardBreak);
|
||||||
|
|
||||||
|
this.insertMenuEmoji = new Emoji({ menuType: "popup", enable: true, header: "classic", hideText: false });
|
||||||
|
this.eventComponents.push(this.insertMenuEmoji);
|
||||||
|
|
||||||
|
this.insertMenuSymbol = new Symbol({ menuType: "popup", enable: true, header: "classic", hideText: false });
|
||||||
|
this.eventComponents.push(this.insertMenuSymbol);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 创建基础菜单
|
* 创建基础菜单
|
||||||
@@ -373,5 +388,12 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
|
|||||||
group1.appendChild(this.insertMenuImage);
|
group1.appendChild(this.insertMenuImage);
|
||||||
group1.appendChild(this.insertMenuVideo);
|
group1.appendChild(this.insertMenuVideo);
|
||||||
group1.appendChild(this.insertMenuAudio);
|
group1.appendChild(this.insertMenuAudio);
|
||||||
|
|
||||||
|
const group2 = document.createElement("div");
|
||||||
|
group2.classList.add("uai-classic-virtual-group");
|
||||||
|
this.classicMenuInsertGroup.appendChild(group2);
|
||||||
|
group2.appendChild(this.insertMenuHardBreak);
|
||||||
|
group2.appendChild(this.insertMenuEmoji);
|
||||||
|
group2.appendChild(this.insertMenuSymbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,6 +52,9 @@ import { Link } from "./insert/Link.ts";
|
|||||||
import { Image } from "./insert/Image.ts";
|
import { Image } from "./insert/Image.ts";
|
||||||
import { Video } from "./insert/Video.ts";
|
import { Video } from "./insert/Video.ts";
|
||||||
import { Audio } from "./insert/Audio.ts";
|
import { Audio } from "./insert/Audio.ts";
|
||||||
|
import { HardBreak } from "./insert/HardBreak.ts";
|
||||||
|
import { Emoji } from "./insert/Emoji.ts";
|
||||||
|
import { Symbol } from "./insert/Symbol.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 经典菜单栏
|
* 经典菜单栏
|
||||||
@@ -114,6 +117,9 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
|
|||||||
insertMenuImage!: Image;
|
insertMenuImage!: Image;
|
||||||
insertMenuVideo!: Video;
|
insertMenuVideo!: Video;
|
||||||
insertMenuAudio!: Audio;
|
insertMenuAudio!: Audio;
|
||||||
|
insertMenuHardBreak!: HardBreak;
|
||||||
|
insertMenuEmoji!: Emoji;
|
||||||
|
insertMenuSymbol!: Symbol;
|
||||||
|
|
||||||
constructor(defaultToolbarMenus: Record<string, any>[]) {
|
constructor(defaultToolbarMenus: Record<string, any>[]) {
|
||||||
super();
|
super();
|
||||||
@@ -315,6 +321,15 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
|
|||||||
|
|
||||||
this.insertMenuAudio = new Audio({ menuType: "button", enable: true, huge: true });
|
this.insertMenuAudio = new Audio({ menuType: "button", enable: true, huge: true });
|
||||||
this.eventComponents.push(this.insertMenuAudio);
|
this.eventComponents.push(this.insertMenuAudio);
|
||||||
|
|
||||||
|
this.insertMenuHardBreak = new HardBreak({ menuType: "button", enable: true, huge: true });
|
||||||
|
this.eventComponents.push(this.insertMenuHardBreak);
|
||||||
|
|
||||||
|
this.insertMenuEmoji = new Emoji({ menuType: "popup", enable: true, huge: true, hideText: false });
|
||||||
|
this.eventComponents.push(this.insertMenuEmoji);
|
||||||
|
|
||||||
|
this.insertMenuSymbol = new Symbol({ menuType: "popup", enable: true, huge: true, hideText: false });
|
||||||
|
this.eventComponents.push(this.insertMenuSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -470,5 +485,12 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
|
|||||||
group1.appendChild(this.insertMenuImage);
|
group1.appendChild(this.insertMenuImage);
|
||||||
group1.appendChild(this.insertMenuVideo);
|
group1.appendChild(this.insertMenuVideo);
|
||||||
group1.appendChild(this.insertMenuAudio);
|
group1.appendChild(this.insertMenuAudio);
|
||||||
|
|
||||||
|
const group2 = document.createElement("div");
|
||||||
|
group2.classList.add("uai-ribbon-virtual-group");
|
||||||
|
this.ribbonMenuInsertGroup.appendChild(group2);
|
||||||
|
group2.appendChild(this.insertMenuHardBreak);
|
||||||
|
group2.appendChild(this.insertMenuEmoji);
|
||||||
|
group2.appendChild(this.insertMenuSymbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
// Copyright (c) 2024-present AI-Labs
|
||||||
|
|
||||||
|
// @ ts-nocheck
|
||||||
|
import { MenuButton, MenuButtonOptions } from "../../MenuButton.ts";
|
||||||
|
import icon from "../../../../assets/icons/emoji.svg";
|
||||||
|
import { t } from "i18next";
|
||||||
|
import { UAIEditorEventListener, UAIEditorOptions } from "../../../../core/UAIEditor.ts";
|
||||||
|
import { EditorEvents } from "@tiptap/core";
|
||||||
|
import tippy, { Instance, Props } from "tippy.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入菜单:插入表情
|
||||||
|
*/
|
||||||
|
export class Emoji extends HTMLElement implements UAIEditorEventListener {
|
||||||
|
// 按钮选项
|
||||||
|
menuButtonOptions: MenuButtonOptions = {
|
||||||
|
menuType: "popup",
|
||||||
|
enable: true,
|
||||||
|
icon: icon,
|
||||||
|
hideText: true,
|
||||||
|
text: t('insert.emoji'),
|
||||||
|
tooltip: t('insert.emoji'),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 功能按钮
|
||||||
|
menuButton: MenuButton;
|
||||||
|
// 选项提示实例
|
||||||
|
tippyInstance!: Instance<Props>;
|
||||||
|
|
||||||
|
constructor(options: MenuButtonOptions) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// 初始化功能按钮选项
|
||||||
|
this.menuButtonOptions = { ...this.menuButtonOptions, ...options };
|
||||||
|
|
||||||
|
// 创建功能按钮
|
||||||
|
this.menuButton = new MenuButton(this.menuButtonOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义创建方法
|
||||||
|
* @param event
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
onCreate(event: EditorEvents["create"], options: UAIEditorOptions) {
|
||||||
|
this.menuButton.onCreate(event, options);
|
||||||
|
this.appendChild(this.menuButton);
|
||||||
|
|
||||||
|
// 创建表情选择提示框
|
||||||
|
if (this.menuButtonOptions.enable && this.menuButton.menuButtonArrow) {
|
||||||
|
this.tippyInstance = tippy(this.menuButton.menuButton, {
|
||||||
|
content: this.createContainer(event, options),
|
||||||
|
appendTo: 'parent',
|
||||||
|
placement: 'bottom',
|
||||||
|
trigger: 'click',
|
||||||
|
interactive: true,
|
||||||
|
arrow: false,
|
||||||
|
onShow: () => {
|
||||||
|
this.menuButton.tippyInstance?.disable();
|
||||||
|
},
|
||||||
|
onHidden: () => {
|
||||||
|
this.menuButton.tippyInstance?.enable();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义Transaction监听方法
|
||||||
|
* @param event
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) {
|
||||||
|
this.menuButton.onTransaction(event, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
onEditableChange(editable: boolean) {
|
||||||
|
this.menuButtonOptions.enable = editable;
|
||||||
|
this.menuButton.onEditableChange(editable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建表情选择容器
|
||||||
|
* @param event
|
||||||
|
* @param options
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
createContainer(event: EditorEvents["create"], options: UAIEditorOptions) {
|
||||||
|
const container = document.createElement("div");
|
||||||
|
container.classList.add("uai-emojis-container");
|
||||||
|
// 添加所有可选表情
|
||||||
|
options.dicts?.emojis?.forEach(emoji => {
|
||||||
|
const groupTitle = document.createElement("div");
|
||||||
|
groupTitle.classList.add("uai-emojis-group-title");
|
||||||
|
groupTitle.innerHTML = emoji.label;
|
||||||
|
container.appendChild(groupTitle);
|
||||||
|
const groupContainer = document.createElement("div");
|
||||||
|
groupContainer.classList.add("uai-emojis-group-container");
|
||||||
|
container.appendChild(groupContainer);
|
||||||
|
emoji.value.toString().split(" ").forEach(item => {
|
||||||
|
const it = document.createElement("div");
|
||||||
|
it.classList.add("uai-emojis-group-item");
|
||||||
|
it.innerHTML = item;
|
||||||
|
groupContainer.appendChild(it);
|
||||||
|
it.addEventListener("click", () => {
|
||||||
|
event.editor.chain().focus().insertContent(item).run();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// Copyright (c) 2024-present AI-Labs
|
||||||
|
|
||||||
|
// @ ts-nocheck
|
||||||
|
import { MenuButton, MenuButtonOptions } from "../../MenuButton.ts";
|
||||||
|
import icon from "../../../../assets/icons/hard-break.svg";
|
||||||
|
import { t } from "i18next";
|
||||||
|
import { UAIEditorEventListener, UAIEditorOptions } from "../../../../core/UAIEditor.ts";
|
||||||
|
import { EditorEvents } from "@tiptap/core";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入菜单:插入换行
|
||||||
|
*/
|
||||||
|
export class HardBreak extends HTMLElement implements UAIEditorEventListener {
|
||||||
|
// 按钮选项
|
||||||
|
menuButtonOptions: MenuButtonOptions = {
|
||||||
|
menuType: "button",
|
||||||
|
enable: true,
|
||||||
|
icon: icon,
|
||||||
|
hideText: false,
|
||||||
|
text: t('insert.hardBreak'),
|
||||||
|
tooltip: t('insert.hardBreak'),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 功能按钮
|
||||||
|
menuButton: MenuButton;
|
||||||
|
|
||||||
|
constructor(options: MenuButtonOptions) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// 初始化功能按钮选项
|
||||||
|
this.menuButtonOptions = { ...this.menuButtonOptions, ...options };
|
||||||
|
|
||||||
|
// 创建功能按钮
|
||||||
|
this.menuButton = new MenuButton(this.menuButtonOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义创建方法
|
||||||
|
* @param event
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
onCreate(event: EditorEvents["create"], options: UAIEditorOptions) {
|
||||||
|
this.menuButton.onCreate(event, options);
|
||||||
|
this.appendChild(this.menuButton);
|
||||||
|
|
||||||
|
// 定义按钮点击事件,插入换行
|
||||||
|
this.addEventListener("click", () => {
|
||||||
|
if (this.menuButtonOptions.enable) {
|
||||||
|
event.editor.chain().focus().setHardBreak().run();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义Transaction监听方法
|
||||||
|
* @param event
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) {
|
||||||
|
this.menuButton.onTransaction(event, options);
|
||||||
|
if (this.menuButton.menuButton) {
|
||||||
|
var disable = event.editor.isEditable;
|
||||||
|
this.onEditableChange(disable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onEditableChange(editable: boolean) {
|
||||||
|
this.menuButtonOptions.enable = editable;
|
||||||
|
this.menuButton.onEditableChange(editable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
// Copyright (c) 2024-present AI-Labs
|
||||||
|
|
||||||
|
// @ ts-nocheck
|
||||||
|
import { MenuButton, MenuButtonOptions } from "../../MenuButton.ts";
|
||||||
|
import icon from "../../../../assets/icons/symbol.svg";
|
||||||
|
import { t } from "i18next";
|
||||||
|
import { UAIEditorEventListener, UAIEditorOptions } from "../../../../core/UAIEditor.ts";
|
||||||
|
import { EditorEvents } from "@tiptap/core";
|
||||||
|
import tippy, { Instance, Props } from "tippy.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入菜单:插入符号
|
||||||
|
*/
|
||||||
|
export class Symbol extends HTMLElement implements UAIEditorEventListener {
|
||||||
|
// 按钮选项
|
||||||
|
menuButtonOptions: MenuButtonOptions = {
|
||||||
|
menuType: "popup",
|
||||||
|
enable: true,
|
||||||
|
icon: icon,
|
||||||
|
hideText: true,
|
||||||
|
text: t('insert.symbol'),
|
||||||
|
tooltip: t('insert.symbol'),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 功能按钮
|
||||||
|
menuButton: MenuButton;
|
||||||
|
// 选项提示实例
|
||||||
|
tippyInstance!: Instance<Props>;
|
||||||
|
|
||||||
|
constructor(options: MenuButtonOptions) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// 初始化功能按钮选项
|
||||||
|
this.menuButtonOptions = { ...this.menuButtonOptions, ...options };
|
||||||
|
|
||||||
|
// 创建功能按钮
|
||||||
|
this.menuButton = new MenuButton(this.menuButtonOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义创建方法
|
||||||
|
* @param event
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
onCreate(event: EditorEvents["create"], options: UAIEditorOptions) {
|
||||||
|
this.menuButton.onCreate(event, options);
|
||||||
|
this.appendChild(this.menuButton);
|
||||||
|
|
||||||
|
// 初始化特殊符号选项提示框
|
||||||
|
if (this.menuButtonOptions.enable && this.menuButton.menuButtonArrow) {
|
||||||
|
this.tippyInstance = tippy(this.menuButton.menuButton, {
|
||||||
|
content: this.createContainer(event, options),
|
||||||
|
appendTo: 'parent',
|
||||||
|
placement: 'bottom',
|
||||||
|
trigger: 'click',
|
||||||
|
interactive: true,
|
||||||
|
arrow: false,
|
||||||
|
onShow: () => {
|
||||||
|
this.menuButton.tippyInstance?.disable();
|
||||||
|
},
|
||||||
|
onHidden: () => {
|
||||||
|
this.menuButton.tippyInstance?.enable();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定义Transaction监听方法
|
||||||
|
* @param event
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) {
|
||||||
|
this.menuButton.onTransaction(event, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
onEditableChange(editable: boolean) {
|
||||||
|
this.menuButtonOptions.enable = editable;
|
||||||
|
this.menuButton.onEditableChange(editable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建特殊符号选择提示框
|
||||||
|
* @param event
|
||||||
|
* @param options
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
createContainer(event: EditorEvents["create"], options: UAIEditorOptions) {
|
||||||
|
const container = document.createElement("div");
|
||||||
|
container.classList.add("uai-emojis-container");
|
||||||
|
// 添加所有可选的特殊符号
|
||||||
|
options.dicts?.symbols?.forEach(symbol => {
|
||||||
|
const groupTitle = document.createElement("div");
|
||||||
|
groupTitle.classList.add("uai-emojis-group-title");
|
||||||
|
groupTitle.innerHTML = symbol.label;
|
||||||
|
container.appendChild(groupTitle);
|
||||||
|
const groupContainer = document.createElement("div");
|
||||||
|
groupContainer.classList.add("uai-emojis-group-container");
|
||||||
|
container.appendChild(groupContainer);
|
||||||
|
symbol.value.toString().split("").forEach(item => {
|
||||||
|
const it = document.createElement("div");
|
||||||
|
it.classList.add("uai-emojis-group-item");
|
||||||
|
it.innerHTML = item;
|
||||||
|
groupContainer.appendChild(it);
|
||||||
|
it.addEventListener("click", () => {
|
||||||
|
event.editor.chain().focus().insertContent(item).run();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user