You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
4.5 KiB

import { EditorComponent, EDITOR_COMPONENT } from '../../editor'
import './dialog.css'
export interface IDialogData {
type: string;
label?: string;
name: string;
value?: string;
placeholder?: string;
width?: number;
height?: number;
}
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 | HTMLTextAreaElement)[]
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')
// 选项名称
if (option.label) {
const optionName = document.createElement('span')
optionName.append(document.createTextNode(option.label))
optionItemContainer.append(optionName)
}
// 选项输入框
let optionInput: HTMLInputElement | HTMLTextAreaElement
if (option.type === 'textarea') {
optionInput = document.createElement('textarea')
} else {
optionInput = document.createElement('input')
optionInput.type = option.type
}
if (option.width) {
optionInput.style.width = `${option.width}px`
}
if (option.height) {
optionInput.style.height = `${option.height}px`
}
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()
}
}