From 2739d4069f591306ebad810ed2942a5bd1658b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E4=BA=91=E9=A3=9E?= Date: Fri, 12 Nov 2021 22:22:05 +0800 Subject: [PATCH] feat:rich text editor by canvas --- .gitignore | 5 + README.md | 19 + favicon.png | Bin 0 -> 9311 bytes index.html | 74 +++ package.json | 12 + src/assets/images/bold.svg | 1 + src/assets/images/color.svg | 1 + src/assets/images/deleteline.svg | 1 + src/assets/images/format.svg | 1 + src/assets/images/highlight.svg | 1 + src/assets/images/italic.svg | 1 + src/assets/images/painter.svg | 1 + src/assets/images/print.svg | 1 + src/assets/images/redo.svg | 1 + src/assets/images/search.svg | 1 + src/assets/images/size-add.svg | 1 + src/assets/images/size-minus.svg | 1 + src/assets/images/underline.svg | 1 + src/assets/images/undo.svg | 1 + src/assets/snapshots/main.png | Bin 0 -> 89328 bytes src/editor/assets/css/index.css | 58 +++ src/editor/core/history/HistoryManager.ts | 35 ++ src/editor/dataset/constant/Common.ts | 2 + src/editor/dataset/enum/Keymap.ts | 13 + src/editor/index.ts | 525 ++++++++++++++++++++++ src/editor/interface/Draw.ts | 5 + src/editor/interface/Editor.ts | 10 + src/editor/interface/Element.ts | 28 ++ src/editor/interface/Range.ts | 4 + src/editor/interface/Row.ts | 12 + src/editor/utils/index.ts | 32 ++ src/main.ts | 46 ++ src/style.css | 143 ++++++ src/vite-env.d.ts | 1 + tsconfig.json | 17 + yarn.lock | 196 ++++++++ 36 files changed, 1251 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 favicon.png create mode 100644 index.html create mode 100644 package.json create mode 100644 src/assets/images/bold.svg create mode 100644 src/assets/images/color.svg create mode 100644 src/assets/images/deleteline.svg create mode 100644 src/assets/images/format.svg create mode 100644 src/assets/images/highlight.svg create mode 100644 src/assets/images/italic.svg create mode 100644 src/assets/images/painter.svg create mode 100644 src/assets/images/print.svg create mode 100644 src/assets/images/redo.svg create mode 100644 src/assets/images/search.svg create mode 100644 src/assets/images/size-add.svg create mode 100644 src/assets/images/size-minus.svg create mode 100644 src/assets/images/underline.svg create mode 100644 src/assets/images/undo.svg create mode 100644 src/assets/snapshots/main.png create mode 100644 src/editor/assets/css/index.css create mode 100644 src/editor/core/history/HistoryManager.ts create mode 100644 src/editor/dataset/constant/Common.ts create mode 100644 src/editor/dataset/enum/Keymap.ts create mode 100644 src/editor/index.ts create mode 100644 src/editor/interface/Draw.ts create mode 100644 src/editor/interface/Editor.ts create mode 100644 src/editor/interface/Element.ts create mode 100644 src/editor/interface/Range.ts create mode 100644 src/editor/interface/Row.ts create mode 100644 src/editor/utils/index.ts create mode 100644 src/main.ts create mode 100644 src/style.css create mode 100644 src/vite-env.d.ts create mode 100644 tsconfig.json create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..53f7466 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules +.DS_Store +dist +dist-ssr +*.local \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..54955c9 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +

canvas-editor

+ +

a rich text editor by canvas

+ +## snapshot + +![image](https://github.com/Hufe921/canvas-editor/blob/main/src/assets/snapshots/main.png) + +## install + +`yarn` + +## dev + +`yarn run dev` + +## build + +`yarn run build` diff --git a/favicon.png b/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..d05e47097ba39b5b127b1edb8e85373d08e5267d GIT binary patch literal 9311 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 OfV#5Q^SWo2@BbGdB5|Am literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..d1acbbb --- /dev/null +++ b/index.html @@ -0,0 +1,74 @@ + + + + + + + + canvas-editor + + + +
+ +
+ +
+
+ + + + \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..c93f08a --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "version": "0.0.1", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "serve": "vite preview" + }, + "devDependencies": { + "typescript": "^4.3.2", + "vite": "^2.4.2" + } +} \ No newline at end of file diff --git a/src/assets/images/bold.svg b/src/assets/images/bold.svg new file mode 100644 index 0000000..80728d0 --- /dev/null +++ b/src/assets/images/bold.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/color.svg b/src/assets/images/color.svg new file mode 100644 index 0000000..2b84e88 --- /dev/null +++ b/src/assets/images/color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/deleteline.svg b/src/assets/images/deleteline.svg new file mode 100644 index 0000000..c2c83ca --- /dev/null +++ b/src/assets/images/deleteline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/format.svg b/src/assets/images/format.svg new file mode 100644 index 0000000..aae6e6b --- /dev/null +++ b/src/assets/images/format.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/highlight.svg b/src/assets/images/highlight.svg new file mode 100644 index 0000000..c4b2e8b --- /dev/null +++ b/src/assets/images/highlight.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/italic.svg b/src/assets/images/italic.svg new file mode 100644 index 0000000..73b2af5 --- /dev/null +++ b/src/assets/images/italic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/painter.svg b/src/assets/images/painter.svg new file mode 100644 index 0000000..a865d1d --- /dev/null +++ b/src/assets/images/painter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/print.svg b/src/assets/images/print.svg new file mode 100644 index 0000000..5ee44a0 --- /dev/null +++ b/src/assets/images/print.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/redo.svg b/src/assets/images/redo.svg new file mode 100644 index 0000000..fc88331 --- /dev/null +++ b/src/assets/images/redo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/search.svg b/src/assets/images/search.svg new file mode 100644 index 0000000..9d515dc --- /dev/null +++ b/src/assets/images/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/size-add.svg b/src/assets/images/size-add.svg new file mode 100644 index 0000000..aa1073c --- /dev/null +++ b/src/assets/images/size-add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/size-minus.svg b/src/assets/images/size-minus.svg new file mode 100644 index 0000000..7bfa958 --- /dev/null +++ b/src/assets/images/size-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/underline.svg b/src/assets/images/underline.svg new file mode 100644 index 0000000..dcd81b0 --- /dev/null +++ b/src/assets/images/underline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/undo.svg b/src/assets/images/undo.svg new file mode 100644 index 0000000..820f852 --- /dev/null +++ b/src/assets/images/undo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/snapshots/main.png b/src/assets/snapshots/main.png new file mode 100644 index 0000000000000000000000000000000000000000..49741f39f0dbcc172b3ceff448bcccd9fd53a298 GIT binary patch literal 89328 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 = [] + private redoStack: Array = [] + + undo() { + if (this.undoStack.length > 1) { + const pop = this.undoStack.pop()! + this.redoStack.push(pop) + if (this.undoStack.length) { + this.undoStack[this.undoStack.length - 1]() + } + } + } + + redo() { + if (this.redoStack.length) { + const pop = this.redoStack.pop()! + this.undoStack.push(pop) + pop() + } + } + + execute(fn: Function) { + this.undoStack.push(fn) + if (this.redoStack.length) { + this.redoStack = [] + } + while (this.undoStack.length > this.MAX_RECORD_COUNT) { + this.undoStack.shift() + } + } + +} \ No newline at end of file diff --git a/src/editor/dataset/constant/Common.ts b/src/editor/dataset/constant/Common.ts new file mode 100644 index 0000000..6d915ad --- /dev/null +++ b/src/editor/dataset/constant/Common.ts @@ -0,0 +1,2 @@ +export const ZERO = '\u200B' +export const WRAP = '\n' \ No newline at end of file diff --git a/src/editor/dataset/enum/Keymap.ts b/src/editor/dataset/enum/Keymap.ts new file mode 100644 index 0000000..a293df2 --- /dev/null +++ b/src/editor/dataset/enum/Keymap.ts @@ -0,0 +1,13 @@ +export enum KeyMap { + Backspace = 'Backspace', + Enter = "Enter", + Left = "ArrowLeft", + Right = "ArrowRight", + Up = "ArrowUp", + Down = "ArrowDown", + A = "a", + C = "c", + X = "x", + Y = "y", + Z = "z" +} \ No newline at end of file diff --git a/src/editor/index.ts b/src/editor/index.ts new file mode 100644 index 0000000..e4908c9 --- /dev/null +++ b/src/editor/index.ts @@ -0,0 +1,525 @@ +import './assets/css/index.css' +import { ZERO } from './dataset/constant/Common' +import { KeyMap } from './dataset/enum/Keymap' +import { deepClone, writeText } from './utils' +import { HistoryManager } from './core/history/HistoryManager' +import { IRange } from './interface/Range' +import { IRow } from './interface/Row' +import { IDrawOption } from './interface/Draw' +import { IEditorOption } from './interface/Editor' +import { IElement, IElementPosition } from './interface/Element' + +export default class Editor { + + private readonly defaultOptions: Required = { + defaultType: 'TEXT', + defaultFont: 'Yahei', + defaultSize: 16, + rangeAlpha: 0.6, + rangeColor: '#AECBFA', + marginIndicatorSize: 35, + marginIndicatorColor: '#BABABA', + margins: [100, 120, 100, 120] + } + + private canvas: HTMLCanvasElement + private ctx: CanvasRenderingContext2D + + private options: Required + private elementList: IElement[] + private position: IElementPosition[] + private range: IRange + + private cursorPosition: IElementPosition | null + private cursorDom: HTMLDivElement + private textareaDom: HTMLTextAreaElement + private isCompositing: boolean + private isAllowDrag: boolean + private rowCount: number + private mouseDownStartIndex: number + + private historyManager: HistoryManager + + constructor(canvas: HTMLCanvasElement, data: IElement[], options: IEditorOption = {}) { + this.options = { + ...this.defaultOptions, + ...options + }; + const ctx = canvas.getContext('2d') + const dpr = window.devicePixelRatio; + canvas.width = parseInt(canvas.style.width) * dpr; + canvas.height = parseInt(canvas.style.height) * dpr; + canvas.style.cursor = 'text' + this.canvas = canvas + this.ctx = ctx as CanvasRenderingContext2D + this.ctx.scale(dpr, dpr) + this.elementList = [] + this.position = [] + this.cursorPosition = null + this.isCompositing = false + this.isAllowDrag = false + this.range = { + startIndex: 0, + endIndex: 0 + } + this.rowCount = 0 + this.mouseDownStartIndex = 0 + + // 历史管理 + this.historyManager = new HistoryManager() + + // 全局事件 + document.addEventListener('click', (evt) => { + const innerDoms = [this.canvas, this.cursorDom, this.textareaDom, document.body] + if (innerDoms.includes(evt.target as any)) return + this.recoveryCursor() + }) + document.addEventListener('mouseup', () => { + this.isAllowDrag = false + }) + + // 事件监听转发 + const textarea = document.createElement('textarea') + textarea.autocomplete = 'off' + textarea.classList.add('inputarea') + textarea.innerText = '' + textarea.onkeydown = (evt: KeyboardEvent) => this.handleKeydown(evt) + textarea.oninput = (evt: Event) => { + const data = (evt as InputEvent).data + setTimeout(() => this.handleInput(data || '')) + } + textarea.onpaste = (evt: ClipboardEvent) => this.handlePaste(evt) + textarea.addEventListener('compositionstart', this.handleCompositionstart.bind(this)) + textarea.addEventListener('compositionend', this.handleCompositionend.bind(this)) + this.canvas.parentNode?.append(textarea) + this.textareaDom = textarea + + // 光标 + this.cursorDom = document.createElement('div') + this.cursorDom.classList.add('cursor') + this.canvas.parentNode?.append(this.cursorDom) + + // canvas原生事件 + canvas.addEventListener('mousedown', this.setCursor.bind(this)) + canvas.addEventListener('mousedown', this.handleMousedown.bind(this)) + canvas.addEventListener('mouseleave', this.handleMouseleave.bind(this)) + canvas.addEventListener('mousemove', this.handleMousemove.bind(this)) + + // 启动 + const isZeroStart = data[0].value === ZERO + if (!isZeroStart) { + data.unshift({ + value: ZERO + }) + } + data.forEach(text => { + if (text.value === '\n') { + text.value = ZERO + } + }) + this.elementList = data + this.draw() + } + + private draw(options?: IDrawOption) { + let { curIndex, isSubmitHistory = true, isSetCursor = true } = options || {} + // 清除光标 + this.recoveryCursor() + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) + this.position = [] + // 基础信息 + const { defaultSize, defaultFont, margins, marginIndicatorColor, marginIndicatorSize } = this.options + const canvasRect = this.canvas.getBoundingClientRect() + const canvasWidth = canvasRect.width + const canvasHeight = canvasRect.height + // 绘制页边距 + this.ctx.save() + this.ctx.strokeStyle = marginIndicatorColor + this.ctx.beginPath() + const leftTopPoint: [number, number] = [margins[3], margins[0]] + const rightTopPoint: [number, number] = [canvasWidth - margins[1], margins[0]] + const leftBottomPoint: [number, number] = [margins[3], canvasHeight - margins[2]] + const rightBottomPoint: [number, number] = [canvasWidth - margins[1], canvasHeight - margins[2]] + // 上左 + this.ctx.moveTo(leftTopPoint[0] - marginIndicatorSize, leftTopPoint[1]) + this.ctx.lineTo(...leftTopPoint) + this.ctx.lineTo(leftTopPoint[0], leftTopPoint[1] - marginIndicatorSize) + // 上右 + this.ctx.moveTo(rightTopPoint[0] + marginIndicatorSize, rightTopPoint[1]) + this.ctx.lineTo(...rightTopPoint) + this.ctx.lineTo(rightTopPoint[0], rightTopPoint[1] - marginIndicatorSize) + // 下左 + this.ctx.moveTo(leftBottomPoint[0] - marginIndicatorSize, leftBottomPoint[1]) + this.ctx.lineTo(...leftBottomPoint) + this.ctx.lineTo(leftBottomPoint[0], leftBottomPoint[1] + marginIndicatorSize) + // 下右 + this.ctx.moveTo(rightBottomPoint[0] + marginIndicatorSize, rightBottomPoint[1]) + this.ctx.lineTo(...rightBottomPoint) + this.ctx.lineTo(rightBottomPoint[0], rightBottomPoint[1] + marginIndicatorSize) + this.ctx.stroke() + this.ctx.restore() + // 计算行信息 + const rowList: IRow[] = [] + if (this.elementList.length) { + rowList.push({ + width: 0, + height: 0, + ascent: 0, + elementList: [] + }) + } + for (let i = 0; i < this.elementList.length; i++) { + this.ctx.save() + const curRow: IRow = rowList[rowList.length - 1] + const element = this.elementList[i] + this.ctx.font = `${element.bold ? 'bold ' : ''}${element.size || defaultSize}px ${element.font || defaultFont}` + const metrics = this.ctx.measureText(element.value) + const width = metrics.width + const fontBoundingBoxAscent = metrics.fontBoundingBoxAscent + const fontBoundingBoxDescent = metrics.fontBoundingBoxDescent + const height = fontBoundingBoxAscent + fontBoundingBoxDescent + const lineText = { ...element, metrics } + if (curRow.width + width > rightTopPoint[0] - leftTopPoint[0] || (i !== 0 && element.value === ZERO)) { + rowList.push({ + width, + height: 0, + elementList: [lineText], + ascent: fontBoundingBoxAscent + }) + } else { + curRow.width += width + if (curRow.height < height) { + curRow.height = height + curRow.ascent = fontBoundingBoxAscent + } + curRow.elementList.push(lineText) + } + this.ctx.restore() + } + // 渲染元素 + let x = leftTopPoint[0] + let y = leftTopPoint[1] + let index = 0 + for (let i = 0; i < rowList.length; i++) { + const curRow = rowList[i]; + for (let j = 0; j < curRow.elementList.length; j++) { + this.ctx.save() + const element = curRow.elementList[j]; + const metrics = element.metrics + this.ctx.font = `${element.bold ? 'bold ' : ''}${element.size || defaultSize}px ${element.font || defaultFont}` + if (element.color) { + this.ctx.fillStyle = element.color + } + const positionItem: IElementPosition = { + index, + value: element.value, + rowNo: i, + metrics, + lineHeight: curRow.height, + isLastLetter: j === curRow.elementList.length - 1, + coordinate: { + leftTop: [x, y], + leftBottom: [x, y + curRow.height], + rightTop: [x + metrics.width, y], + rightBottom: [x + metrics.width, y + curRow.height] + } + } + this.position.push(positionItem) + this.ctx.fillText(element.value, x, y + curRow.ascent) + // 选区绘制 + const { startIndex, endIndex } = this.range + if (startIndex !== endIndex && startIndex < index && index <= endIndex) { + this.ctx.save() + this.ctx.globalAlpha = this.options.rangeAlpha + this.ctx.fillStyle = this.options.rangeColor + this.ctx.fillRect(x, y, metrics.width, curRow.height) + this.ctx.restore() + } + index++ + x += metrics.width + this.ctx.restore() + } + x = leftTopPoint[0] + y += curRow.height + } + // 光标重绘 + if (curIndex === undefined) { + curIndex = this.position.length - 1 + } + if (isSetCursor) { + this.cursorPosition = this.position[curIndex!] || null + this.drawCursor() + } + // canvas高度自适应计算 + const lastPosition = this.position[this.position.length - 1] + const { coordinate: { leftBottom, leftTop } } = lastPosition + if (leftBottom[1] > this.canvas.height) { + const height = Math.ceil(leftBottom[1] + (leftBottom[1] - leftTop[1])) + this.canvas.height = height + this.canvas.style.height = `${height}px` + this.draw({ curIndex, isSubmitHistory: false }) + } + this.rowCount = rowList.length + // 历史记录用于undo、redo + if (isSubmitHistory) { + const self = this + const oldelementList = deepClone(this.elementList) + this.historyManager.execute(function () { + self.elementList = deepClone(oldelementList) + self.draw({ curIndex, isSubmitHistory: false }) + }) + } + } + + private getCursorPosition(evt: MouseEvent): number { + const x = evt.offsetX + const y = evt.offsetY + let isTextArea = false + for (let j = 0; j < this.position.length; j++) { + const { index, coordinate: { leftTop, rightTop, leftBottom } } = this.position[j]; + // 命中元素 + if (leftTop[0] <= x && rightTop[0] >= x && leftTop[1] <= y && leftBottom[1] >= y) { + let curPostionIndex = j + // 判断是否元素中间前后 + if (this.elementList[index].value !== ZERO) { + const valueWidth = rightTop[0] - leftTop[0] + if (x < leftTop[0] + valueWidth / 2) { + curPostionIndex = j - 1 + } + } + isTextArea = true + return curPostionIndex + } + } + // 非命中区域 + if (!isTextArea) { + let isLastArea = false + let curPostionIndex = -1 + // 判断所属行是否存在元素 + const firstLetterList = this.position.filter(p => p.isLastLetter) + for (let j = 0; j < firstLetterList.length; j++) { + const { index, coordinate: { leftTop, leftBottom } } = firstLetterList[j] + if (y > leftTop[1] && y <= leftBottom[1]) { + curPostionIndex = index + isLastArea = true + break + } + } + if (!isLastArea) { + return this.position.length - 1 + } + return curPostionIndex + } + return -1 + } + + private setCursor(evt: MouseEvent) { + const positionIndex = this.getCursorPosition(evt) + if (~positionIndex) { + this.range.startIndex = 0 + this.range.endIndex = 0 + setTimeout(() => { + this.draw({ curIndex: positionIndex, isSubmitHistory: false }) + }) + } + } + + private drawCursor() { + if (!this.cursorPosition) return + // 设置光标代理 + const { lineHeight, metrics, coordinate: { rightTop } } = this.cursorPosition + const height = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent + this.textareaDom.focus() + this.textareaDom.setSelectionRange(0, 0) + const lineBottom = rightTop[1] + lineHeight + const curosrleft = `${rightTop[0]}px` + this.textareaDom.style.left = curosrleft + this.textareaDom.style.top = `${lineBottom - 12}px` + // 模拟光标显示 + this.cursorDom.style.left = curosrleft + this.cursorDom.style.top = `${lineBottom - height}px` + this.cursorDom.style.display = 'block' + this.cursorDom.style.height = `${height}px` + setTimeout(() => { + this.cursorDom.classList.add('cursor--animation') + }, 200) + } + + private recoveryCursor() { + this.cursorDom.style.display = 'none' + this.cursorDom.classList.remove('cursor--animation') + } + + private strokeRange() { + this.draw({ + isSubmitHistory: false, + isSetCursor: false + }) + } + + private clearRange() { + this.range.startIndex = 0 + this.range.endIndex = 0 + } + + private handleMousemove(evt: MouseEvent) { + if (!this.isAllowDrag) return + // 结束位置 + const endIndex = this.getCursorPosition(evt) + let end = ~endIndex ? endIndex : 0 + // 开始位置 + let start = this.mouseDownStartIndex + if (start > end) { + [start, end] = [end, start] + } + this.range.startIndex = start + this.range.endIndex = end + if (start === end) return + // 绘制选区 + this.strokeRange() + } + + private handleMousedown(evt: MouseEvent) { + this.isAllowDrag = true + this.mouseDownStartIndex = this.getCursorPosition(evt) || 0 + } + + private handleMouseleave(evt: MouseEvent) { + // 是否还在canvas内部 + const { x, y, width, height } = this.canvas.getBoundingClientRect() + if (evt.x >= x && evt.x <= x + width && evt.y >= y && evt.y <= y + height) return + this.isAllowDrag = false + } + + private handleKeydown(evt: KeyboardEvent) { + if (!this.cursorPosition) return + const { index } = this.cursorPosition + const { startIndex, endIndex } = this.range + const isCollspace = startIndex === endIndex + if (evt.key === KeyMap.Backspace) { + // 判断是否允许删除 + if (this.elementList[index].value === ZERO && index === 0) { + evt.preventDefault() + return + } + if (!isCollspace) { + this.elementList.splice(startIndex + 1, endIndex - startIndex) + } else { + this.elementList.splice(index, 1) + } + this.clearRange() + this.draw({ curIndex: isCollspace ? index - 1 : startIndex }) + } else if (evt.key === KeyMap.Enter) { + const enterText: IElement = { + value: ZERO + } + if (isCollspace) { + this.elementList.splice(index + 1, 0, enterText) + } else { + this.elementList.splice(startIndex + 1, endIndex - startIndex, enterText) + } + this.clearRange() + this.draw({ curIndex: index + 1 }) + } else if (evt.key === KeyMap.Left) { + if (index > 0) { + this.clearRange() + this.draw({ curIndex: index - 1, isSubmitHistory: false }) + } + } else if (evt.key === KeyMap.Right) { + if (index < this.position.length - 1) { + this.clearRange() + this.draw({ curIndex: index + 1, isSubmitHistory: false }) + } + } else if (evt.key === KeyMap.Up || evt.key === KeyMap.Down) { + const { rowNo, index, coordinate: { leftTop, rightTop } } = this.cursorPosition + if ((evt.key === KeyMap.Up && rowNo !== 0) || (evt.key === KeyMap.Down && rowNo !== this.rowCount)) { + // 下一个光标点所在行位置集合 + const probablePosition = evt.key === KeyMap.Up + ? this.position.slice(0, index).filter(p => p.rowNo === rowNo - 1) + : this.position.slice(index, this.position.length - 1).filter(p => p.rowNo === rowNo + 1) + // 查找与当前位置元素点交叉最多的位置 + let maxIndex = 0 + let maxDistance = 0 + for (let p = 0; p < probablePosition.length; p++) { + const position = probablePosition[p] + // 当前光标在前 + if (position.coordinate.leftTop[0] >= leftTop[0] && position.coordinate.leftTop[0] <= rightTop[0]) { + const curDistance = rightTop[0] - position.coordinate.leftTop[0] + if (curDistance > maxDistance) { + maxIndex = position.index + maxDistance = curDistance + } + } + // 当前光标在后 + else if (position.coordinate.leftTop[0] <= leftTop[0] && position.coordinate.rightTop[0] >= leftTop[0]) { + const curDistance = position.coordinate.rightTop[0] - leftTop[0] + if (curDistance > maxDistance) { + maxIndex = position.index + maxDistance = curDistance + } + } + // 匹配不到 + if (p === probablePosition.length - 1 && maxIndex === 0) { + maxIndex = position.index + } + } + this.clearRange() + this.draw({ curIndex: maxIndex, isSubmitHistory: false }) + } + } else if (evt.ctrlKey && evt.key === KeyMap.Z) { + this.historyManager.undo() + evt.preventDefault() + } else if (evt.ctrlKey && evt.key === KeyMap.Y) { + this.historyManager.redo() + evt.preventDefault() + } else if (evt.ctrlKey && evt.key === KeyMap.C) { + if (!isCollspace) { + writeText(this.elementList.slice(startIndex + 1, endIndex + 1).map(p => p.value).join('')) + } + } else if (evt.ctrlKey && evt.key === KeyMap.X) { + if (!isCollspace) { + writeText(this.position.slice(startIndex + 1, endIndex + 1).map(p => p.value).join('')) + this.elementList.splice(startIndex + 1, endIndex - startIndex) + this.clearRange() + this.draw({ curIndex: startIndex }) + } + } else if (evt.ctrlKey && evt.key === KeyMap.A) { + this.range.startIndex = 0 + this.range.endIndex = this.position.length - 1 + this.draw({ isSubmitHistory: false, isSetCursor: false }) + } + } + + private handleInput(data: string) { + if (!data || !this.cursorPosition || this.isCompositing) return + this.textareaDom.value = '' + const { index } = this.cursorPosition + const { startIndex, endIndex } = this.range + const isCollspace = startIndex === endIndex + const inputData: IElement[] = data.split('').map(value => ({ + value + })) + if (isCollspace) { + this.elementList.splice(index + 1, 0, ...inputData) + } else { + this.elementList.splice(startIndex + 1, endIndex - startIndex, ...inputData) + } + this.clearRange() + this.draw({ curIndex: (isCollspace ? index : startIndex) + inputData.length }) + } + + private handlePaste(evt: ClipboardEvent) { + const text = evt.clipboardData?.getData('text') + this.handleInput(text || '') + evt.preventDefault() + } + + private handleCompositionstart() { + this.isCompositing = true + } + + private handleCompositionend() { + this.isCompositing = false + } + +} \ No newline at end of file diff --git a/src/editor/interface/Draw.ts b/src/editor/interface/Draw.ts new file mode 100644 index 0000000..ac0253b --- /dev/null +++ b/src/editor/interface/Draw.ts @@ -0,0 +1,5 @@ +export interface IDrawOption { + curIndex?: number; + isSetCursor?: boolean + isSubmitHistory?: boolean; +} \ No newline at end of file diff --git a/src/editor/interface/Editor.ts b/src/editor/interface/Editor.ts new file mode 100644 index 0000000..aac9221 --- /dev/null +++ b/src/editor/interface/Editor.ts @@ -0,0 +1,10 @@ +export interface IEditorOption { + defaultType?: string; + defaultFont?: string; + defaultSize?: number; + rangeColor?: string; + rangeAlpha?: number; + marginIndicatorSize?: number; + marginIndicatorColor?: string, + margins?: [top: number, right: number, bootom: number, left: number] +} \ No newline at end of file diff --git a/src/editor/interface/Element.ts b/src/editor/interface/Element.ts new file mode 100644 index 0000000..9111d7a --- /dev/null +++ b/src/editor/interface/Element.ts @@ -0,0 +1,28 @@ +export interface IElement { + type?: 'TEXT' | 'IMAGE'; + value: string; + font?: string; + size?: number; + width?: number; + height?: number; + bold?: boolean; + color?: string; + italic?: boolean; + underline?: boolean; + strikeout?: boolean; +} + +export interface IElementPosition { + index: number; + value: string, + rowNo: number; + lineHeight: number; + metrics: TextMetrics; + isLastLetter: boolean, + coordinate: { + leftTop: number[]; + leftBottom: number[]; + rightTop: number[]; + rightBottom: number[]; + } +} \ No newline at end of file diff --git a/src/editor/interface/Range.ts b/src/editor/interface/Range.ts new file mode 100644 index 0000000..6d9c85b --- /dev/null +++ b/src/editor/interface/Range.ts @@ -0,0 +1,4 @@ +export interface IRange { + startIndex: number; + endIndex: number +} \ No newline at end of file diff --git a/src/editor/interface/Row.ts b/src/editor/interface/Row.ts new file mode 100644 index 0000000..af8d44b --- /dev/null +++ b/src/editor/interface/Row.ts @@ -0,0 +1,12 @@ +import { IElement } from "./Element"; + +export type IRowElement = IElement & { + metrics: TextMetrics +} + +export interface IRow { + width: number; + height: number; + ascent: number; + elementList: IRowElement[]; +} diff --git a/src/editor/utils/index.ts b/src/editor/utils/index.ts new file mode 100644 index 0000000..ccbc23f --- /dev/null +++ b/src/editor/utils/index.ts @@ -0,0 +1,32 @@ +import { ZERO } from "../dataset/constant/Common" + +export function debounce(func: Function, delay: number) { + let timer: number + return function (...args: any) { + if (timer) clearTimeout(timer) + timer = setTimeout(() => { + // @ts-ignore + func.apply(this, args) + }, delay) + } +} + +export function writeText(text: string) { + if (!text) return + window.navigator.clipboard.writeText(text.replaceAll(ZERO, `\n`)) +} + +export function deepClone(obj: any) { + if (!obj || typeof obj !== 'object') { + return obj; + } + let newObj: any = {}; + if (Array.isArray(obj)) { + newObj = obj.map(item => deepClone(item)); + } else { + Object.keys(obj).forEach((key) => { + return newObj[key] = deepClone(obj[key]); + }) + } + return newObj; +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..493ace7 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,46 @@ +import './style.css' +import Editor from './editor' + +window.onload = function () { + const canvas = document.querySelector('canvas') + if (!canvas) return + const text = `\n主诉:\n发热三天,咳嗽五天。\n现病史:\n发病前14天内有病历报告社区的旅行时或居住史;发病前14天内与新型冠状病毒感染的患者或无症状感染者有接触史;发病前14天内解除过来自病历报告社区的发热或有呼吸道症状的患者;聚集性发病,2周内在小范围如家庭、办公室、学校班级等场所,出现2例及以上发热或呼吸道症状的病例。\n既往史:\n有糖尿病10年,有高血压2年,有传染性疾病1年。\n体格检查:\nT:36.5℃,P:80bpm,R:20次/分,BP:120/80mmHg;\n辅助检查:\n2020年6月10日,普放:血细胞比容36.50%(偏低)40~50;单核细胞绝对值0.75*10^9/L(偏高)参考值:0.1~0.6;\n门诊诊断:\n1.高血压\n处置治疗:\n1.超声引导下甲状腺细针穿刺术;\n2.乙型肝炎表面抗体测定;\n3.膜式病变细胞采集术、后颈皮下肤层;\n4.氯化钠注射液 250ml/袋、1袋;\n5.七叶皂苷钠片(欧开)、30mg/片*24/盒、1片、口服、BID(每日两次)、1天` + // 模拟加粗字 + const boldText = ['主诉:', '现病史:', '既往史:', '体格检查:', '辅助检查:', '门诊诊断:', '处置治疗:'] + const boldIndex: number[] = boldText.map(b => { + const i = text.indexOf(b) + return ~i ? Array(b.length).fill(i).map((_, j) => i + j) : [] + }).flat() + // 模拟颜色字 + const colorText = ['传染性疾病'] + const colorIndex: number[] = colorText.map(b => { + const i = text.indexOf(b) + return ~i ? Array(b.length).fill(i).map((_, j) => i + j) : [] + }).flat() + // 组合数据 + const data = text.split('').map((value, index) => { + if (boldIndex.includes(index)) { + return { + value, + size: 18, + bold: true + } + } + if (colorIndex.includes(index)) { + return { + value, + color: 'red', + size: 16 + } + } + return { + value, + size: 16 + } + }) + // 初始化编辑器 + const instance = new Editor(canvas, data, { + margins: [120, 120, 200, 120] + }) + console.log('编辑器实例: ', instance); +} \ No newline at end of file diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..b36f06a --- /dev/null +++ b/src/style.css @@ -0,0 +1,143 @@ +* { + margin: 0; + padding: 0; +} + +body { + background-color: #F2F4F7; +} + +.menu { + width: 100%; + height: 60px; + top: 0; + z-index: 9; + position: fixed; + display: flex; + align-items: center; + justify-content: center; + background: #F2F4F7; + box-shadow: 0 2px 4px 0 transparent; +} + +.menu-divider { + width: 1px; + height: 16px; + margin: 0 6px; + display: inline-block; + background-color: #cfd2d8; +} + +.menu-item { + height: 24px; + display: flex; + align-items: center; +} + +.menu-item>div { + width: 24px; + height: 24px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + margin: 0 6px; +} + +.menu-item>div:hover { + background: rgba(25, 55, 88, .04); +} + +.menu-item i { + width: 16px; + height: 16px; + display: inline-block; + background-repeat: no-repeat; + background-size: 100% 100%; +} + +.menu-item>div span { + width: 16px; + height: 3px; + display: inline-block; + border: 1px solid #e2e6ed; +} + +.menu-item__undo i { + background-image: url('./assets/images/undo.svg'); +} + +.menu-item__redo i { + background-image: url('./assets/images/redo.svg'); +} + +.menu-item__painter i { + background-image: url('./assets/images/painter.svg'); +} + +.menu-item__format i { + background-image: url('./assets/images/format.svg'); +} + +.menu-item__size-add i { + background-image: url('./assets/images/size-add.svg'); +} + +.menu-item__size-minus i { + background-image: url('./assets/images/size-minus.svg'); +} + +.menu-item__bold i { + background-image: url('./assets/images/bold.svg'); +} + +.menu-item__italic i { + background-image: url('./assets/images/italic.svg'); +} + +.menu-item__underline i { + background-image: url('./assets/images/underline.svg'); +} + +.menu-item__deleteline i { + background-image: url('./assets/images/deleteline.svg'); +} + +.menu-item__color, +.menu-item__highlight { + display: flex; + flex-direction: column; +} + +.menu-item__color i { + background-image: url('./assets/images/color.svg'); +} + +.menu-item__color span { + background-color: #000000; +} + +.menu-item__highlight i { + background-image: url('./assets/images/highlight.svg'); +} + +.menu-item__highlight span { + background-color: #ffff00; +} + +.menu-item__search i { + background-image: url('./assets/images/search.svg'); +} + +.menu-item__print i { + background-image: url('./assets/images/print.svg'); +} + +.editor { + width: 794px; + height: 1123px; + margin: 80px auto; + position: relative; + background-color: #ffffff; + box-shadow: rgb(158 161 165 / 40%) 0px 2px 12px 0px; +} \ No newline at end of file diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4824d01 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "lib": ["ESNext", "DOM"], + "moduleResolution": "Node", + "strict": true, + "sourceMap": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "noEmit": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true + }, + "include": ["./src"] +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..7db1408 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,196 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +esbuild-android-arm64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.13.tgz#da07b5fb2daf7d83dcd725f7cf58a6758e6e702a" + integrity sha512-T02aneWWguJrF082jZworjU6vm8f4UQ+IH2K3HREtlqoY9voiJUwHLRL6khRlsNLzVglqgqb7a3HfGx7hAADCQ== + +esbuild-darwin-64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.13.tgz#e94e9fd3b4b5455a2e675cd084a19a71b6904bbf" + integrity sha512-wkaiGAsN/09X9kDlkxFfbbIgR78SNjMOfUhoel3CqKBDsi9uZhw7HBNHNxTzYUK8X8LAKFpbODgcRB3b/I8gHA== + +esbuild-darwin-arm64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.13.tgz#8c320eafbb3ba2c70d8062128c5b71503e342471" + integrity sha512-b02/nNKGSV85Gw9pUCI5B48AYjk0vFggDeom0S6QMP/cEDtjSh1WVfoIFNAaLA0MHWfue8KBwoGVsN7rBshs4g== + +esbuild-freebsd-64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.13.tgz#ce0ca5b8c4c274cfebc9326f9b316834bd9dd151" + integrity sha512-ALgXYNYDzk9YPVk80A+G4vz2D22Gv4j4y25exDBGgqTcwrVQP8rf/rjwUjHoh9apP76oLbUZTmUmvCMuTI1V9A== + +esbuild-freebsd-arm64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.13.tgz#463da17562fdcfdf03b3b94b28497d8d8dcc8f62" + integrity sha512-uFvkCpsZ1yqWQuonw5T1WZ4j59xP/PCvtu6I4pbLejhNo4nwjW6YalqnBvBSORq5/Ifo9S/wsIlVHzkzEwdtlw== + +esbuild-linux-32@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.13.tgz#2035793160da2c4be48a929e5bafb14a31789acc" + integrity sha512-yxR9BBwEPs9acVEwTrEE2JJNHYVuPQC9YGjRfbNqtyfK/vVBQYuw8JaeRFAvFs3pVJdQD0C2BNP4q9d62SCP4w== + +esbuild-linux-64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.13.tgz#fbe4802a8168c6d339d0749f977b099449b56f22" + integrity sha512-kzhjlrlJ+6ESRB/n12WTGll94+y+HFeyoWsOrLo/Si0s0f+Vip4b8vlnG0GSiS6JTsWYAtGHReGczFOaETlKIw== + +esbuild-linux-arm64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.13.tgz#f08d98df28d436ed4aad1529615822bb74d4d978" + integrity sha512-KMrEfnVbmmJxT3vfTnPv/AiXpBFbbyExH13BsUGy1HZRPFMi5Gev5gk8kJIZCQSRfNR17aqq8sO5Crm2KpZkng== + +esbuild-linux-arm@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.13.tgz#6f968c3a98b64e30c80b212384192d0cfcb32e7f" + integrity sha512-hXub4pcEds+U1TfvLp1maJ+GHRw7oizvzbGRdUvVDwtITtjq8qpHV5Q5hWNNn6Q+b3b2UxF03JcgnpzCw96nUQ== + +esbuild-linux-mips64le@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.13.tgz#690c78dc4725efe7d06a1431287966fbf7774c7f" + integrity sha512-cJT9O1LYljqnnqlHaS0hdG73t7hHzF3zcN0BPsjvBq+5Ad47VJun+/IG4inPhk8ta0aEDK6LdP+F9299xa483w== + +esbuild-linux-ppc64le@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.13.tgz#7ec9048502de46754567e734aae7aebd2df6df02" + integrity sha512-+rghW8st6/7O6QJqAjVK3eXzKkZqYAw6LgHv7yTMiJ6ASnNvghSeOcIvXFep3W2oaJc35SgSPf21Ugh0o777qQ== + +esbuild-netbsd-64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.13.tgz#439bdaefffa03a8fa84324f5d83d636f548a2de3" + integrity sha512-A/B7rwmzPdzF8c3mht5TukbnNwY5qMJqes09ou0RSzA5/jm7Jwl/8z853ofujTFOLhkNHUf002EAgokzSgEMpQ== + +esbuild-openbsd-64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.13.tgz#c9958e5291a00a3090c1ec482d6bcdf2d5b5d107" + integrity sha512-szwtuRA4rXKT3BbwoGpsff6G7nGxdKgUbW9LQo6nm0TVCCjDNDC/LXxT994duIW8Tyq04xZzzZSW7x7ttDiw1w== + +esbuild-sunos-64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.13.tgz#ac9ead8287379cd2f6d00bd38c5997fda9c1179e" + integrity sha512-ihyds9O48tVOYF48iaHYUK/boU5zRaLOXFS+OOL3ceD39AyHo46HVmsJLc7A2ez0AxNZCxuhu+P9OxfPfycTYQ== + +esbuild-windows-32@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.13.tgz#a3820fc86631ca594cb7b348514b5cc3f058cfd6" + integrity sha512-h2RTYwpG4ldGVJlbmORObmilzL8EECy8BFiF8trWE1ZPHLpECE9//J3Bi+W3eDUuv/TqUbiNpGrq4t/odbayUw== + +esbuild-windows-64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.13.tgz#1da748441f228d75dff474ddb7d584b81887323c" + integrity sha512-oMrgjP4CjONvDHe7IZXHrMk3wX5Lof/IwFEIbwbhgbXGBaN2dke9PkViTiXC3zGJSGpMvATXVplEhlInJ0drHA== + +esbuild-windows-arm64@0.13.13: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.13.tgz#06dfa52a6b178a5932a9a6e2fdb240c09e6da30c" + integrity sha512-6fsDfTuTvltYB5k+QPah/x7LrI2+OLAJLE3bWLDiZI6E8wXMQU+wLqtEO/U/RvJgVY1loPs5eMpUBpVajczh1A== + +esbuild@^0.13.2: + version "0.13.13" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.13.tgz#0b5399c20f219f663c8c1048436fb0f59ab17a41" + integrity sha512-Z17A/R6D0b4s3MousytQ/5i7mTCbaF+Ua/yPfoe71vdTv4KBvVAvQ/6ytMngM2DwGJosl8WxaD75NOQl2QF26Q== + optionalDependencies: + esbuild-android-arm64 "0.13.13" + esbuild-darwin-64 "0.13.13" + esbuild-darwin-arm64 "0.13.13" + esbuild-freebsd-64 "0.13.13" + esbuild-freebsd-arm64 "0.13.13" + esbuild-linux-32 "0.13.13" + esbuild-linux-64 "0.13.13" + esbuild-linux-arm "0.13.13" + esbuild-linux-arm64 "0.13.13" + esbuild-linux-mips64le "0.13.13" + esbuild-linux-ppc64le "0.13.13" + esbuild-netbsd-64 "0.13.13" + esbuild-openbsd-64 "0.13.13" + esbuild-sunos-64 "0.13.13" + esbuild-windows-32 "0.13.13" + esbuild-windows-64 "0.13.13" + esbuild-windows-arm64 "0.13.13" + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +is-core-module@^2.2.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" + integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== + dependencies: + has "^1.0.3" + +nanoid@^3.1.30: + version "3.1.30" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" + integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== + +path-parse@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +postcss@^8.3.8: + version "8.3.11" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.11.tgz#c3beca7ea811cd5e1c4a3ec6d2e7599ef1f8f858" + integrity sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA== + dependencies: + nanoid "^3.1.30" + picocolors "^1.0.0" + source-map-js "^0.6.2" + +resolve@^1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +rollup@^2.57.0: + version "2.60.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.60.0.tgz#4ee60ab7bdd0356763f87d7099f413e5460fc193" + integrity sha512-cHdv9GWd58v58rdseC8e8XIaPUo8a9cgZpnCMMDGZFDZKEODOiPPEQFXLriWr/TjXzhPPmG5bkAztPsOARIcGQ== + optionalDependencies: + fsevents "~2.3.2" + +source-map-js@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" + integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== + +typescript@^4.3.2: + version "4.4.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c" + integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== + +vite@^2.4.2: + version "2.6.14" + resolved "https://registry.yarnpkg.com/vite/-/vite-2.6.14.tgz#35c09a15e4df823410819a2a239ab11efb186271" + integrity sha512-2HA9xGyi+EhY2MXo0+A2dRsqsAG3eFNEVIo12olkWhOmc8LfiM+eMdrXf+Ruje9gdXgvSqjLI9freec1RUM5EA== + dependencies: + esbuild "^0.13.2" + postcss "^8.3.8" + resolve "^1.20.0" + rollup "^2.57.0" + optionalDependencies: + fsevents "~2.3.2"