feat: add hyperlink

This commit is contained in:
黄云飞
2021-12-22 21:50:11 +08:00
parent a0e12fe509
commit 34d778dcaa
22 changed files with 554 additions and 43 deletions
+136
View File
@@ -0,0 +1,136 @@
import { EditorComponent, EDITOR_COMPONENT } from '../../editor'
import './dialog.css'
export interface IDialogData {
type: string;
label: string;
name: string;
value?: string;
placeholder?: string;
}
export interface IDialogConfirm {
name: string;
value: string;
}
export interface IDialogOptions {
onClose?: () => void;
onCancel?: () => void;
onConfirm?: (payload: IDialogConfirm[]) => void;
title: string;
data: IDialogData[];
}
export class Dialog {
private options: IDialogOptions
private mask: HTMLDivElement | null
private container: HTMLDivElement | null
private inputList: HTMLInputElement[]
constructor(options: IDialogOptions) {
this.options = options
this.mask = null
this.container = null
this.inputList = []
this._render()
}
private _render() {
const { title, data, onClose, onCancel, onConfirm } = this.options
// 渲染遮罩层
const mask = document.createElement('div')
mask.classList.add('dialog-mask')
mask.setAttribute(EDITOR_COMPONENT, EditorComponent.COMPONENT)
document.body.append(mask)
// 渲染容器
const container = document.createElement('div')
container.classList.add('dialog-container')
container.setAttribute(EDITOR_COMPONENT, EditorComponent.COMPONENT)
// 弹窗
const dialogContainer = document.createElement('div')
dialogContainer.classList.add('dialog')
container.append(dialogContainer)
// 标题容器
const titleContainer = document.createElement('div')
titleContainer.classList.add('dialog-title')
// 标题&关闭按钮
const titleSpan = document.createElement('span')
titleSpan.append(document.createTextNode(title))
const titleClose = document.createElement('i')
titleClose.onclick = () => {
if (onClose) {
onClose()
}
this._dispose()
}
titleContainer.append(titleSpan)
titleContainer.append(titleClose)
dialogContainer.append(titleContainer)
// 选项容器
const optionContainer = document.createElement('div')
optionContainer.classList.add('dialog-option')
// 选项
for (let i = 0; i < data.length; i++) {
const option = data[i]
const optionItemContainer = document.createElement('div')
optionItemContainer.classList.add('dialog-option__item')
// 选项名称
const optionName = document.createElement('span')
optionName.append(document.createTextNode(option.label))
optionItemContainer.append(optionName)
// 选项输入框
const optionInput = document.createElement('input')
optionInput.type = option.type
optionInput.name = option.name
optionInput.value = option.value || ''
optionInput.placeholder = option.placeholder || ''
optionItemContainer.append(optionInput)
optionContainer.append(optionItemContainer)
this.inputList.push(optionInput)
}
dialogContainer.append(optionContainer)
// 按钮容器
const menuContainer = document.createElement('div')
menuContainer.classList.add('dialog-menu')
// 取消按钮
const cancelBtn = document.createElement('button')
cancelBtn.classList.add('dialog-menu__cancel')
cancelBtn.append(document.createTextNode('取消'))
cancelBtn.type = 'default'
cancelBtn.onclick = () => {
if (onCancel) {
onCancel()
}
this._dispose()
}
menuContainer.append(cancelBtn)
// 确认按钮
const confirmBtn = document.createElement('button')
confirmBtn.append(document.createTextNode('确定'))
confirmBtn.type = 'primary'
confirmBtn.onclick = () => {
if (onConfirm) {
const payload = this.inputList.map<IDialogConfirm>(input => ({
name: input.name,
value: input.value
}))
onConfirm(payload)
}
this._dispose()
}
menuContainer.append(confirmBtn)
dialogContainer.append(menuContainer)
// 渲染
document.body.append(container)
this.container = container
this.mask = mask
}
private _dispose() {
this.mask?.remove()
this.container?.remove()
}
}
+119
View File
@@ -0,0 +1,119 @@
.dialog-mask {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: .5;
background: #000000;
z-index: 99;
}
.dialog-container {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
z-index: 999;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
.dialog {
position: absolute;
padding: 0 30px 30px;
background: #ffffff;
box-shadow: 0 2px 12px 0 rgb(56 56 56 / 20%);
border: 1px solid #e2e6ed;
border-radius: 2px;
}
.dialog-title {
position: relative;
border-bottom: 1px solid #e2e6ed;
margin-bottom: 30px;
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
}
.dialog-title i {
width: 16px;
height: 16px;
cursor: pointer;
display: inline-block;
background: url(../../assets/images/close.svg);
}
.dialog-option__item {
margin-bottom: 18px;
height: 30px;
display: flex;
align-items: center;
}
.dialog-option__item span {
margin-right: 12px;
font-size: 14px;
color: #3d4757;
}
.dialog-option__item input {
width: 276px;
height: 30px;
border-radius: 2px;
border: 1px solid #d3d3d3;
min-height: 30px;
line-height: 17px;
padding: 5px;
box-sizing: border-box;
outline: none;
appearance: none;
user-select: none;
}
.dialog-option__item input:focus {
border-color: #4991f2;
}
.dialog-menu {
display: flex;
align-items: center;
justify-content: flex-end;
}
.dialog-menu button {
position: relative;
display: inline-block;
border: 1px solid #e2e6ed;
border-radius: 2px;
background: #ffffff;
line-height: 22px;
padding: 0 16px;
white-space: nowrap;
cursor: pointer;
}
.dialog-menu button:hover {
background: rgba(25, 55, 88, .04);
}
.dialog-menu__cancel {
margin-right: 16px;
}
.dialog-menu button[type='primary'] {
color: #ffffff;
background: #4991f2;
border-color: #4991f2;
}
.dialog-menu button[type='primary']:hover {
background: #5b9cf3;
border-color: #5b9cf3;
}