界面优化

This commit is contained in:
wux_labs
2025-03-09 23:44:02 +08:00
parent 5502be0f9e
commit 033c0ffdbf
13 changed files with 747 additions and 474 deletions

View File

@@ -5,6 +5,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>有爱文档UAI Editor</title> <title>有爱文档UAI Editor</title>
<link rel="icon" href="/favicon.png" /> <link rel="icon" href="/favicon.png" />
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
</head> </head>
<body> <body>
<div id="uai-editor" style="height: 100vh; overflow: hidden; border: solid 1px var(--uai-border-color)"></div> <div id="uai-editor" style="height: 100vh; overflow: hidden; border: solid 1px var(--uai-border-color)"></div>

20
package-lock.json generated
View File

@@ -43,7 +43,6 @@
"@types/file-saver": "^2.0.7", "@types/file-saver": "^2.0.7",
"@types/katex": "^0.16.7", "@types/katex": "^0.16.7",
"@vscode/markdown-it-katex": "^1.1.0", "@vscode/markdown-it-katex": "^1.1.0",
"bootstrap": "^5.3.3",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"dom-to-image-more": "^3.5.0", "dom-to-image-more": "^3.5.0",
"evaluatex": "^2.2.0", "evaluatex": "^2.2.0",
@@ -2174,25 +2173,6 @@
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/bootstrap": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
"integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"license": "MIT",
"peerDependencies": {
"@popperjs/core": "^2.11.8"
}
},
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",

View File

@@ -80,7 +80,6 @@
"@types/file-saver": "^2.0.7", "@types/file-saver": "^2.0.7",
"@types/katex": "^0.16.7", "@types/katex": "^0.16.7",
"@vscode/markdown-it-katex": "^1.1.0", "@vscode/markdown-it-katex": "^1.1.0",
"bootstrap": "^5.3.3",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"dom-to-image-more": "^3.5.0", "dom-to-image-more": "^3.5.0",
"evaluatex": "^2.2.0", "evaluatex": "^2.2.0",

View File

@@ -22,7 +22,9 @@ import codeblock from "../assets/icons/codeblock.svg";
export class Header extends HTMLElement implements UAIEditorEventListener { export class Header extends HTMLElement implements UAIEditorEventListener {
toolbar!: HTMLElement; toolbar!: HTMLElement;
container!: HTMLElement; container!: HTMLElement;
menus!: HTMLElement;
actions!: HTMLElement; actions!: HTMLElement;
allMenus: HTMLElement[] = [];
defaultToolbarMenus!: Record<string, any>[]; defaultToolbarMenus!: Record<string, any>[];
@@ -56,7 +58,7 @@ export class Header extends HTMLElement implements UAIEditorEventListener {
this.classicMenu = new Classic(this.defaultToolbarMenus); this.classicMenu = new Classic(this.defaultToolbarMenus);
// 创建源码编辑器 // 创建源码编辑器
this.sourceMenu = document.createElement("div"); this.sourceMenu = document.createElement("div");
this.sourceMenu.classList.add("uai-classic-scrollable-container"); this.sourceMenu.classList.add("uai-source-menu");
this.sourceMenu.innerHTML = `<img src="${codeblock}" width="20" />&nbsp;${t('toolbar.source')}`; this.sourceMenu.innerHTML = `<img src="${codeblock}" width="20" />&nbsp;${t('toolbar.source')}`;
} }
@@ -80,9 +82,14 @@ export class Header extends HTMLElement implements UAIEditorEventListener {
// 初始化经典工具栏 // 初始化经典工具栏
this.classicMenu.onCreate(event, options); this.classicMenu.onCreate(event, options);
this.container.appendChild(this.ribbonMenu); this.allMenus.push(this.ribbonMenu);
this.container.appendChild(this.classicMenu); this.allMenus.push(this.classicMenu);
this.container.appendChild(this.sourceMenu); this.allMenus.push(this.sourceMenu);
// 添加工具栏切换菜单
this.menus = document.createElement("div");
this.menus.classList.add("uai-toolbar-menus");
this.container.appendChild(this.menus);
// 添加工具栏切换菜单 // 添加工具栏切换菜单
this.actions = document.createElement("div"); this.actions = document.createElement("div");
@@ -138,14 +145,22 @@ export class Header extends HTMLElement implements UAIEditorEventListener {
this.classicMenu.onEditableChange(editable); this.classicMenu.onEditableChange(editable);
} }
removeAllMenus(): void {
this.allMenus.forEach(menu => {
try {
this.menus.removeChild(menu);
} catch (e) {
}
});
}
/** /**
* 切换专业工具栏 * 切换专业工具栏
* @param event * @param event
*/ */
switchRibbonMenu(event: EditorEvents["create"]) { switchRibbonMenu(event: EditorEvents["create"]) {
this.ribbonMenu.style.display = "flex"; this.removeAllMenus();
this.classicMenu.style.display = "none"; this.menus.appendChild(this.ribbonMenu);
this.sourceMenu.style.display = "none";
this.menuMode = "ribbon"; this.menuMode = "ribbon";
(event.editor as InnerEditor).uaiEditor.switchEditor(); (event.editor as InnerEditor).uaiEditor.switchEditor();
} }
@@ -155,9 +170,8 @@ export class Header extends HTMLElement implements UAIEditorEventListener {
* @param event * @param event
*/ */
switchClassicMenu(event: EditorEvents["create"]) { switchClassicMenu(event: EditorEvents["create"]) {
this.ribbonMenu.style.display = "none"; this.removeAllMenus();
this.classicMenu.style.display = "flex"; this.menus.appendChild(this.classicMenu);
this.sourceMenu.style.display = "none";
this.menuMode = "classic"; this.menuMode = "classic";
(event.editor as InnerEditor).uaiEditor.switchEditor(); (event.editor as InnerEditor).uaiEditor.switchEditor();
} }
@@ -167,9 +181,8 @@ export class Header extends HTMLElement implements UAIEditorEventListener {
* @param event * @param event
*/ */
switchSourceMenu(event: EditorEvents["create"]) { switchSourceMenu(event: EditorEvents["create"]) {
this.ribbonMenu.style.display = "none"; this.removeAllMenus();
this.classicMenu.style.display = "none"; this.menus.appendChild(this.sourceMenu);
this.sourceMenu.style.display = "flex";
this.menuMode = "source"; this.menuMode = "source";
(event.editor as InnerEditor).uaiEditor.switchSource(); (event.editor as InnerEditor).uaiEditor.switchSource();
} }

View File

@@ -89,6 +89,7 @@ import menuIcon from "../../../assets/icons/menu.svg";
export class Classic extends HTMLElement implements UAIEditorEventListener { export class Classic extends HTMLElement implements UAIEditorEventListener {
defaultToolbarMenus!: Record<string, any>[]; defaultToolbarMenus!: Record<string, any>[];
eventComponents: UAIEditorEventListener[] = []; eventComponents: UAIEditorEventListener[] = [];
scrollableDivs: ScrollableDiv[] = [];
// 传统菜单栏容器 // 传统菜单栏容器
classicMenu!: HTMLElement; classicMenu!: HTMLElement;
@@ -216,17 +217,12 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
component.onCreate(event, options); component.onCreate(event, options);
}) })
// 创建菜单容器 // 创建菜单容器
this.classicScrollableContainer = document.createElement("div");
this.classicScrollableContainer.classList.add("uai-classic-scrollable-container");
this.appendChild(this.classicScrollableContainer);
this.classicMenu = document.createElement("div"); this.classicMenu = document.createElement("div");
this.classicMenu.classList.add("uai-classic-menu"); this.classicMenu.classList.add("uai-classic-menu");
this.classicScrollableContainer.appendChild(this.classicMenu); this.appendChild(this.classicMenu);
const selectDiv = document.createElement("div"); const selectDiv = document.createElement("div");
selectDiv.classList.add("uai-classic-virtual-group"); selectDiv.classList.add("uai-classic-menu-switch");
selectDiv.classList.add("uai-editor-menu-select-3");
selectDiv.innerHTML = `<img src="${menuIcon}" width="16" />`; selectDiv.innerHTML = `<img src="${menuIcon}" width="16" />`;
this.classicMenu.appendChild(selectDiv); this.classicMenu.appendChild(selectDiv);
@@ -242,35 +238,39 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
// 添加事件,处理菜单分组切换、界面元素切换 // 添加事件,处理菜单分组切换、界面元素切换
selectMuenus.addEventListener("change", () => { selectMuenus.addEventListener("change", () => {
const menu = selectMuenus.selectedOptions[0].value; const menu = selectMuenus.selectedOptions[0].value;
this.classicMenuBaseScrollable.style.display = "none"; this.scrollableDivs.forEach(scrollable => {
this.classicMenuInsertScrollable.style.display = "none"; try {
this.classicMenuTableScrollable.style.display = "none"; this.classicScrollableContainer.removeChild(scrollable);
this.classicMenuToolScrollable.style.display = "none"; } catch (e) {
this.classicMenuPageScrollable.style.display = "none"; }
this.classicMenuExportScrollable.style.display = "none"; });
this.classicMenuAIScrollable.style.display = "none";
if (menu === "base") { if (menu === "base") {
this.classicMenuBaseScrollable.style.display = "flex"; this.classicScrollableContainer.appendChild(this.classicMenuBaseScrollable);
} }
if (menu === "insert") { if (menu === "insert") {
this.classicMenuInsertScrollable.style.display = "flex"; this.classicScrollableContainer.appendChild(this.classicMenuInsertScrollable);
} }
if (menu === "table") { if (menu === "table") {
this.classicMenuTableScrollable.style.display = "flex"; this.classicScrollableContainer.appendChild(this.classicMenuTableScrollable);
} }
if (menu === "tools") { if (menu === "tools") {
this.classicMenuToolScrollable.style.display = "flex"; this.classicScrollableContainer.appendChild(this.classicMenuToolScrollable);
} }
if (menu === "page") { if (menu === "page") {
this.classicMenuPageScrollable.style.display = "flex"; this.classicScrollableContainer.appendChild(this.classicMenuPageScrollable);
} }
if (menu === "export") { if (menu === "export") {
this.classicMenuExportScrollable.style.display = "flex"; this.classicScrollableContainer.appendChild(this.classicMenuExportScrollable);
} }
if (menu === "ai") { if (menu === "ai") {
this.classicMenuAIScrollable.style.display = "flex"; this.classicScrollableContainer.appendChild(this.classicMenuAIScrollable);
} }
}) })
this.classicScrollableContainer = document.createElement("div");
this.classicScrollableContainer.classList.add("uai-classic-scrollable-container");
this.classicMenu.appendChild(this.classicScrollableContainer);
// 创建分组菜单 // 创建分组菜单
this.createBaseMenu(event, options); this.createBaseMenu(event, options);
this.createInsertMenu(event, options); this.createInsertMenu(event, options);
@@ -279,7 +279,7 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
this.createPageMenu(event, options); this.createPageMenu(event, options);
this.createExportMenu(event, options); this.createExportMenu(event, options);
this.createAIMenu(event, options); this.createAIMenu(event, options);
this.classicMenuBaseScrollable.style.display = "flex"; selectMuenus.dispatchEvent(new Event("change"));
} }
/** /**
@@ -489,9 +489,9 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
this.classicMenuBaseGroup = document.createElement("div"); this.classicMenuBaseGroup = document.createElement("div");
this.classicMenuBaseGroup.style.display = "flex"; this.classicMenuBaseGroup.style.display = "flex";
this.classicMenuBaseScrollable = new ScrollableDiv(this.classicMenuBaseGroup); this.classicMenuBaseScrollable = new ScrollableDiv(this.classicMenuBaseGroup);
this.classicMenuBaseScrollable.style.display = "none"; this.classicMenuBaseScrollable.style.display = "flex";
this.classicMenu.appendChild(this.classicMenuBaseScrollable);
this.classicMenuBaseScrollable.onCreate(event, options); this.classicMenuBaseScrollable.onCreate(event, options);
this.scrollableDivs.push(this.classicMenuBaseScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-classic-virtual-group"); group1.classList.add("uai-classic-virtual-group");
@@ -549,9 +549,9 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
this.classicMenuInsertGroup = document.createElement("div"); this.classicMenuInsertGroup = document.createElement("div");
this.classicMenuInsertGroup.style.display = "flex"; this.classicMenuInsertGroup.style.display = "flex";
this.classicMenuInsertScrollable = new ScrollableDiv(this.classicMenuInsertGroup); this.classicMenuInsertScrollable = new ScrollableDiv(this.classicMenuInsertGroup);
this.classicMenuInsertScrollable.style.display = "none"; this.classicMenuInsertScrollable.style.display = "flex";
this.classicMenu.appendChild(this.classicMenuInsertScrollable);
this.classicMenuInsertScrollable.onCreate(event, options); this.classicMenuInsertScrollable.onCreate(event, options);
this.scrollableDivs.push(this.classicMenuInsertScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-classic-virtual-group"); group1.classList.add("uai-classic-virtual-group");
@@ -585,9 +585,9 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
this.classicMenuTableGroup = document.createElement("div"); this.classicMenuTableGroup = document.createElement("div");
this.classicMenuTableGroup.style.display = "flex"; this.classicMenuTableGroup.style.display = "flex";
this.classicMenuTableScrollable = new ScrollableDiv(this.classicMenuTableGroup); this.classicMenuTableScrollable = new ScrollableDiv(this.classicMenuTableGroup);
this.classicMenuTableScrollable.style.display = "none"; this.classicMenuTableScrollable.style.display = "flex";
this.classicMenu.appendChild(this.classicMenuTableScrollable);
this.classicMenuTableScrollable.onCreate(event, options); this.classicMenuTableScrollable.onCreate(event, options);
this.scrollableDivs.push(this.classicMenuTableScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-classic-virtual-group"); group1.classList.add("uai-classic-virtual-group");
@@ -619,9 +619,9 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
this.classicMenuToolGroup = document.createElement("div"); this.classicMenuToolGroup = document.createElement("div");
this.classicMenuToolGroup.style.display = "flex"; this.classicMenuToolGroup.style.display = "flex";
this.classicMenuToolScrollable = new ScrollableDiv(this.classicMenuToolGroup); this.classicMenuToolScrollable = new ScrollableDiv(this.classicMenuToolGroup);
this.classicMenuToolScrollable.style.display = "none"; this.classicMenuToolScrollable.style.display = "flex";
this.classicMenu.appendChild(this.classicMenuToolScrollable);
this.classicMenuToolScrollable.onCreate(event, options); this.classicMenuToolScrollable.onCreate(event, options);
this.scrollableDivs.push(this.classicMenuToolScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-classic-virtual-group"); group1.classList.add("uai-classic-virtual-group");
@@ -638,9 +638,9 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
this.classicMenuPageGroup = document.createElement("div"); this.classicMenuPageGroup = document.createElement("div");
this.classicMenuPageGroup.style.display = "flex"; this.classicMenuPageGroup.style.display = "flex";
this.classicMenuPageScrollable = new ScrollableDiv(this.classicMenuPageGroup); this.classicMenuPageScrollable = new ScrollableDiv(this.classicMenuPageGroup);
this.classicMenuPageScrollable.style.display = "none"; this.classicMenuPageScrollable.style.display = "flex";
this.classicMenu.appendChild(this.classicMenuPageScrollable);
this.classicMenuPageScrollable.onCreate(event, options); this.classicMenuPageScrollable.onCreate(event, options);
this.scrollableDivs.push(this.classicMenuPageScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-classic-virtual-group"); group1.classList.add("uai-classic-virtual-group");
@@ -663,9 +663,9 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
this.classicMenuExportGroup = document.createElement("div"); this.classicMenuExportGroup = document.createElement("div");
this.classicMenuExportGroup.style.display = "flex"; this.classicMenuExportGroup.style.display = "flex";
this.classicMenuExportScrollable = new ScrollableDiv(this.classicMenuExportGroup); this.classicMenuExportScrollable = new ScrollableDiv(this.classicMenuExportGroup);
this.classicMenuExportScrollable.style.display = "none"; this.classicMenuExportScrollable.style.display = "flex";
this.classicMenu.appendChild(this.classicMenuExportScrollable);
this.classicMenuExportScrollable.onCreate(event, options); this.classicMenuExportScrollable.onCreate(event, options);
this.scrollableDivs.push(this.classicMenuExportScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-classic-virtual-group"); group1.classList.add("uai-classic-virtual-group");
@@ -690,9 +690,9 @@ export class Classic extends HTMLElement implements UAIEditorEventListener {
this.classicMenuAIGroup = document.createElement("div"); this.classicMenuAIGroup = document.createElement("div");
this.classicMenuAIGroup.style.display = "flex"; this.classicMenuAIGroup.style.display = "flex";
this.classicMenuAIScrollable = new ScrollableDiv(this.classicMenuAIGroup); this.classicMenuAIScrollable = new ScrollableDiv(this.classicMenuAIGroup);
this.classicMenuAIScrollable.style.display = "none"; this.classicMenuAIScrollable.style.display = "flex";
this.classicMenu.appendChild(this.classicMenuAIScrollable);
this.classicMenuAIScrollable.onCreate(event, options); this.classicMenuAIScrollable.onCreate(event, options);
this.scrollableDivs.push(this.classicMenuAIScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-classic-virtual-group"); group1.classList.add("uai-classic-virtual-group");

View File

@@ -91,6 +91,7 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
defaultToolbarMenus!: Record<string, any>[]; defaultToolbarMenus!: Record<string, any>[];
eventComponents: UAIEditorEventListener[] = []; eventComponents: UAIEditorEventListener[] = [];
headingOptions: Record<string, any>[] = []; headingOptions: Record<string, any>[] = [];
scrollableDivs: ScrollableDiv[] = [];
// 经典菜单栏容器 // 经典菜单栏容器
ribbonMenu!: HTMLElement; ribbonMenu!: HTMLElement;
@@ -237,38 +238,36 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
ribbonTabs.children[i].classList.remove("active"); ribbonTabs.children[i].classList.remove("active");
} }
tab.classList.add("active"); tab.classList.add("active");
this.ribbonMenuBaseScrollable.style.display = "none"; this.scrollableDivs.forEach(scrollable => {
this.ribbonMenuInsertScrollable.style.display = "none"; try {
this.ribbonMenuTableScrollable.style.display = "none"; this.ribbonScrollableContainer.removeChild(scrollable);
this.ribbonMenuToolScrollable.style.display = "none"; } catch (e) {
this.ribbonMenuPageScrollable.style.display = "none"; }
this.ribbonMenuExportScrollable.style.display = "none"; });
this.ribbonMenuAIScrollable.style.display = "none";
if (menu.value === "base") { if (menu.value === "base") {
this.ribbonMenuBaseScrollable.style.display = "flex"; this.ribbonScrollableContainer.appendChild(this.ribbonMenuBaseScrollable);
} }
if (menu.value === "insert") { if (menu.value === "insert") {
this.ribbonMenuInsertScrollable.style.display = "flex"; this.ribbonScrollableContainer.appendChild(this.ribbonMenuInsertScrollable);
} }
if (menu.value === "table") { if (menu.value === "table") {
this.ribbonMenuTableScrollable.style.display = "flex"; this.ribbonScrollableContainer.appendChild(this.ribbonMenuTableScrollable);
} }
if (menu.value === "tools") { if (menu.value === "tools") {
this.ribbonMenuToolScrollable.style.display = "flex"; this.ribbonScrollableContainer.appendChild(this.ribbonMenuToolScrollable);
} }
if (menu.value === "page") { if (menu.value === "page") {
this.ribbonMenuPageScrollable.style.display = "flex"; this.ribbonScrollableContainer.appendChild(this.ribbonMenuPageScrollable);
} }
if (menu.value === "export") { if (menu.value === "export") {
this.ribbonMenuExportScrollable.style.display = "flex"; this.ribbonScrollableContainer.appendChild(this.ribbonMenuExportScrollable);
} }
if (menu.value === "ai") { if (menu.value === "ai") {
this.ribbonMenuAIScrollable.style.display = "flex"; this.ribbonScrollableContainer.appendChild(this.ribbonMenuAIScrollable);
} }
}) })
ribbonTabs.appendChild(tab); ribbonTabs.appendChild(tab);
}); });
ribbonTabs.children[0].classList.add("active")
this.ribbonScrollableContainer = document.createElement("div"); this.ribbonScrollableContainer = document.createElement("div");
this.ribbonScrollableContainer.classList.add("uai-ribbon-scrollable-container"); this.ribbonScrollableContainer.classList.add("uai-ribbon-scrollable-container");
@@ -289,7 +288,7 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
this.createPageMenu(event, options); this.createPageMenu(event, options);
this.createExportMenu(event, options); this.createExportMenu(event, options);
this.createAIMenu(event, options); this.createAIMenu(event, options);
this.ribbonMenuBaseScrollable.style.display = "flex"; ribbonTabs.children[0].dispatchEvent(new MouseEvent("click"));
} }
/** /**
@@ -508,13 +507,14 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
* @param event * @param event
* @param options * @param options
*/ */
createBaseMenu(event: EditorEvents["create"], _options: UAIEditorOptions) { createBaseMenu(event: EditorEvents["create"], options: UAIEditorOptions) {
this.ribbonMenuBaseGroup = document.createElement("div"); this.ribbonMenuBaseGroup = document.createElement("div");
this.ribbonMenuBaseGroup.classList.add("uai-ribbon-container"); this.ribbonMenuBaseGroup.classList.add("uai-ribbon-container");
this.ribbonMenuBaseGroup.style.display = "flex"; this.ribbonMenuBaseGroup.style.display = "flex";
this.ribbonMenuBaseScrollable = new ScrollableDiv(this.ribbonMenuBaseGroup); this.ribbonMenuBaseScrollable = new ScrollableDiv(this.ribbonMenuBaseGroup);
this.ribbonMenuBaseScrollable.style.display = "none"; this.ribbonMenuBaseScrollable.style.display = "flex";
this.ribbonScrollableContainer.appendChild(this.ribbonMenuBaseScrollable); this.ribbonMenuBaseScrollable.onCreate(event, options);
this.scrollableDivs.push(this.ribbonMenuBaseScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-ribbon-virtual-group"); group1.classList.add("uai-ribbon-virtual-group");
@@ -641,13 +641,14 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
* @param event * @param event
* @param options * @param options
*/ */
createInsertMenu(_event: EditorEvents["create"], _options: UAIEditorOptions) { createInsertMenu(event: EditorEvents["create"], options: UAIEditorOptions) {
this.ribbonMenuInsertGroup = document.createElement("div"); this.ribbonMenuInsertGroup = document.createElement("div");
this.ribbonMenuInsertGroup.classList.add("uai-ribbon-container"); this.ribbonMenuInsertGroup.classList.add("uai-ribbon-container");
this.ribbonMenuInsertGroup.style.display = "flex"; this.ribbonMenuInsertGroup.style.display = "flex";
this.ribbonMenuInsertScrollable = new ScrollableDiv(this.ribbonMenuInsertGroup); this.ribbonMenuInsertScrollable = new ScrollableDiv(this.ribbonMenuInsertGroup);
this.ribbonMenuInsertScrollable.style.display = "none"; this.ribbonMenuInsertScrollable.style.display = "flex";
this.ribbonScrollableContainer.appendChild(this.ribbonMenuInsertScrollable); this.ribbonMenuInsertScrollable.onCreate(event, options);
this.scrollableDivs.push(this.ribbonMenuInsertScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-ribbon-virtual-group"); group1.classList.add("uai-ribbon-virtual-group");
@@ -677,13 +678,14 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
* @param event * @param event
* @param options * @param options
*/ */
createTableMenu(_event: EditorEvents["create"], _options: UAIEditorOptions) { createTableMenu(event: EditorEvents["create"], options: UAIEditorOptions) {
this.ribbonMenuTableGroup = document.createElement("div"); this.ribbonMenuTableGroup = document.createElement("div");
this.ribbonMenuTableGroup.classList.add("uai-ribbon-container"); this.ribbonMenuTableGroup.classList.add("uai-ribbon-container");
this.ribbonMenuTableGroup.style.display = "flex"; this.ribbonMenuTableGroup.style.display = "flex";
this.ribbonMenuTableScrollable = new ScrollableDiv(this.ribbonMenuTableGroup); this.ribbonMenuTableScrollable = new ScrollableDiv(this.ribbonMenuTableGroup);
this.ribbonMenuTableScrollable.style.display = "none"; this.ribbonMenuTableScrollable.style.display = "flex";
this.ribbonScrollableContainer.appendChild(this.ribbonMenuTableScrollable); this.ribbonMenuTableScrollable.onCreate(event, options);
this.scrollableDivs.push(this.ribbonMenuTableScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-ribbon-virtual-group"); group1.classList.add("uai-ribbon-virtual-group");
@@ -719,13 +721,14 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
* @param event * @param event
* @param options * @param options
*/ */
createToolMenu(_event: EditorEvents["create"], _options: UAIEditorOptions) { createToolMenu(event: EditorEvents["create"], options: UAIEditorOptions) {
this.ribbonMenuToolGroup = document.createElement("div"); this.ribbonMenuToolGroup = document.createElement("div");
this.ribbonMenuToolGroup.classList.add("uai-ribbon-container"); this.ribbonMenuToolGroup.classList.add("uai-ribbon-container");
this.ribbonMenuToolGroup.style.display = "flex"; this.ribbonMenuToolGroup.style.display = "flex";
this.ribbonMenuToolScrollable = new ScrollableDiv(this.ribbonMenuToolGroup); this.ribbonMenuToolScrollable = new ScrollableDiv(this.ribbonMenuToolGroup);
this.ribbonMenuToolScrollable.style.display = "none"; this.ribbonMenuToolScrollable.style.display = "flex";
this.ribbonScrollableContainer.appendChild(this.ribbonMenuToolScrollable); this.ribbonMenuToolScrollable.onCreate(event, options);
this.scrollableDivs.push(this.ribbonMenuToolScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-ribbon-virtual-group"); group1.classList.add("uai-ribbon-virtual-group");
@@ -738,13 +741,14 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
* @param event * @param event
* @param options * @param options
*/ */
createPageMenu(_event: EditorEvents["create"], _options: UAIEditorOptions) { createPageMenu(event: EditorEvents["create"], options: UAIEditorOptions) {
this.ribbonMenuPageGroup = document.createElement("div"); this.ribbonMenuPageGroup = document.createElement("div");
this.ribbonMenuPageGroup.classList.add("uai-ribbon-container"); this.ribbonMenuPageGroup.classList.add("uai-ribbon-container");
this.ribbonMenuPageGroup.style.display = "flex"; this.ribbonMenuPageGroup.style.display = "flex";
this.ribbonMenuPageScrollable = new ScrollableDiv(this.ribbonMenuPageGroup); this.ribbonMenuPageScrollable = new ScrollableDiv(this.ribbonMenuPageGroup);
this.ribbonMenuPageScrollable.style.display = "none"; this.ribbonMenuPageScrollable.style.display = "flex";
this.ribbonScrollableContainer.appendChild(this.ribbonMenuPageScrollable); this.ribbonMenuPageScrollable.onCreate(event, options);
this.scrollableDivs.push(this.ribbonMenuPageScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-ribbon-virtual-group"); group1.classList.add("uai-ribbon-virtual-group");
@@ -763,13 +767,14 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
* @param event * @param event
* @param options * @param options
*/ */
createExportMenu(_event: EditorEvents["create"], _options: UAIEditorOptions) { createExportMenu(event: EditorEvents["create"], options: UAIEditorOptions) {
this.ribbonMenuExportGroup = document.createElement("div"); this.ribbonMenuExportGroup = document.createElement("div");
this.ribbonMenuExportGroup.classList.add("uai-ribbon-container"); this.ribbonMenuExportGroup.classList.add("uai-ribbon-container");
this.ribbonMenuExportGroup.style.display = "flex"; this.ribbonMenuExportGroup.style.display = "flex";
this.ribbonMenuExportScrollable = new ScrollableDiv(this.ribbonMenuExportGroup); this.ribbonMenuExportScrollable = new ScrollableDiv(this.ribbonMenuExportGroup);
this.ribbonMenuExportScrollable.style.display = "none"; this.ribbonMenuExportScrollable.style.display = "flex";
this.ribbonScrollableContainer.appendChild(this.ribbonMenuExportScrollable); this.ribbonMenuExportScrollable.onCreate(event, options);
this.scrollableDivs.push(this.ribbonMenuExportScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-ribbon-virtual-group"); group1.classList.add("uai-ribbon-virtual-group");
@@ -790,13 +795,14 @@ export class Ribbon extends HTMLElement implements UAIEditorEventListener {
* @param event * @param event
* @param options * @param options
*/ */
createAIMenu(_event: EditorEvents["create"], _options: UAIEditorOptions) { createAIMenu(event: EditorEvents["create"], options: UAIEditorOptions) {
this.ribbonMenuAIGroup = document.createElement("div"); this.ribbonMenuAIGroup = document.createElement("div");
this.ribbonMenuAIGroup.classList.add("uai-ribbon-container"); this.ribbonMenuAIGroup.classList.add("uai-ribbon-container");
this.ribbonMenuAIGroup.style.display = "flex"; this.ribbonMenuAIGroup.style.display = "flex";
this.ribbonMenuAIScrollable = new ScrollableDiv(this.ribbonMenuAIGroup); this.ribbonMenuAIScrollable = new ScrollableDiv(this.ribbonMenuAIGroup);
this.ribbonMenuAIScrollable.style.display = "none"; this.ribbonMenuAIScrollable.style.display = "flex";
this.ribbonScrollableContainer.appendChild(this.ribbonMenuAIScrollable); this.ribbonMenuAIScrollable.onCreate(event, options);
this.scrollableDivs.push(this.ribbonMenuAIScrollable);
const group1 = document.createElement("div"); const group1 = document.createElement("div");
group1.classList.add("uai-ribbon-virtual-group"); group1.classList.add("uai-ribbon-virtual-group");

View File

@@ -19,17 +19,19 @@ export class ScrollableDiv extends HTMLElement implements UAIEditorEventListener
constructor(content: HTMLElement) { constructor(content: HTMLElement) {
super(); super();
this.content = content; this.content = content;
this.classList.add("uai-scrollable-control");
this.scrollLeftBtn = document.createElement("div"); this.scrollLeftBtn = document.createElement("div");
this.scrollLeftBtn.classList.add("uai-scrollable-control-button"); this.scrollLeftBtn.classList.add("uai-scrollable-control-button");
this.scrollLeftBtn.classList.add("uai-scrollable-control-button-left");
this.scrollLeftBtn.innerHTML = "<strong><</strong>"; this.scrollLeftBtn.innerHTML = "<strong><</strong>";
this.scrollLeftBtn.style.display = "none"; this.scrollLeftBtn.style.display = "none";
this.container = document.createElement("div"); this.container = document.createElement("div");
this.container.classList.add("uai-scrollable-control-content");
this.container.appendChild(this.content); this.container.appendChild(this.content);
// this.container.style.overflow = "hidden";
// this.container.style.position = "relative";
this.scrollRightBtn = document.createElement("div"); this.scrollRightBtn = document.createElement("div");
this.scrollRightBtn.classList.add("uai-scrollable-control-button"); this.scrollRightBtn.classList.add("uai-scrollable-control-button");
this.scrollRightBtn.classList.add("uai-scrollable-control-button-right");
this.scrollRightBtn.innerHTML = "<strong>></strong>"; this.scrollRightBtn.innerHTML = "<strong>></strong>";
this.scrollRightBtn.style.display = "none"; this.scrollRightBtn.style.display = "none";
@@ -37,19 +39,18 @@ export class ScrollableDiv extends HTMLElement implements UAIEditorEventListener
if (this.transform < 0) { if (this.transform < 0) {
this.transform += Math.min(this.scrollAmount, 0 - this.transform); this.transform += Math.min(this.scrollAmount, 0 - this.transform);
} }
this.content.style.transform = `translateX(${this.transform}px)`; this.renderTranslate();
this.scrollButtonControl(); this.scrollButtonControl();
}); });
this.scrollRightBtn.addEventListener('click', () => { this.scrollRightBtn.addEventListener('click', () => {
const scrollWidth = this.content.scrollWidth + this.transform - this.scrollRightBtn.clientWidth - this.container.clientWidth; const scrollWidth = this.content.scrollWidth + this.transform - this.container.clientWidth;
if (scrollWidth > 0) { if (scrollWidth > 0) {
this.transform -= Math.min(this.scrollAmount, scrollWidth); this.transform -= Math.min(this.scrollAmount, scrollWidth);
} }
this.content.style.transform = `translateX(${this.transform}px)`; this.renderTranslate();
this.scrollButtonControl(); this.scrollButtonControl();
}); });
this.classList.add("uai-classic-scrollable-menu")
this.appendChild(this.scrollLeftBtn) this.appendChild(this.scrollLeftBtn)
this.appendChild(this.container) this.appendChild(this.container)
this.appendChild(this.scrollRightBtn) this.appendChild(this.scrollRightBtn)
@@ -58,13 +59,13 @@ export class ScrollableDiv extends HTMLElement implements UAIEditorEventListener
onCreate(event: EditorEvents["create"], options: UAIEditorOptions) { onCreate(event: EditorEvents["create"], options: UAIEditorOptions) {
const resizeObserver = new ResizeObserver(entries => { const resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) { for (let entry of entries) {
if (entry.target === this.parentElement) { if (entry.target === this.content) {
this.scrollButtonControl(); this.scrollButtonControl();
} }
} }
}); });
resizeObserver.observe(this.parentElement!); resizeObserver.observe(this.content!);
} }
onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) { onTransaction(event: EditorEvents["transaction"], options: UAIEditorOptions) {
@@ -75,16 +76,25 @@ export class ScrollableDiv extends HTMLElement implements UAIEditorEventListener
} }
scrollButtonControl() { scrollButtonControl() {
if (this.transform < 0) { if (this.transform < 0 && this.container.clientWidth > this.content.scrollWidth + this.transform) {
this.scrollLeftBtn.style.display = "flex"; this.transform = this.container.clientWidth - this.content.scrollWidth;
} else { this.content.style.transform = `translateX(${this.transform}px)`;
this.scrollLeftBtn.style.display = "none";
} }
if (this.parentElement!.scrollWidth + this.transform - this.scrollRightBtn.clientWidth < this.container.clientWidth) { const shouldShowLeftButton = this.transform < 0;
this.scrollRightBtn.style.display = "flex"; const shouldShowRightButton = this.container.scrollWidth > this.content.clientWidth;
} else { this.scrollLeftBtn.style.display = shouldShowLeftButton ? "flex" : "none";
this.scrollRightBtn.style.display = "none"; this.scrollRightBtn.style.display = shouldShowRightButton ? "flex" : "none";
if (!shouldShowLeftButton && !shouldShowRightButton) {
this.transform = 0;
this.renderTranslate();
} }
// 触发宽度变化事件 }
renderTranslate() {
this.content.style.transform = `translateX(${this.transform}px)`;
// 更新所有tippy实例位置
this.querySelectorAll('[data-tippy-root]').forEach((tip: any) => {
tip._tippy?.popperInstance?.update();
});
} }
} }

View File

@@ -1,75 +1,115 @@
// Copyright (c) 2024-present AI-Labs // Copyright (c) 2024-present AI-Labs
// @ ts-nocheck // @ ts-nocheck
import { Modal } from "bootstrap"; import './Modal.css';
import 'bootstrap/dist/css/bootstrap.css';
/**
* 居中的模态弹出框
*/
export class CenterModal extends Modal {
export class CenterModal {
modalHeader!: HTMLElement; modalHeader!: HTMLElement;
modalBody!: HTMLElement; modalBody!: HTMLElement;
modalFooter!: HTMLElement; modalFooter!: HTMLElement;
commit: HTMLButtonElement; commit: HTMLButtonElement;
constructor(title: string, options?: Partial<Modal.Options>) { private overlay: HTMLElement;
const modal = document.createElement("div"); private container: HTMLElement;
// 设置模态弹出框 private closeBtn: HTMLButtonElement;
modal.classList.add("modal");
modal.setAttribute("role", "dialog");
modal.setAttribute("tabindex", "-1");
modal.setAttribute("aria-hidden", "true");
modal.setAttribute("aria-labelledby", "exampleModalCenterTitle");
// 模态弹出框居中样式 constructor(title: string) {
const modalDialog = document.createElement("div"); // 创建遮罩层
modalDialog.classList.add("modal-dialog"); this.overlay = document.createElement('div');
modalDialog.classList.add("modal-dialog-centered"); this.overlay.classList.add('modal-overlay');
modalDialog.setAttribute("role", "document");
// 创建模态框容器
this.container = document.createElement('div');
this.container.classList.add('modal-container');
this.container.classList.add('modal-container-center');
// 模态弹出框内容 // 头部区域
const modalContent = document.createElement("div"); this.modalHeader = document.createElement('div');
modalContent.classList.add("modal-content"); this.modalHeader.classList.add('modal-header');
modalDialog.appendChild(modalContent); this.modalHeader.innerHTML = `<h3>${title}</h3>`;
modal.appendChild(modalDialog);
super(modal, options);
// 标题区
this.modalHeader = document.createElement("div");
this.modalHeader.classList.add("modal-header");
this.modalHeader.innerHTML = `<h5 class="modal-title">${title}</h5>`
modalContent.appendChild(this.modalHeader);
// 主体区
this.modalBody = document.createElement("div");
this.modalBody.classList.add("modal-body");
modalContent.appendChild(this.modalBody);
// 底部按钮区
this.modalFooter = document.createElement("div");
this.modalFooter.classList.add("modal-footer");
modalContent.appendChild(this.modalFooter);
// 关闭按钮 // 关闭按钮
const close = document.createElement("button"); this.closeBtn = document.createElement('button');
close.classList.add("btn"); this.closeBtn.classList.add('modal-close');
close.classList.add("btn-secondary"); this.closeBtn.innerHTML = '×';
close.setAttribute("data-dismiss", "modal"); this.closeBtn.onclick = () => this.hide();
close.innerHTML = "关闭";
close.addEventListener("click", () => {
this.hide();
});
this.modalFooter.appendChild(close);
// 确定按钮 // 内容区域
this.commit = document.createElement("button") this.modalBody = document.createElement('div');
this.commit.classList.add("btn"); this.modalBody.classList.add('modal-body');
this.commit.classList.add("btn-primary");
this.commit.innerHTML = "确定"; // 底部区域
this.modalFooter = document.createElement('div');
this.modalFooter.classList.add('modal-footer');
// 添加commit按钮
this.commit = document.createElement('button');
this.commit.classList.add('modal-button');
this.commit.classList.add('modal-button-primary');
this.commit.textContent = '确定';
this.modalFooter.appendChild(this.commit); this.modalFooter.appendChild(this.commit);
// 添加cancel按钮
const cancelBtn = document.createElement('button');
cancelBtn.classList.add('modal-button');
cancelBtn.classList.add('modal-button-secondary');
cancelBtn.textContent = '关闭';
cancelBtn.onclick = () => {
this.hide();
};
this.modalFooter.appendChild(cancelBtn);
// 组装结构
this.modalHeader.appendChild(this.closeBtn);
this.container.append(this.modalHeader, this.modalBody, this.modalFooter);
this.overlay.appendChild(this.container);
} }
setContent(content: string | HTMLElement) {
this.modalBody.innerHTML = '';
if (typeof content === 'string') {
this.modalBody.innerHTML = content;
} else {
this.modalBody.appendChild(content);
}
}
addButton(text: string, onClick: () => void) {
const btn = document.createElement('button');
btn.className = 'modal-button';
btn.textContent = text;
btn.onclick = () => {
onClick();
this.hide();
};
this.modalFooter.appendChild(btn);
}
show() {
document.body.appendChild(this.overlay);
this.overlay.getBoundingClientRect(); // 强制重绘
this.overlay.style.opacity = '1';
this.container.style.transform = 'translateY(0)';
// 点击遮罩层关闭
this.overlay.onclick = (e) => {
if (e.target === this.overlay) this.hide();
};
// ESC键关闭
document.addEventListener('keydown', this.handleEscape);
}
hide() {
this.overlay.style.opacity = '0';
this.container.style.transform = 'translateY(-3rem)';
setTimeout(() => {
this.overlay.remove();
}, 300);
document.removeEventListener('keydown', this.handleEscape);
}
private handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape') this.hide();
};
} }

View File

@@ -1,74 +1,89 @@
// Copyright (c) 2024-present AI-Labs // Copyright (c) 2024-present AI-Labs
// @ ts-nocheck // @ ts-nocheck
import { Modal } from "bootstrap"; import './Modal.css';
import 'bootstrap/dist/css/bootstrap.css';
import closeIcon from "../../assets/icons/close.svg";
/**
* 全屏的模态弹出框
*/
export class FullScreenModal extends Modal {
export class FullScreenModal {
modalHeader!: HTMLElement; modalHeader!: HTMLElement;
modalBody!: HTMLElement; modalBody!: HTMLElement;
modalFooter!: HTMLElement;
private overlay: HTMLElement;
private container: HTMLElement;
private closeBtn: HTMLButtonElement;
messageListener?: (evt: MessageEvent) => void messageListener?: (evt: MessageEvent) => void
constructor(title: string, options?: Partial<Modal.Options>) { constructor(title: string) {
const modal = document.createElement("div"); // 创建遮罩层
// 设置模态弹出框 this.overlay = document.createElement('div');
modal.classList.add("modal"); this.overlay.classList.add('modal-overlay');
modal.setAttribute("role", "dialog");
modal.setAttribute("tabindex", "-1");
modal.setAttribute("aria-labelledby", "exampleModalCenterTitle");
// 模态弹出框全屏样式 // 创建模态框容器
const modalDialog = document.createElement("div"); this.container = document.createElement('div');
modalDialog.classList.add("modal-dialog"); this.container.classList.add('modal-container');
modalDialog.classList.add("modal-fullscreen"); this.container.classList.add('modal-container-fullscreen');
modalDialog.classList.add("modal-dialog-centered");
modalDialog.setAttribute("role", "document");
// 模态弹出框内容 // 头部区域
const modalContent = document.createElement("div"); this.modalHeader = document.createElement('div');
modalContent.classList.add("modal-content"); this.modalHeader.classList.add('modal-header');
modalDialog.appendChild(modalContent); this.modalHeader.innerHTML = `<h3>${title}</h3>`;
modal.appendChild(modalDialog);
super(modal, options);
// 标题区
this.modalHeader = document.createElement("div");
this.modalHeader.classList.add("modal-header");
// 标题
const titleDiv = document.createElement("div");
titleDiv.innerHTML = `<h5 class="modal-title" style="width:calc(100vw - 55px)">${title}</h5>`
this.modalHeader.appendChild(titleDiv);
// 关闭按钮 // 关闭按钮
const closeDiv = document.createElement("div"); this.closeBtn = document.createElement('button');
closeDiv.innerHTML = `<img src="${closeIcon}" width="24"/>`; this.closeBtn.classList.add('modal-close');
closeDiv.addEventListener("click", () => { this.closeBtn.innerHTML = '×';
this.hide(); this.closeBtn.onclick = () => this.hide();
if (this.messageListener) {
window.removeEventListener('message', this.messageListener);
}
});
this.modalHeader.appendChild(closeDiv);
modalContent.appendChild(this.modalHeader); // 内容区域
this.modalBody = document.createElement('div');
// 主体区 this.modalBody.classList.add('modal-body');
this.modalBody = document.createElement("div");
this.modalBody.classList.add("modal-body");
modalContent.appendChild(this.modalBody);
// 组装结构
this.modalHeader.appendChild(this.closeBtn);
this.container.append(this.modalHeader, this.modalBody);
this.overlay.appendChild(this.container);
} }
setContent(content: string | HTMLElement) {
this.modalBody.innerHTML = '';
if (typeof content === 'string') {
this.modalBody.innerHTML = content;
} else {
this.modalBody.appendChild(content);
}
}
show() {
document.body.appendChild(this.overlay);
this.overlay.getBoundingClientRect(); // 强制重绘
this.overlay.style.opacity = '1';
this.container.style.transform = 'translateY(0)';
// 点击遮罩层关闭
this.overlay.onclick = (e) => {
if (e.target === this.overlay) this.hide();
};
// ESC键关闭
document.addEventListener('keydown', this.handleEscape);
}
hide() {
this.overlay.style.opacity = '0';
this.container.style.transform = 'translateY(-3rem)';
setTimeout(() => {
this.overlay.remove();
}, 300);
document.removeEventListener('keydown', this.handleEscape);
if (this.messageListener) {
window.removeEventListener('message', this.messageListener);
}
}
private handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape') this.hide();
};
/** /**
* 添加回调监听 * 添加回调监听
* @param messageListener * @param messageListener

View File

@@ -0,0 +1,119 @@
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
transition: opacity 0.3s ease-in-out;
z-index: 9999;
}
.modal-container {
background: white;
transform: translateY(-3rem);
transition: transform 0.3s ease-in-out;
position: relative;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.modal-container-center {
border-radius: 8px;
min-width: 500px;
width: fit-content;
.modal-body {
padding: 1rem;
}
}
.modal-container-fullscreen {
width: 100%;
height: 100%;
.modal-body {
height: 100%;
}
}
.modal-header {
padding: 1rem;
font-size: 1.25rem;
color: #333;
border-bottom: 1px solid #eee;
h3 {
margin: 0 2rem 0 0;
font-size: 1.25rem;
color: #333;
}
.modal-close {
position: absolute;
top: 0.5rem;
right: 1rem;
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
padding: 0.5rem;
line-height: 1;
}
}
.modal-body {
min-height: 50px;
.form-group {
margin-bottom: 1rem;
input {
padding: 0.375rem 0.75rem;
font-size: 1rem;
min-width: 400px;
background-color: #fff;
border: 1px solid #ced4da;
border-radius: 0.25rem;
}
}
}
.modal-footer {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
padding: 1rem;
border-top: 1px solid #eee;
}
.modal-button {
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
border: none;
color: gray;
font-size: 1rem;
}
.modal-button-primary {
background-color: #007bff;
color: white;
}
.modal-button-secondary {
background-color: #6c757d;
color: white;
}
@media (max-width: 768px) {
.modal-container {
min-width: unset;
width: 90%;
padding: 1.5rem;
}
}

View File

@@ -346,8 +346,6 @@ export class UAIEditor {
rootEl.appendChild(this.container); rootEl.appendChild(this.container);
this.header = new Header(); this.header = new Header();
this.header.classList.add("uai-toolbar");
this.header.classList.add("toolbar-ribbon");
this.container.appendChild(this.header); this.container.appendChild(this.header);
this.center = document.createElement("div"); this.center = document.createElement("div");

View File

@@ -58,129 +58,252 @@
user-select: none; user-select: none;
border-bottom: solid 1px var(--uai-border-color); border-bottom: solid 1px var(--uai-border-color);
position: relative; position: relative;
z-index: 200;
.uai-editor-menu-select { .uai-toolbar-menus {
border: solid 1px var(--uai-border-color-light); width: calc(100% - 120px);
border-radius: var(--uai-radius); position: relative;
margin-left: 3px; z-index: 2;
}
.uai-editor-menu-select-3 { .uai-ribbon-menu {
padding: 3px;
border: solid 1px var(--uai-border-color-light);
border-radius: var(--uai-radius);
}
.uai-ribbon-menu { .uai-ribbon-tabs {
padding: 10px 10px 0;
.uai-ribbon-tabs {
padding: 10px 10px 0;
display: flex;
&-item {
font-size: var(--uai-font-size-small);
margin-right: 25px;
cursor: pointer;
display: flex; display: flex;
align-items: center;
flex-direction: column;
&:hover { &-item {
font-weight: 600; font-size: var(--uai-font-size-small);
margin-right: 25px;
cursor: pointer;
display: flex;
align-items: center;
flex-direction: column;
&::after { &:hover {
display: block; font-weight: 600;
content: '';
height: 3px;
width: 100%;
margin-top: 5px;
background-color: var(--uai-border-color);
}
}
&.active { &::after {
color: var(--uai-primary-color); display: block;
font-weight: 600; content: '';
height: 3px;
&::after { width: 100%;
display: block; margin-top: 5px;
content: ''; background-color: var(--uai-border-color);
height: 3px; }
width: 100%;
margin-top: 5px;
background-color: var(--uai-primary-color);
transition: width 0.3s;
} }
&:hover::after { &.active {
width: 120%; color: var(--uai-primary-color);
} font-weight: 600;
}
@media screen and (max-width: 640px) { &::after {
margin-right: 10px; display: block;
content: '';
height: 3px;
width: 100%;
margin-top: 5px;
background-color: var(--uai-primary-color);
transition: width 0.3s;
}
&:hover::after {
width: 120%;
}
}
@media screen and (max-width: 640px) {
margin-right: 10px;
}
} }
} }
}
.uai-ribbon-scrollable-container { .uai-ribbon-scrollable-container {
padding: 10px; padding: 10px 0;
box-sizing: border-box; box-sizing: border-box;
align-items: center;
/* 垂直居中子元素 */
justify-content: center;
/* 如果你也想要水平居中 */
vertical-align: middle;
.uai-ribbon-container { .uai-ribbon-container {
display: flex; height: 57px;
height: 61px; flex-shrink: 0;
flex-shrink: 0; width: 100%;
select { select {
border: none; border: solid 1px var(--uai-border-color-light);
outline: none; background-color: var(--uai-toolbar-background);
border-radius: var(--uai-radius);
padding: 6px;
outline: none;
}
.uai-ribbon-virtual-group {
padding: 0 20px;
border-left: solid 1px var(--uai-border-color-light);
flex-shrink: 0;
.uai-ribbon-heading-container {
width: 321px;
height: 56px;
display: flex;
position: relative;
z-index: 2;
background-color: var(--uai-container-background);
border: solid 1px var(--uai-border-color);
border-radius: var(--uai-radius);
.uai-ribbon-heading-list {
margin: 5px;
display: flex;
flex-wrap: wrap;
max-width: 300px;
overflow: hidden;
}
.uai-ribbon-heading-arrow {
margin-top: 8px;
margin-right: 5px;
padding-top: 15px;
height: 25px;
width: 16px;
border-radius: var(--uai-radius);
&:hover {
cursor: pointer;
background: #ddd; // var(--uai-content-node-selected-background);
border-radius: var(--uai-radius);
}
}
.uai-ribbon-heading-item {
width: 140px;
height: 42px;
margin: 2px;
padding: 0;
text-align: center;
background-color: #fff;
border: solid 1px var(--uai-border-color);
border-radius: var(--uai-radius);
padding: 5px 10px;
box-sizing: border-box;
cursor: pointer;
flex: 0 0 68px;
&:hover,
&.active {
border-color: var(--uai-primary-color);
}
&-title {
line-height: 18px;
font-weight: 600;
&.text {
font-size: 12px;
font-weight: 400;
}
&.h1 {
font-size: 15px;
}
&.h2 {
font-size: 14px;
}
&.h3 {
font-size: 13px;
}
&.h4 {
font-size: 12px;
}
&.h5 {
font-size: 11px;
}
&.h6 {
font-size: 10px;
}
}
&-subtitle {
font-size: 8px;
color: var(--uai-text-color-light);
text-transform: capitalize;
margin-top: 3px;
line-height: 1;
}
}
}
&:empty {
display: none;
}
&:first-child {
padding-left: 0;
}
&:first-child {
border-left: none;
}
&-row {
display: flex;
align-items: center;
:deep(> *:not(:last-child)) {
margin-right: 5px;
}
&:not(:last-child) {
margin-bottom: 5px;
}
}
}
} }
.uai-ribbon-virtual-group { .uai-scrollable-control {
padding: 0 20px; .uai-scrollable-control-button {
border-left: solid 1px var(--uai-border-color-light); padding: 0 10px;
flex-shrink: 0; border: 1px solid var(--uai-border-color);
background-color: var(--uai-container-background);
&:empty { border-radius: var(--uai-radius);
display: none;
}
&:first-child {
padding-left: 0;
}
&:first-child {
border-left: none;
}
&-row {
display: flex; display: flex;
align-items: center; align-items: center;
/* 垂直居中子元素 */
justify-content: center;
/* 如果你也想要水平居中 */
vertical-align: middle;
position: absolute;
height: 56px;
z-index: 2;
:deep(> *:not(:last-child)) { &-left {
margin-right: 5px; left: 0;
} }
&:not(:last-child) { &-right {
margin-bottom: 5px; right: 0;
} }
&:hover {
cursor: pointer;
background-color: var(--uai-primary-color);
}
}
.uai-scrollable-control-content {
flex: 1;
width: calc(100% - 120px);
} }
} }
} }
} }
}
.uai-classic-scrollable-container {
height: 50px;
padding: 10px;
display: flex;
align-items: center;
.uai-classic-scrollable-menu {
display: flex;
overflow: hidden;
}
.uai-classic-menu { .uai-classic-menu {
display: flex; display: flex;
@@ -193,65 +316,123 @@
outline: none; outline: none;
} }
.uai-classic-virtual-group { .uai-classic-menu-switch {
border: solid 1px var(--uai-border-color-light);
background-color: var(--uai-toolbar-background);
border-radius: var(--uai-radius);
padding: 6px;
display: flex; display: flex;
align-items: center; align-items: center;
// border-left: solid 1px #db2323;// var(--uai-border-color-light); /* 垂直居中子元素 */
flex-shrink: 0; justify-content: center;
/* 如果你也想要水平居中 */
vertical-align: middle;
z-index: 500;
}
&:empty { .uai-classic-scrollable-container {
display: none; height: 30px;
padding: 10px 0;
width: calc(100% - 104px);
.uai-editor-menu-select {
border: solid 1px var(--uai-border-color-light);
background-color: var(--uai-toolbar-background);
border-radius: var(--uai-radius);
margin-left: 3px;
padding: 2px;
} }
.uai-classic-virtual-group {
display: flex;
align-items: center;
// border-left: solid 1px #db2323;// var(--uai-border-color-light);
flex-shrink: 0;
// &:not(:last-child) { &:empty {
&::before { display: none;
content: ''; }
display: block;
height: 18px;
width: 1px;
background-color: var(--uai-border-color-light);
margin: 0 10px;
}
// } // &:not(:last-child) {
&::before {
content: '';
display: block;
height: 18px;
width: 1px;
background-color: var(--uai-border-color-light);
margin: 0 10px;
}
&:first-child::before { // }
display: none;
}
:deep(.uai-menu-button .uai-button--shape-square) { &:first-child::before {
.uai-icon { display: none;
font-size: 14px; }
:deep(.uai-menu-button .uai-button--shape-square) {
.uai-icon {
font-size: 14px;
}
}
&-row {
display: flex;
} }
} }
&-row { .uai-scrollable-control {
display: flex;
.uai-scrollable-control-button {
padding: 0 10px;
border: 1px solid var(--uai-border-color);
background-color: var(--uai-container-background);
border-radius: var(--uai-radius);
display: flex;
align-items: center;
/* 垂直居中子元素 */
justify-content: center;
/* 如果你也想要水平居中 */
vertical-align: middle;
position: absolute;
height: 28px;
z-index: 2;
&-left {
left: 1;
}
&-right {
right: 0;
}
&:hover {
cursor: pointer;
background-color: var(--uai-primary-color);
}
}
.uai-scrollable-control-content {
width: calc(100%);
}
} }
} }
} }
}
.uai-scrollable-control-button { .uai-source-menu {
padding: 0 10px; height: 30px;
background: var(--uai-primary-color); padding: 10px;
border-radius: var(--uai-radius); display: flex;
display: flex; align-items: center;
align-items: center;
/* 垂直居中子元素 */
justify-content: center;
/* 如果你也想要水平居中 */
vertical-align: middle;
&:hover {
cursor: pointer;
} }
} }
.uai-toolbar-actions { .uai-toolbar-actions {
padding: 6px 10px; padding: 6px 10px;
font-size: small; font-size: small;
min-width: 110px; width: 100px;
z-index: 500;
background-color: var(--uai-toolbar-background);
&.ribbon { &.ribbon {
position: absolute; position: absolute;
@@ -370,7 +551,8 @@
.uai-button-icon-arrow { .uai-button-icon-arrow {
width: 14px; width: 14px;
margin-left: -3px; margin-left: -4px;
padding-top: 4px;
border-top-right-radius: var(--uai-radius); border-top-right-radius: var(--uai-radius);
border-bottom-right-radius: var(--uai-radius); border-bottom-right-radius: var(--uai-radius);
@@ -419,7 +601,7 @@
.uai-button-icon-arrow { .uai-button-icon-arrow {
width: 14px; width: 14px;
margin-left: -10px; margin-left: -10px;
padding-top: 10px; padding-top: 20px;
border-top-right-radius: var(--uai-radius); border-top-right-radius: var(--uai-radius);
border-bottom-right-radius: var(--uai-radius); border-bottom-right-radius: var(--uai-radius);
@@ -807,102 +989,6 @@
} }
} }
.uai-ribbon-heading-container {
width: 321px;
height: 56px;
display: flex;
position: relative;
z-index: 100;
background-color: var(--uai-container-background);
border: solid 1px var(--uai-border-color);
border-radius: var(--uai-radius);
.uai-ribbon-heading-list {
margin: 5px;
display: flex;
flex-wrap: wrap;
max-width: 300px;
overflow: hidden;
}
.uai-ribbon-heading-arrow {
margin-top: 8px;
margin-right: 5px;
padding-top: 8px;
height: 40px;
width: 16px;
border-radius: var(--uai-radius);
&:hover {
cursor: pointer;
background: #ddd; // var(--uai-content-node-selected-background);
border-radius: var(--uai-radius);
}
}
.uai-ribbon-heading-item {
width: 140px;
height: 42px;
margin: 2px;
padding: 0;
text-align: center;
background-color: #fff;
border: solid 1px var(--uai-border-color);
border-radius: var(--uai-radius);
padding: 5px 10px;
box-sizing: border-box;
cursor: pointer;
flex: 0 0 68px;
&:hover,
&.active {
border-color: var(--uai-primary-color);
}
&-title {
line-height: 18px;
font-weight: 600;
&.text {
font-size: 12px;
font-weight: 400;
}
&.h1 {
font-size: 15px;
}
&.h2 {
font-size: 14px;
}
&.h3 {
font-size: 13px;
}
&.h4 {
font-size: 12px;
}
&.h5 {
font-size: 11px;
}
&.h6 {
font-size: 10px;
}
}
&-subtitle {
font-size: 8px;
color: var(--uai-text-color-light);
text-transform: capitalize;
margin-top: 3px;
line-height: 1;
}
}
}
.uai-modal { .uai-modal {
display: none; display: none;
/* 默认隐藏 */ /* 默认隐藏 */
@@ -925,7 +1011,7 @@
.uai-pannel-container { .uai-pannel-container {
background-color: var(--uai-color-white); background-color: var(--uai-color-white);
border-right: solid 1px var(--uai-border-color); border-right: solid 1px var(--uai-border-color);
width: 400px; width: 500px;
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
display: flex; display: flex;
@@ -1139,9 +1225,8 @@
.bubble { .bubble {
padding: 10px; padding: 10px;
display: inline-block; display: inline-block;
height: 100%;
min-height: auto !important; min-height: auto !important;
max-width: calc(100% - 97px); max-width: calc(100% - 120px);
} }
.bubble-sent { .bubble-sent {

View File

@@ -7,6 +7,7 @@
--uai-warning-color: #f6913e; --uai-warning-color: #f6913e;
--uai-error-color: #ef3f35; --uai-error-color: #ef3f35;
// 背景颜色 // 背景颜色
--uai-toolbar-background: #fff;
--uai-container-background: #f4f5f7; --uai-container-background: #f4f5f7;
--uai-button-hover-background: #f1f3f5; --uai-button-hover-background: #f1f3f5;
// 文本选中时的背景颜色 // 文本选中时的背景颜色