@8btc/whiteboard 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +0 -12
- package/dist/index.js +203 -254
- package/dist/index.js.map +1 -0
- package/dist/index.umd.js +3 -2
- package/dist/index.umd.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/app/core/stage.ts","../src/app/core/transformer.ts","../src/app/core/state.ts","../src/app/core/utils/const.ts","../src/const/shape.ts","../src/lib/math.ts","../src/lib/shape.ts","../src/app/canvas/helpers/helpers.ts","../src/app/core/node/base.ts","../src/app/core/node/rect.ts","../src/app/core/node/image.ts","../src/app/core/node/image-marker.ts","../src/app/core/node/_factory.ts","../src/app/core/utils/draft.ts","../src/app/core/core.ts","../src/app/core/api.ts","../src/app/jsx/GridBackground.tsx","../src/lib/utils.ts","../src/components/ui/button.tsx","../src/app/jsx/ZoomPanel.tsx","../src/app/jsx/HistoryPanel.tsx","../src/app/React.tsx"],"sourcesContent":["import Konva from \"konva\";\nimport type { KonvaEventObject } from \"konva/lib/Node\";\nimport type { CanvasCore } from \"./core\";\n\nexport type StageConfig = {\n container: HTMLDivElement;\n width: number;\n height: number;\n draggable?: boolean;\n className?: string;\n};\n\nexport type ViewportState = {\n x: number;\n y: number;\n scale: number;\n width?: number;\n height?: number;\n};\n\n/**\n * CanvasStage 封装了 Konva.Stage 的核心功能\n * 提供视口管理、事件处理、拖拽和缩放等能力\n */\nexport class CanvasStage {\n #core: CanvasCore;\n #stage: Konva.Stage;\n #viewport: ViewportState = { x: 0, y: 0, scale: 1 };\n\n constructor(core: CanvasCore, config: StageConfig) {\n this.#core = core;\n this.#stage = new Konva.Stage({\n container: config.container,\n width: config.width,\n height: config.height,\n x: 0,\n y: 0,\n scaleX: 1,\n scaleY: 1,\n draggable: config.draggable ?? false,\n className: config.className,\n });\n\n this.#setupEventListeners();\n }\n\n /**\n * 获取原生 Konva.Stage 实例\n */\n getStage(): Konva.Stage {\n return this.#stage;\n }\n\n /**\n * 获取当前视口状态\n */\n getViewport(): ViewportState {\n return { ...this.#viewport };\n }\n\n /**\n * 设置视口(包括位置、缩放和尺寸)\n */\n setViewport(viewport: Partial<ViewportState>): void {\n const newViewport = { ...this.#viewport, ...viewport };\n this.#viewport = newViewport;\n\n if (viewport.x !== undefined) {\n this.#stage.x(viewport.x);\n }\n if (viewport.y !== undefined) {\n this.#stage.y(viewport.y);\n }\n if (viewport.scale !== undefined) {\n this.#stage.scaleX(viewport.scale);\n this.#stage.scaleY(viewport.scale);\n }\n if (viewport.width !== undefined) {\n this.#stage.width(viewport.width);\n }\n if (viewport.height !== undefined) {\n this.#stage.height(viewport.height);\n }\n }\n\n /**\n * 设置是否可拖拽\n */\n setDraggable(draggable: boolean): void {\n this.#stage.draggable(draggable);\n }\n\n /**\n * 设置光标样式\n */\n setCursor(cursor: string): void {\n const container = this.#stage.container();\n container.style.cursor = cursor;\n }\n\n /**\n * 重置光标样式\n */\n resetCursor(): void {\n const container = this.#stage.container();\n const toolType = this.#core.getState().toolType;\n if (toolType === \"hand\") {\n container.style.cursor = \"grab\";\n return;\n }\n container.style.cursor = \"default\";\n }\n\n /**\n * 销毁 Stage\n */\n destroy(): void {\n this.#stage.destroy();\n }\n\n /**\n * 处理滚轮缩放和平移\n */\n #handleWheel = (e: KonvaEventObject<WheelEvent>) => {\n e.evt.preventDefault();\n\n const stage = this.#stage;\n const pointer = stage.getPointerPosition();\n if (!pointer) return;\n\n // 检测是否为捏合缩放手势(触控板捏合时 ctrlKey 为 true)\n if (e.evt.ctrlKey) {\n // 缩放操作\n const oldScale = this.#viewport.scale;\n const mousePointTo = {\n x: (pointer.x - this.#viewport.x) / oldScale,\n y: (pointer.y - this.#viewport.y) / oldScale,\n };\n\n const scaleBy = 1.01;\n const direction = e.evt.deltaY > 0 ? -1 : 1;\n const steps = Math.min(Math.abs(e.evt.deltaY), 10);\n let newScale = oldScale;\n\n for (let i = 0; i < steps; i++) {\n newScale = direction > 0 ? newScale * scaleBy : newScale / scaleBy;\n }\n\n // 限制缩放范围 (10% ~ 500%)\n const scale = Math.max(0.1, Math.min(5, newScale));\n\n const newPos = {\n x: pointer.x - mousePointTo.x * scale,\n y: pointer.y - mousePointTo.y * scale,\n };\n\n this.#core.updateViewport({ x: newPos.x, y: newPos.y, scale });\n } else {\n // 平移操作(双指滑动或鼠标滚轮)\n const deltaX = e.evt.shiftKey ? e.evt.deltaY : e.evt.deltaX;\n const deltaY = e.evt.shiftKey ? 0 : e.evt.deltaY;\n\n this.#core.updateViewport({\n x: this.#viewport.x - deltaX,\n y: this.#viewport.y - deltaY,\n });\n }\n };\n\n #handlePointerDown = (event: KonvaEventObject<PointerEvent>): void => {\n const toolType = this.#core.getState().toolType;\n if (event.evt.button !== 0 || toolType === \"hand\") {\n return;\n }\n\n const clickedOnEmpty = event.target === this.#stage;\n const pointerPos = this.#stage.getRelativePointerPosition();\n\n if (toolType === \"select\" && !clickedOnEmpty) {\n const nodeId = event.target.id();\n if (nodeId) {\n this.#core.selectNode(nodeId, event.evt.shiftKey);\n }\n return;\n }\n\n if (toolType === \"rectangle\" && pointerPos) {\n this.#core.createDraftNode(toolType, pointerPos);\n }\n\n if (toolType === \"image-marker\" && pointerPos) {\n // 查找点击位置的图片\n const imageShape = this.#core.findImageAtPosition(pointerPos);\n console.log(imageShape, \"imageShape\");\n if (imageShape) {\n const width = imageShape.width();\n const height = imageShape.height();\n if (width && height) {\n // 设置图片边界用于限制绘制区域\n const imageBounds = {\n x: imageShape.x(),\n y: imageShape.y(),\n width,\n height,\n };\n this.#core.createDraftNode(toolType, pointerPos, {\n parent: imageShape.id(),\n bounds: imageBounds,\n startPosition: pointerPos,\n });\n }\n }\n }\n\n this.#core.selectNode();\n };\n\n #handlePointerMove = (): void => {\n const toolType = this.#core.getState().toolType;\n if (toolType === \"hand\") {\n return;\n }\n\n const pointerPos = this.#stage.getRelativePointerPosition();\n\n if (\n (toolType === \"rectangle\" || toolType === \"image-marker\") &&\n pointerPos\n ) {\n this.#core.updateDraftNode(pointerPos);\n }\n };\n\n #handlePointerUp = (): void => {\n const toolType = this.#core.getState().toolType;\n if (toolType === \"hand\") {\n return;\n }\n\n if (toolType === \"rectangle\" || toolType === \"image-marker\") {\n this.#core.finalizeDraftNode();\n }\n };\n\n #handleDragStart = (event: KonvaEventObject<DragEvent>): void => {\n if (event.target !== this.#stage) {\n return;\n }\n const toolType = this.#core.getState().toolType;\n if (toolType === \"hand\") {\n this.setCursor(\"grabbing\");\n } else if (toolType === \"select\") {\n this.setCursor(\"all-scroll\");\n }\n };\n\n #handleDragMove = (event: KonvaEventObject<DragEvent>): void => {\n if (event.target !== this.#stage) {\n return;\n }\n this.#core.updateViewport({\n x: this.#stage.x(),\n y: this.#stage.y(),\n });\n };\n\n #handleDragEnd = (event: KonvaEventObject<DragEvent>): void => {\n if (event.target !== this.#stage) {\n return;\n }\n this.#core.updateViewport({\n x: this.#stage.x(),\n y: this.#stage.y(),\n });\n this.resetCursor();\n };\n\n /**\n * 设置事件监听器\n */\n #setupEventListeners(): void {\n this.#stage.on(\"wheel\", this.#handleWheel);\n this.#stage.on(\"pointerdown\", this.#handlePointerDown);\n this.#stage.on(\"pointermove\", this.#handlePointerMove);\n this.#stage.on(\"pointerup\", this.#handlePointerUp);\n this.#stage.on(\"dragstart\", this.#handleDragStart);\n this.#stage.on(\"dragmove\", this.#handleDragMove);\n this.#stage.on(\"dragend\", this.#handleDragEnd);\n }\n}\n","import Konva from \"konva\";\nimport type { CanvasCore } from \"./core\";\nimport type { TransformerPosition } from \"@/types\";\n\nexport type TransformerConfig = {\n rotateEnabled?: boolean;\n ignoreStroke?: boolean;\n anchorSize?: number;\n borderDash?: number[];\n anchorCornerRadius?: number;\n padding?: number;\n};\n\n/**\n * CanvasTransformer 封装了 Konva.Transformer 的核心功能\n * 提供变换器管理、位置计算、事件处理等能力\n */\nexport class CanvasTransformer {\n #core: CanvasCore;\n #transformer: Konva.Transformer;\n\n constructor(core: CanvasCore, config?: TransformerConfig) {\n this.#core = core;\n this.#transformer = new Konva.Transformer({\n rotateEnabled: config?.rotateEnabled ?? true,\n ignoreStroke: config?.ignoreStroke ?? true,\n anchorSize: config?.anchorSize ?? 8,\n borderDash: config?.borderDash ?? [4, 4],\n anchorCornerRadius: config?.anchorCornerRadius ?? 4,\n padding: config?.padding ?? 6,\n });\n\n this.#setupEventListeners();\n }\n\n /**\n * 获取原生 Konva.Transformer 实例\n */\n getTransformer(): Konva.Transformer {\n return this.#transformer;\n }\n\n /**\n * 获取 Transformer 的位置信息\n */\n getPosition(): TransformerPosition | null {\n const nodes = this.#transformer.nodes();\n if (nodes.length === 0) {\n return null;\n }\n\n const box = this.#transformer.getClientRect();\n return {\n x: box.x,\n y: box.y,\n width: box.width,\n height: box.height,\n rotation: this.#transformer.rotation(),\n };\n }\n\n /**\n * 设置要变换的节点\n */\n setNodes(nodes: Konva.Node[]): void {\n if (nodes.length === 0) {\n this.clearNodes();\n return;\n }\n this.#transformer.nodes(nodes);\n this.#transformer.moveToTop();\n this.emitPositionChange();\n }\n\n /**\n * 获取当前变换的节点\n */\n getNodes(): Konva.Node[] {\n return this.#transformer.nodes();\n }\n\n /**\n * 清除所有节点\n */\n clearNodes(): void {\n this.#transformer.nodes([]);\n this.#transformer.moveToBottom();\n this.emitPositionChange();\n }\n\n /**\n * emit Transformer 位置\n */\n emitPositionChange(): void {\n const position = this.getPosition();\n this.#core.emitEvent(\"transformer:positionChange\", position);\n }\n\n /**\n * 处理 transformstart 事件\n */\n #handleTransformStart = (): void => {\n this.emitPositionChange();\n };\n\n /**\n * 处理 transform 事件\n */\n #handleTransform = (): void => {\n console.log(\"transforming...\");\n this.emitPositionChange();\n };\n\n /**\n * 处理 transformend 事件\n */\n #handleTransformEnd = (): void => {\n this.emitPositionChange();\n };\n\n /**\n * 处理 dragstart 事件\n */\n #handleDragStart = (): void => {\n this.emitPositionChange();\n };\n\n /**\n * 处理 dragmove 事件\n */\n #handleDragMove = (): void => {\n this.emitPositionChange();\n };\n\n /**\n * 处理 dragend 事件\n */\n #handleDragEnd = (): void => {\n this.emitPositionChange();\n };\n\n /**\n * 设置事件监听器\n */\n #setupEventListeners(): void {\n // Transform 事件\n this.#transformer.on(\"transformstart\", this.#handleTransformStart);\n this.#transformer.on(\"transform\", this.#handleTransform);\n this.#transformer.on(\"transformend\", this.#handleTransformEnd);\n\n // Drag 事件\n this.#transformer.on(\"dragstart\", this.#handleDragStart);\n this.#transformer.on(\"dragmove\", this.#handleDragMove);\n this.#transformer.on(\"dragend\", this.#handleDragEnd);\n }\n\n /**\n * 销毁 Transformer\n */\n destroy(): void {\n this.#transformer.destroy();\n }\n}\n","import mitt, { type Emitter } from \"mitt\";\nimport type { ICoreState, HistoryState } from \"./type\";\nimport type { TransformerPosition } from \"@/types\";\n\n/**\n * 状态事件类型定义\n */\nexport type StateEvents = {\n \"state:change\": ICoreState;\n \"state:undo\": ICoreState;\n \"state:redo\": ICoreState;\n \"state:reset\": ICoreState;\n \"viewport:change\": ICoreState[\"viewport\"];\n \"transformer:positionChange\": TransformerPosition | null;\n \"toolType:change\": ICoreState[\"toolType\"];\n};\n\n/**\n * CanvasState 类负责管理画布的状态\n * 包括历史记录(past/present/future)和状态监听\n */\nexport class CanvasState {\n private _past: ICoreState[] = [];\n private _present: ICoreState;\n private _future: ICoreState[] = [];\n private _emitter: Emitter<StateEvents>;\n\n constructor(initialState: ICoreState) {\n this._present = initialState;\n this._emitter = mitt<StateEvents>();\n }\n\n /**\n * 获取当前状态\n */\n getState(): ICoreState {\n return { ...this._present };\n }\n\n /**\n * 获取完整历史状态\n */\n getHistory(): HistoryState<ICoreState> {\n return {\n past: [...this._past],\n present: { ...this._present },\n future: [...this._future],\n };\n }\n\n /**\n * 是否可以撤销\n */\n canUndo(): boolean {\n return this._past.length > 0;\n }\n\n /**\n * 是否可以重做\n */\n canRedo(): boolean {\n return this._future.length > 0;\n }\n\n /**\n * 订阅状态事件\n */\n on<K extends keyof StateEvents>(\n event: K,\n handler: (data: StateEvents[K]) => void\n ): void {\n this._emitter.on(event, handler);\n }\n\n /**\n * 取消订阅状态事件\n */\n off<K extends keyof StateEvents>(\n event: K,\n handler: (data: StateEvents[K]) => void\n ): void {\n this._emitter.off(event, handler);\n }\n\n /**\n * 发送事件\n */\n protected emit<K extends keyof StateEvents>(\n event: K,\n data: StateEvents[K]\n ): void {\n this._emitter.emit(event, data);\n }\n\n /**\n * 撤销操作\n */\n undo(): void {\n if (this._past.length === 0) return;\n\n const previous = this._past[this._past.length - 1];\n const newPast = this._past.slice(0, this._past.length - 1);\n\n this._past = newPast;\n this._future = [this._present, ...this._future];\n this._present = previous;\n\n // 同步状态(由子类实现)\n this._syncState(previous);\n this._emitter.emit(\"state:undo\", previous);\n this._emitter.emit(\"state:change\", previous);\n }\n\n /**\n * 重做操作\n */\n redo(): void {\n if (this._future.length === 0) return;\n\n const next = this._future[0];\n const newFuture = this._future.slice(1);\n\n this._past = [...this._past, this._present];\n this._future = newFuture;\n this._present = next;\n\n // 同步状态(由子类实现)\n this._syncState(next);\n this._emitter.emit(\"state:redo\", next);\n this._emitter.emit(\"state:change\", next);\n }\n\n /**\n * 重置历史记录\n */\n resetHistory(): void {\n this._past = [];\n this._future = [];\n this._emitter.emit(\"state:reset\", this._present);\n this._emitter.emit(\"state:change\", this._present);\n }\n\n /**\n * 更新状态\n * @param partial - 部分状态更新\n * @param addToHistory - 是否添加到历史记录\n */\n protected _updateState(\n partial: Partial<ICoreState>,\n addToHistory = true\n ): void {\n const newState = { ...this._present, ...partial };\n\n if (addToHistory) {\n this._past = [...this._past, this._present];\n this._future = [];\n }\n\n this._present = newState;\n this._emitter.emit(\"state:change\", newState);\n }\n\n /**\n * 同步状态到外部系统(由子类实现)\n * @param _state - 要同步的状态\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected _syncState(_state: ICoreState): void {\n // 空实现,由子类覆盖\n }\n\n /**\n * 清理资源\n */\n protected _dispose(): void {\n this._emitter.all.clear();\n }\n}\n","export const NODE_NAME_FOR_SELECT = \"shapeNameForSelect\";\n\nexport const RECT = {\n CORNER_RADIUS: 6,\n MIN_SIZE: 10,\n};\n\nexport const IMAGE = {\n MIN_SIZE: 10,\n};\n","import { defaultTheme } from \"./theme\";\n\nexport const TRANSFORMER = {\n NAME: \"transformer\",\n MIN_SIZE: 10,\n ROTATION_SNAPS: [0, 90, 180, 270],\n ROTATION_ANCHOR_OFFSET: 24,\n PADDING: 6,\n ANCHOR_CORNER_RADIUS: 5,\n ANCHOR_SIZE: 9,\n ANCHOR_STROKE_WIDTH: 1.5,\n ANCHOR_STROKE: defaultTheme.colors.green300,\n BORDER_STROKE: defaultTheme.colors.green300,\n};\n\nexport const ARROW_TRANSFORMER = {\n RADIUS: 3.75,\n ANCHOR_STROKE_WIDTH: 2.75,\n ANCHOR_STROKE_WIDTH_HOVER: 11,\n HIT_STROKE_WIDTH: 16,\n STROKE: defaultTheme.colors.green300,\n NAME: \"arrow-transformer\",\n ANCHOR_NAME: \"arrow-transformer-anchor\",\n SNAP_OFFSET: 8,\n} as const;\n\nexport const ARROW = {\n HEAD_WIDTH: 6,\n HEAD_LENGTH: 6,\n DEFAULT_BEND: 0.5,\n};\n\nexport const FREE_PATH = {\n TENSION: 0.5,\n};\n\nexport const RECT = {\n CORNER_RADIUS: 6,\n MIN_SIZE: 10,\n};\n\nexport const ELLIPSE = {\n MIN_RADIUS: 5,\n} as const;\n\nexport const TEXT = {\n PADDING: 4,\n LINE_HEIGHT: 1,\n FONT_FAMILY: \"Klee One\",\n FONT_WEIGHT: \"bold\",\n NAME: \"text\",\n};\n\nexport const SELECT_RECT = {\n STROKE: defaultTheme.colors.red500,\n FILL: defaultTheme.colors.gray400,\n CORNER_RADIUS: 1,\n OPACITY: 0.1,\n};\n\nexport const LASER = {\n TRIM_COUNT: 2,\n TRIM_INTERVAL: 24,\n TRIM_DELAY: 250,\n MAX_LENGTH: 50,\n WIDTH: 3.5,\n COLOR: defaultTheme.colors.red500,\n} as const;\n\nexport const IMAGE = {\n MIN_SIZE: 20,\n} as const;\n","import type { IRect, Vector2d } from \"konva/lib/types\";\nimport type { NodeObject, Point } from \"@/types\";\nimport { RECT } from \"@/const/shape\";\n\nexport function getRatioFromValue(value: number, min: number, max: number) {\n return max === min ? 1 : (value - min) / (max - min);\n}\n\nexport function getValueFromRatio(ratio: number, min: number, max: number) {\n return ratio * (max - min) + min;\n}\n\nexport function calculateMiddlePoint(rect: IRect): Vector2d {\n return {\n x: rect.x + rect.x + rect.width / 2,\n y: rect.y + rect.y + rect.height / 2,\n };\n}\n\nexport function calculateMidPointFromRange(start: Point, end: Point): Point {\n return [(start[0] + end[0]) / 2, (start[1] + end[1]) / 2];\n}\n\nexport function clamp(value: number, range: [min: number, max: number]) {\n return Math.min(Math.max(value, range[0]), range[1]);\n}\n\ninterface Bounds {\n x: number; // 矩形左上角 x\n y: number; // 矩形左上角 y\n width: number; // 宽度\n height: number; // 高度\n}\n\n/**\n * 限制坐标点在指定的矩形区域内\n * @param point 待处理的坐标 {x, y}\n * @param bounds 限制范围 {x, y, width, height}\n */\nexport const clampToBounds = (point: Point, bounds: Bounds): Point => {\n return [\n clamp(point[0], [bounds.x, bounds.x + bounds.width]),\n clamp(point[1], [bounds.y, bounds.y + bounds.height]),\n ];\n};\n\nexport function calculateLengthFromPoints(points: Point[]) {\n let length = 0;\n\n for (let i = 0; i < points.length - 1; i++) {\n const [x1, y1] = points[i];\n const [x2, y2] = points[i + 1];\n const deltaX = x2 - x1;\n const deltaY = y2 - y1;\n\n length += Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));\n }\n\n return length;\n}\n\nexport function calculatePerimeter(\n width: number,\n height: number,\n cornerRadius: number\n) {\n return 2 * (height + width - cornerRadius * (4 - Math.PI));\n}\n\nexport function calculateCircumference(rx: number, ry: number): number {\n const a = rx;\n const b = ry;\n const h = Math.pow(a - b, 2) / Math.pow(a + b, 2);\n\n return Math.PI * (a + b) * (1 + (3 * h) / (10 + Math.sqrt(4 - 3 * h)));\n}\n\nexport function getShapeLength(node: NodeObject): number {\n if (Array.isArray(node.nodeProps.points)) {\n return calculateLengthFromPoints([\n node.nodeProps.point,\n ...node.nodeProps.points,\n ]);\n }\n\n if (node.nodeProps.width && node.nodeProps.height) {\n if (node.type === \"ellipse\") {\n return calculateCircumference(\n node.nodeProps.width,\n node.nodeProps.height\n );\n }\n if (node.type === \"rectangle\") {\n return calculatePerimeter(\n node.nodeProps.width,\n node.nodeProps.height,\n RECT.CORNER_RADIUS\n );\n }\n }\n\n return 0;\n}\n","import { defaultTheme, darkTheme } from \"@/const/theme\";\nimport { hexToRGBa } from \"./string\";\nimport { getShapeLength } from \"./math\";\nimport type {\n NodeColor,\n NodeFill,\n NodeLine,\n NodeObject,\n NodeSize,\n ThemeColorValue,\n ThemeColors,\n} from \"@/types\";\nimport type { ShapeConfig } from \"konva/lib/Shape\";\n\nexport function getDashValue(\n shapeLength: number,\n strokeWidth: number,\n lineStyle: NodeLine\n) {\n let ratio = 1;\n let dashLength = 0;\n let dashGap = 0;\n\n switch (lineStyle) {\n case \"dashed\":\n dashLength = Math.min(strokeWidth * 2, shapeLength / 4);\n break;\n case \"dotted\":\n ratio = 8;\n dashLength = strokeWidth / ratio;\n break;\n default:\n return [];\n }\n\n let dashCount = Math.floor(shapeLength / dashLength / (2 * ratio));\n dashCount = Math.max(dashCount, 3);\n\n dashLength = shapeLength / dashCount / (2 * ratio);\n dashGap = (shapeLength - dashCount * dashLength) / dashCount;\n\n return [dashLength, dashGap];\n}\n\nexport function getSizeValue(key: NodeSize) {\n switch (key) {\n case \"small\":\n return 2;\n case \"medium\":\n return 3;\n case \"large\":\n return 5;\n case \"extra-large\":\n return 8;\n default:\n return 3;\n }\n}\n\nexport function getColorValue(\n key: NodeColor,\n themeColors: ThemeColors\n): ThemeColorValue {\n if (key in themeColors) {\n return themeColors[key as keyof ThemeColors];\n }\n\n return themeColors.black;\n}\n\nexport function getFillValue(fill: NodeFill, colorValue: ThemeColorValue) {\n switch (fill) {\n case \"semi\": {\n return \"transparent\";\n }\n case \"solid\": {\n return hexToRGBa(colorValue, 0.25);\n }\n default:\n return undefined;\n }\n}\n\nexport function getDashStyle(\n node: NodeObject,\n sizeValue: number,\n scale: number\n) {\n if (node.style.line === \"solid\") {\n return [];\n }\n\n const shapeLength = getShapeLength(node) * scale;\n const strokeWidth = sizeValue * scale;\n\n return getDashValue(shapeLength, strokeWidth, node.style.line);\n}\n\nexport function getTotalDashLength(dash: ShapeConfig[\"dash\"]) {\n return Array.isArray(dash) && dash.length > 1 ? dash[0] + dash[1] : 0;\n}\n\nexport function getFontSize(size: number) {\n return size * 8;\n}\n\nexport function getCurrentThemeColors({\n isDarkTheme,\n}: {\n isDarkTheme: boolean;\n}) {\n return isDarkTheme ? darkTheme.colors : defaultTheme.colors;\n}\n","import { RECT, TEXT, TRANSFORMER } from \"@/const/shape\";\nimport type Konva from \"konva\";\nimport type { Box } from \"konva/lib/shapes/Transformer\";\n\nexport function normalizeTransformerSize(oldBox: Box, newBox: Box) {\n if (\n newBox.width < TRANSFORMER.MIN_SIZE ||\n newBox.height < TRANSFORMER.MIN_SIZE\n ) {\n return oldBox;\n }\n\n return newBox;\n}\n\nexport function getNodeSize(width: number, scale: number, min = 20) {\n return Math.max(width * scale, min);\n}\n\nexport function getSizePropsFromTextValue(text: string, fontSize: number) {\n const lines = text.split(\"\\n\");\n const longestLine = Math.max(...lines.map((line) => line.length), 1);\n const numberOfLines = lines.length;\n\n return {\n width: `calc(${longestLine}ch + ${TEXT.PADDING}px)`,\n height: `${\n fontSize * numberOfLines * TEXT.LINE_HEIGHT + TEXT.PADDING * 4\n }px`,\n };\n}\n\nexport function getRectSize(rect: Konva.Rect) {\n return {\n width: Math.max(RECT.MIN_SIZE, rect.width() * rect.scaleX()),\n height: Math.max(RECT.MIN_SIZE, rect.height() * rect.scaleY()),\n };\n}\n","import type Konva from \"konva\";\nimport type { CanvasCore } from \"../core\";\nimport type { INode } from \"../type\";\nimport type { ICanvasNode } from \"../type\";\n\n/**\n * BaseCanvasNode 基类\n * 为所有 Canvas 节点提供通用功能,如监听 toolType 变化控制交互性\n */\nexport abstract class BaseCanvasNode<T extends INode = INode>\n implements ICanvasNode\n{\n protected core: CanvasCore;\n protected node: T;\n protected element: Konva.Shape | Konva.Group;\n private toolTypeChangeHandler: (toolType: string) => void;\n\n constructor(core: CanvasCore, node: T) {\n this.core = core;\n this.node = node;\n this.element = this.createElement();\n\n // 监听 toolType 变化\n this.toolTypeChangeHandler = (toolType: string) => {\n const isSelect = toolType === \"select\";\n this.element.listening(isSelect);\n };\n\n // 设置初始状态\n this.toolTypeChangeHandler(this.core.getToolType());\n\n // 监听变化\n this.core.on(\"toolType:change\", this.toolTypeChangeHandler);\n }\n\n /**\n * 获取 Konva 元素\n */\n getElement(): Konva.Shape | Konva.Group {\n return this.element;\n }\n\n /**\n * 获取节点数据\n */\n getNode(): INode {\n return this.node;\n }\n\n /**\n * 子类必须实现:创建 Konva 元素\n */\n protected abstract createElement(): Konva.Shape | Konva.Group;\n\n /**\n * 子类必须实现:更新节点数据\n */\n abstract updateNode(node: Partial<INode>): void;\n\n /**\n * 销毁节点\n */\n destroy(): void {\n // 移除事件监听\n this.core.off(\"toolType:change\", this.toolTypeChangeHandler);\n this.element.destroy();\n }\n}\n","import Konva from \"konva\";\nimport { RECT } from \"../utils/const\";\nimport { calculatePerimeter } from \"@/lib/math\";\nimport { getDashValue, getSizeValue, getTotalDashLength } from \"@/lib/shape\";\nimport { getRectSize } from \"@/app/canvas/helpers\";\nimport type { NodeObject } from \"@/types\";\nimport type { KonvaEventObject } from \"konva/lib/Node\";\nimport type { CanvasCore } from \"../core\";\nimport type { INode } from \"../type\";\nimport { NODE_NAME_FOR_SELECT } from \"../utils/const\";\nimport { BaseCanvasNode } from \"./base\";\n\nexport interface RectConfig {\n node: NodeObject<\"rectangle\">;\n stageScale: number;\n config: Konva.RectConfig;\n}\n\nexport interface AnimationControl {\n start: () => void;\n stop: () => void;\n isRunning: () => boolean;\n}\n\n/**\n * 创建 Rect 动画控制器\n */\nexport function createRectAnimation(\n rect: Konva.Rect,\n totalDashLength: number\n): AnimationControl | null {\n if (!totalDashLength || totalDashLength === 0) {\n return null;\n }\n\n const anim = new Konva.Animation((frame) => {\n if (!frame) return;\n const dashOffset = (-frame.time / 10) % totalDashLength;\n rect.dashOffset(dashOffset);\n }, rect.getLayer());\n\n return {\n start: () => anim.start(),\n stop: () => anim.stop(),\n isRunning: () => anim.isRunning(),\n };\n}\n\n/**\n * RectNode 类封装了 Konva.Rect 的业务逻辑\n */\nexport class RectNode extends BaseCanvasNode<INode<\"rectangle\">> {\n #animation: AnimationControl | null = null;\n\n constructor(core: CanvasCore, node: INode<\"rectangle\">) {\n super(core, node);\n\n // 初始化动画\n if (node.style.animated) {\n this.#initAnimation();\n }\n\n // 设置事件监听(必须在 super 之后,确保私有字段已初始化)\n this.#setupEventHandlers(this.getElement());\n }\n\n protected createElement(): Konva.Rect {\n // 计算尺寸\n const width = Math.max(\n this.node.props.width ?? RECT.MIN_SIZE,\n RECT.MIN_SIZE\n );\n const height = Math.max(\n this.node.props.height ?? RECT.MIN_SIZE,\n RECT.MIN_SIZE\n );\n\n // 创建 Rect\n const config: Konva.RectConfig = {\n id: this.node.id,\n ...this.node.props,\n ...this.node.style,\n width: width,\n height: height,\n cornerRadius: RECT.CORNER_RADIUS,\n name: NODE_NAME_FOR_SELECT,\n draggable: true,\n stroke: \"black\",\n strokeWidth: 2,\n };\n const rect = new Konva.Rect(config);\n // todo: 直接设置在 constructor 中不生效的问题\n rect.setAttrs({\n width,\n height,\n });\n\n return rect;\n }\n\n /**\n * 获取 Konva.Rect 实例\n */\n getElement(): Konva.Rect {\n return this.element as Konva.Rect;\n }\n\n /**\n * 更新节点数据\n */\n updateNode(node: Partial<INode<\"rectangle\">>): void {\n this.node = {\n ...this.node,\n ...node,\n props: {\n ...this.node.props,\n ...node.props,\n },\n style: {\n ...this.node.style,\n ...node.style,\n },\n };\n\n const rect = this.getElement();\n // 更新位置\n rect.x(this.node.props.x);\n rect.y(this.node.props.y);\n\n // 更新尺寸\n const width = Math.max(\n this.node.props.width ?? RECT.MIN_SIZE,\n RECT.MIN_SIZE\n );\n const height = Math.max(\n this.node.props.height ?? RECT.MIN_SIZE,\n RECT.MIN_SIZE\n );\n rect.width(width);\n rect.height(height);\n\n // 更新动画\n if (this.node.style.animated && !this.#animation) {\n this.#initAnimation();\n } else if (!this.node.style.animated && this.#animation) {\n this.#destroyAnimation();\n }\n }\n\n /**\n * 销毁\n */\n destroy(): void {\n this.#destroyAnimation();\n super.destroy();\n }\n\n /**\n * 初始化动画\n */\n #initAnimation(): void {\n const rect = this.getElement();\n const dash = rect.dash();\n if (!dash || dash.length === 0) return;\n\n const totalDashLength = getTotalDashLength(dash);\n this.#animation = createRectAnimation(rect, totalDashLength);\n\n if (this.#animation) {\n this.#animation.start();\n }\n }\n\n /**\n * 销毁动画\n */\n #destroyAnimation(): void {\n if (this.#animation) {\n this.#animation.stop();\n this.#animation = null;\n }\n }\n\n /**\n * 设置事件处理器\n */\n #setupEventHandlers(rect: Konva.Rect | undefined = undefined): void {\n const element = rect ?? (this.getElement() as Konva.Rect);\n // TransformStart\n element.on(\"transformstart\", () => {\n if (this.node.style.animated && this.#animation) {\n this.#animation.stop();\n }\n });\n\n // Transform\n element.on(\"transform\", (event: KonvaEventObject<Event>) => {\n const rect = event.target as Konva.Rect;\n const { width, height } = getRectSize(rect);\n\n const totalLength = calculatePerimeter(width, height, RECT.CORNER_RADIUS);\n const dash = getDashValue(\n totalLength,\n getSizeValue(this.node.style.size),\n this.node.style.line\n );\n\n rect.scale({ x: 1, y: 1 });\n rect.width(width);\n rect.height(height);\n rect.dash(dash.map((d) => d * this.core.getStageScale()));\n });\n\n // TransformEnd\n element.on(\"transformend\", (event: KonvaEventObject<Event>) => {\n const rect = event.target as Konva.Rect;\n const { width, height } = getRectSize(rect);\n const newProps = {\n ...this.node.props,\n x: rect.x(),\n y: rect.y(),\n width: width,\n height: height,\n rotation: rect.rotation(),\n };\n this.node.props = newProps;\n this.core._syncNodeFromElement(this.node.id, {\n props: newProps,\n });\n\n if (this.node.style.animated && this.#animation?.isRunning() === false) {\n this.#animation.start();\n }\n });\n\n element.on(\"dragend\", (event: KonvaEventObject<DragEvent>) => {\n const rect = event.target as Konva.Rect;\n\n const newProps = {\n ...this.node.props,\n x: rect.x(),\n y: rect.y(),\n };\n this.node.props = newProps;\n this.core._syncNodeFromElement(this.node.id, {\n props: newProps,\n });\n });\n }\n}\n","import Konva from \"konva\";\nimport { IMAGE } from \"../utils/const\";\nimport type { KonvaEventObject } from \"konva/lib/Node\";\nimport type { CanvasCore } from \"../core\";\nimport type { INode } from \"../type\";\nimport { NODE_NAME_FOR_SELECT } from \"../utils/const\";\nimport { BaseCanvasNode } from \"./base\";\n\n/**\n * ImageNode 类封装了 Konva.Image 的业务逻辑\n */\nexport class ImageNode extends BaseCanvasNode<INode<\"image\">> {\n constructor(core: CanvasCore, node: INode<\"image\">) {\n super(core, node);\n // 加载图片\n this.#loadImage();\n\n // 设置事件监听\n this.#setupEventHandlers(this.getElement());\n }\n\n protected createElement(): Konva.Image {\n // 创建一个空的 Image 元素(使用空画布作为占位符)\n const placeholder = document.createElement(\"canvas\");\n placeholder.width = 1;\n placeholder.height = 1;\n\n const img = new Konva.Image({\n id: this.node.id,\n x: this.node.props.x,\n y: this.node.props.y,\n name: NODE_NAME_FOR_SELECT,\n draggable: true,\n image: placeholder,\n });\n\n return img;\n }\n\n /**\n * 加载图片\n */\n #loadImage(): void {\n const imageUrl = this.node.meta.imageUrl;\n if (!imageUrl) {\n console.warn(\"Image URL is missing\");\n return;\n }\n\n const img = new window.Image();\n img.crossOrigin = \"anonymous\";\n img.src = imageUrl;\n\n img.onload = () => {\n this.getElement().image(img);\n\n // 计算尺寸\n const width = this.node.props.width ?? img.width;\n const height = this.node.props.height ?? img.height;\n\n this.getElement().width(Math.max(width, IMAGE.MIN_SIZE));\n this.getElement().height(Math.max(height, IMAGE.MIN_SIZE));\n };\n\n img.onerror = () => {\n console.error(\"Failed to load image:\", imageUrl);\n };\n }\n\n /**\n * 获取 Konva.Image 实例\n */\n getElement(): Konva.Image {\n return this.element as Konva.Image;\n }\n\n /**\n * 更新节点数据\n */\n updateNode(node: Partial<INode<\"image\">>): void {\n this.node = {\n ...this.node,\n ...node,\n props: {\n ...this.node.props,\n ...node.props,\n },\n style: {\n ...this.node.style,\n ...node.style,\n },\n meta: {\n ...this.node.meta,\n ...node.meta,\n },\n };\n\n const img = this.getElement();\n // 更新位置\n img.x(this.node.props.x);\n img.y(this.node.props.y);\n\n // 更新尺寸\n if (this.node.props.width && this.node.props.height) {\n const width = Math.max(this.node.props.width, IMAGE.MIN_SIZE);\n const height = Math.max(this.node.props.height, IMAGE.MIN_SIZE);\n img.width(width);\n img.height(height);\n }\n\n // 更新旋转\n if (this.node.props.rotation !== undefined) {\n img.rotation(this.node.props.rotation);\n }\n\n // 如果图片 URL 改变,重新加载\n if (node.meta?.imageUrl && node.meta.imageUrl !== this.node.meta.imageUrl) {\n this.#loadImage();\n }\n }\n\n /**\n * 销毁\n */\n destroy(): void {\n super.destroy();\n }\n\n /**\n * 设置事件处理器\n */\n #setupEventHandlers(img: Konva.Image): void {\n // Transform\n img.on(\"transform\", (event: KonvaEventObject<Event>) => {\n const img = event.target as Konva.Image;\n const width = Math.max(IMAGE.MIN_SIZE, img.width() * img.scaleX());\n const height = Math.max(IMAGE.MIN_SIZE, img.height() * img.scaleY());\n\n img.scale({ x: 1, y: 1 });\n img.width(width);\n img.height(height);\n\n // 同步更新关联的 image-marker 节点\n this.#syncImageMarkers();\n });\n\n // TransformEnd\n img.on(\"transformend\", (event: KonvaEventObject<Event>) => {\n const img = event.target as Konva.Image;\n const newProps = {\n ...this.node.props,\n x: img.x(),\n y: img.y(),\n width: img.width(),\n height: img.height(),\n rotation: img.rotation(),\n };\n this.node.props = newProps;\n this.core._syncNodeFromElement(this.node.id, {\n props: newProps,\n });\n\n // 同步更新关联的 image-marker 节点到状态\n this.#syncImageMarkersToState();\n });\n\n // DragMove\n img.on(\"dragmove\", () => {\n this.#syncImageMarkers();\n });\n\n // DragEnd\n img.on(\"dragend\", (event: KonvaEventObject<DragEvent>) => {\n const img = event.target as Konva.Image;\n const newProps = {\n ...this.node.props,\n x: img.x(),\n y: img.y(),\n };\n this.node.props = newProps;\n this.core._syncNodeFromElement(this.node.id, {\n props: newProps,\n });\n\n // 同步更新关联的 image-marker 节点到状态\n this.#syncImageMarkersToState();\n });\n }\n\n /**\n * 同步 image-marker 节点的位置(实时更新 Konva 元素)\n */\n #syncImageMarkers(): void {\n const img = this.getElement();\n const layer = img.getLayer();\n if (!layer) return;\n\n const imgX = img.x();\n const imgY = img.y();\n const imgWidth = img.width();\n const imgHeight = img.height();\n\n // 查找所有关联的 image-marker\n const imageMarkerElements = layer.find((node: Konva.Node) =>\n node.hasName(this.node.id)\n );\n\n const nodes = this.core.getState().nodes || [];\n\n imageMarkerElements.forEach((nodeElement: Konva.Node) => {\n const nodeData = nodes.find((n) => n.id === nodeElement.id());\n\n if (nodeData?.type === \"image-marker\" && nodeData.meta.relativePosition) {\n const { start, end } = nodeData.meta.relativePosition;\n\n // 根据百分比计算新的绝对位置\n const startX = imgX + (start.percentX / 100) * imgWidth;\n const startY = imgY + (start.percentY / 100) * imgHeight;\n const endX = imgX + (end.percentX / 100) * imgWidth;\n const endY = imgY + (end.percentY / 100) * imgHeight;\n\n // 计算标注的新位置和尺寸\n const newX = Math.min(startX, endX);\n const newY = Math.min(startY, endY);\n const newWidth = Math.abs(endX - startX);\n const newHeight = Math.abs(endY - startY);\n\n // 更新 Group 的位置和尺寸\n nodeElement.position({ x: newX, y: newY });\n nodeElement.setAttrs({ width: newWidth, height: newHeight });\n\n // 更新 Group 内部的子元素\n const children = (nodeElement as Konva.Group).getChildren();\n children.forEach((child) => {\n if (child.getClassName() === \"Rect\") {\n child.setAttrs({ width: newWidth, height: newHeight });\n } else if (child.getClassName() === \"Group\") {\n child.setAttrs({ x: newWidth, y: newHeight });\n }\n });\n }\n });\n }\n\n /**\n * 同步 image-marker 节点到状态\n */\n #syncImageMarkersToState(): void {\n const img = this.getElement();\n const layer = img.getLayer();\n if (!layer) return;\n\n const imageMarkerElements = layer.find((node: Konva.Node) =>\n node.hasName(this.node.id)\n );\n\n imageMarkerElements.forEach((nodeElement: Konva.Node) => {\n this.core._syncNodeFromElement(nodeElement.id(), {\n props: {\n x: nodeElement.x(),\n y: nodeElement.y(),\n width: nodeElement.width(),\n height: nodeElement.height(),\n },\n });\n });\n }\n}\n","import Konva from \"konva\";\nimport { RECT } from \"../utils/const\";\nimport type { CanvasCore } from \"../core\";\nimport type { INode } from \"../type\";\nimport { BaseCanvasNode } from \"./base\";\n\n/**\n * ImageMarkerNode 类封装了 Image Marker 的业务逻辑\n * Image Marker 是图片上的标注,使用 Group 包含 Rect 和 Circle+Text\n */\nexport class ImageMarkerNode extends BaseCanvasNode<INode<\"image-marker\">> {\n #rect: Konva.Rect;\n #markerGroup: Konva.Group;\n #circle: Konva.Circle;\n #text: Konva.Text;\n\n constructor(core: CanvasCore, node: INode<\"image-marker\">) {\n super(core, node);\n\n const group = this.getElement();\n this.#rect = group.findOne<Konva.Rect>(\".rect\")!;\n this.#markerGroup = group.findOne<Konva.Group>(\".marker-group\")!;\n this.#circle = this.#markerGroup.findOne<Konva.Circle>(\"Circle\")!;\n this.#text = this.#markerGroup.findOne<Konva.Text>(\"Text\")!;\n\n // 设置事件监听\n this.#setupEventHandlers();\n }\n\n protected createElement(): Konva.Group {\n // 计算尺寸\n const width = Math.max(\n this.node.props.width ?? RECT.MIN_SIZE,\n RECT.MIN_SIZE\n );\n const height = Math.max(\n this.node.props.height ?? RECT.MIN_SIZE,\n RECT.MIN_SIZE\n );\n\n // 创建主 Group\n const group = new Konva.Group({\n id: this.node.id,\n name: `static ${this.node.meta.parent}`,\n x: this.node.props.x,\n y: this.node.props.y,\n width,\n height,\n });\n\n // 创建矩形框\n const rect = new Konva.Rect({\n name: \"rect\",\n x: 0,\n y: 0,\n width,\n height,\n stroke: this.node.style.color,\n strokeWidth: 2,\n dash: [5, 5],\n fill: \"transparent\",\n cornerRadius: RECT.CORNER_RADIUS,\n });\n\n // 创建标记点 Group(圆圈 + 数字)\n const markerGroup = new Konva.Group({\n name: \"marker-group\",\n x: width,\n y: height,\n });\n\n const stageScale = this.core.getStageScale();\n const radius = 16 / stageScale;\n\n const circle = new Konva.Circle({\n radius,\n fill: \"red\",\n stroke: \"black\",\n strokeWidth: 2,\n });\n\n const text = new Konva.Text({\n x: -radius,\n y: -radius,\n width: radius * 2,\n height: radius * 2,\n text: String(this.node.meta.markerNumber || \"\"),\n align: \"center\",\n verticalAlign: \"middle\",\n fontSize: 16,\n fill: \"white\",\n });\n\n // 组装结构\n markerGroup.add(circle);\n markerGroup.add(text);\n group.add(rect);\n group.add(markerGroup);\n\n return group;\n }\n\n /**\n * 获取 Konva.Group 实例\n */\n getElement(): Konva.Group {\n return this.element as Konva.Group;\n }\n\n /**\n * 更新节点数据\n */\n updateNode(node: Partial<INode<\"image-marker\">>): void {\n this.node = {\n ...this.node,\n ...node,\n props: {\n ...this.node.props,\n ...node.props,\n },\n style: {\n ...this.node.style,\n ...node.style,\n },\n meta: {\n ...this.node.meta,\n ...node.meta,\n },\n };\n\n const group = this.getElement();\n // 更新位置\n group.x(this.node.props.x);\n group.y(this.node.props.y);\n\n // 更新尺寸\n const width = Math.max(\n this.node.props.width ?? RECT.MIN_SIZE,\n RECT.MIN_SIZE\n );\n const height = Math.max(\n this.node.props.height ?? RECT.MIN_SIZE,\n RECT.MIN_SIZE\n );\n\n group.width(width);\n group.height(height);\n this.#rect.width(width);\n this.#rect.height(height);\n this.#markerGroup.x(width);\n this.#markerGroup.y(height);\n\n // 更新样式\n if (node.style?.color) {\n this.#rect.stroke(node.style.color);\n }\n\n // 更新标记数字\n if (node.meta?.markerNumber !== undefined) {\n this.#text.text(String(node.meta.markerNumber));\n }\n }\n\n /**\n * 销毁\n */\n destroy(): void {\n super.destroy();\n }\n\n /**\n * 更新焦点状态(hover 或 selected)\n */\n setFocusState(isFocus: boolean): void {\n const strokeWidth = isFocus ? 3 : 2;\n const scale = isFocus ? 1.2 : 1;\n\n this.#rect.strokeWidth(strokeWidth);\n this.#circle.strokeWidth(strokeWidth);\n this.#markerGroup.scaleX(scale);\n this.#markerGroup.scaleY(scale);\n }\n\n /**\n * 设置事件处理器\n */\n #setupEventHandlers(): void {\n // 标记点的交互事件\n this.#markerGroup.on(\"pointerover\", () => {\n this.setFocusState(true);\n this.core.setCursor(\"pointer\");\n });\n\n this.#markerGroup.on(\"pointerout\", () => {\n const selectedIds = this.core.getState().selectedNodeIds || [];\n const isSelected = selectedIds.includes(this.node.id);\n this.setFocusState(isSelected);\n this.core.resetCursor();\n });\n\n this.#markerGroup.on(\"pointerdown\", () => {\n this.core.selectNode(this.node.id);\n });\n }\n}\n","import type { ICanvasNode, INode, NodeType } from \"../type\";\nimport { RectNode } from \"./rect\";\nimport { ImageNode } from \"./image\";\nimport { ImageMarkerNode } from \"./image-marker\";\nimport type { CanvasCore } from \"../core\";\n\nexport function createCanvasNodeByType(\n core: CanvasCore,\n type: NodeType,\n config: INode\n): ICanvasNode | null {\n switch (type) {\n case \"rectangle\":\n return new RectNode(core, config as INode<\"rectangle\">);\n case \"image\":\n return new ImageNode(core, config as INode<\"image\">);\n case \"image-marker\":\n return new ImageMarkerNode(core, config as INode<\"image-marker\">);\n default:\n return null;\n }\n}\n","import type { INode, NodeType } from \"../type\";\nimport { v4 as uuid } from \"uuid\";\nimport { RECT } from \"./const\";\n\nexport const createNodeByType = <T extends NodeType>(\n type: T,\n position: { x: number; y: number },\n style?: INode[\"style\"],\n meta?: Partial<INode[\"meta\"]>\n): INode<T> => {\n const baseNode = {\n type,\n id: uuid(),\n text: null,\n style: style ?? {\n opacity: 1,\n line: \"solid\",\n color: \"black\",\n size: \"medium\",\n animated: false,\n },\n props: {\n x: position.x,\n y: position.y,\n rotation: 0,\n visible: true,\n },\n meta: meta ?? {},\n };\n\n // image-marker 使用特殊的默认样式\n if (type === \"image-marker\") {\n return {\n ...baseNode,\n style: {\n ...baseNode.style,\n color: \"#ff0000\",\n line: \"dashed\",\n },\n } as INode<T>;\n }\n\n return baseNode;\n};\n\nexport function updateNodeByType<T extends NodeType>(\n node: INode<T>,\n position: { x: number; y: number },\n bounds?: { x: number; y: number; width: number; height: number }\n): INode<T> {\n let finalPosition = position;\n\n // 如果是 image-marker 且提供了边界,限制在边界内\n if (node.type === \"image-marker\" && bounds) {\n finalPosition = {\n x: Math.max(bounds.x, Math.min(bounds.x + bounds.width, position.x)),\n y: Math.max(bounds.y, Math.min(bounds.y + bounds.height, position.y)),\n };\n }\n\n const [p1, p2] = normalizePoints(\n { x: node.props.x, y: node.props.y },\n finalPosition\n );\n\n if (node.type === \"rectangle\" || node.type === \"image-marker\") {\n return {\n ...node,\n props: {\n ...node.props,\n x: p1.x,\n y: p1.y,\n width: Math.max(p2.x - p1.x, RECT.MIN_SIZE),\n height: Math.max(p2.y - p1.y, RECT.MIN_SIZE),\n },\n };\n }\n return node;\n}\n\nexport function normalizePoints(\n p1: { x: number; y: number },\n p2: { x: number; y: number }\n): { x: number; y: number }[] {\n let p1x = p1.x,\n p1y = p1.y,\n p2x = p2.x,\n p2y = p2.y,\n d;\n\n if (p1x > p2x) {\n d = Math.abs(p1x - p2x);\n p1x = p2x;\n p2x = p1x + d;\n }\n\n if (p1y > p2y) {\n d = Math.abs(p1y - p2y);\n p1y = p2y;\n p2y = p1y + d;\n }\n\n return [\n { x: p1x, y: p1y },\n { x: p2x, y: p2y },\n ];\n}\n","import Konva from \"konva\";\nimport type {\n ICanvasNode,\n ICoreState,\n INode,\n NodeType,\n ToolType,\n} from \"./type\";\nimport { CanvasStage } from \"./stage\";\nimport { CanvasTransformer } from \"./transformer\";\nimport { CanvasState } from \"./state\";\nimport { createCanvasNodeByType } from \"./node/_factory\";\nimport { NODE_NAME_FOR_SELECT } from \"./utils/const\";\nimport { createNodeByType, updateNodeByType } from \"./utils/draft\";\nimport { v4 as uuid } from \"uuid\";\n\nexport class CanvasCore extends CanvasState {\n #canvasStage: CanvasStage;\n #mainLayer: Konva.Layer;\n #canvasTransformer: CanvasTransformer;\n #draftNode: ICanvasNode | null = null;\n\n constructor(el: HTMLDivElement) {\n // 调用父类构造函数,初始化状态\n super({\n viewport: {\n x: 0,\n y: 0,\n width: el.clientWidth,\n height: el.clientHeight,\n scale: 1,\n },\n toolType: \"select\",\n nodes: [],\n });\n\n // 使用 CanvasStage 替代直接创建 Konva.Stage\n this.#canvasStage = new CanvasStage(this, {\n container: el,\n width: el.clientWidth,\n height: el.clientHeight,\n draggable: false,\n className: \"touch-none\",\n });\n\n this.#mainLayer = new Konva.Layer();\n this.#canvasTransformer = new CanvasTransformer(this);\n this.#canvasStage.getStage().add(this.#mainLayer);\n this.#mainLayer.add(this.#canvasTransformer.getTransformer());\n\n // 设置初始视口状态\n this.updateViewport(this.getState().viewport, false);\n }\n\n /**\n * 获取 CanvasStage 实例\n */\n getCanvasStage(): CanvasStage {\n return this.#canvasStage;\n }\n\n /**\n * 获取 CanvasTransformer 实例\n */\n getCanvasTransformer(): CanvasTransformer {\n return this.#canvasTransformer;\n }\n\n /**\n * 发射事件(供内部类使用)\n */\n emitEvent<K extends keyof import(\"./state\").StateEvents>(\n event: K,\n data: import(\"./state\").StateEvents[K]\n ): void {\n this.emit(event, data);\n }\n\n /**\n * 获取 Konva.Stage 实例\n */\n getStage(): Konva.Stage {\n return this.#canvasStage.getStage();\n }\n\n /**\n * 获取 Stage 容器元素\n */\n getContainer(): HTMLDivElement {\n return this.#canvasStage.getStage().container();\n }\n\n /**\n * 获取主图层\n */\n getMainLayer(): Konva.Layer {\n return this.#mainLayer;\n }\n\n /**\n * 获取当前工具类型\n */\n getToolType(): ToolType {\n return this.getState().toolType;\n }\n\n /**\n * 设置当前工具类型(内部使用)\n */\n setToolType(type: ToolType): void {\n this.selectNode(); // 取消选择所有节点\n\n this._updateState(\n {\n toolType: type,\n },\n false\n );\n\n // emit toolType 变化事件\n this.emit(\"toolType:change\", type);\n\n if (type === \"hand\") {\n this.#canvasStage.setDraggable(true);\n this.#canvasStage.setCursor(\"grab\");\n } else {\n this.#canvasStage.setDraggable(false);\n this.#canvasStage.resetCursor();\n }\n }\n\n /**\n * 设置是否可拖拽(内部使用)\n */\n protected setDraggable(draggable: boolean): void {\n this.#canvasStage.setDraggable(draggable);\n }\n\n /**\n * 设置光标\n * @internal 仅供内部使用\n */\n setCursor(cursor: string): void {\n this.#canvasStage.setCursor(cursor);\n }\n\n /**\n * 重置光标\n * @internal 仅供内部使用\n */\n resetCursor(): void {\n this.#canvasStage.resetCursor();\n }\n\n /**\n * 获取当前 Stage 缩放比例\n */\n getStageScale(): number {\n return this.#canvasStage.getStage().scaleX();\n }\n\n /**\n * 更新视口位置\n * @internal 仅供内部使用,外部请使用 CanvasApi\n */\n updateViewport(\n viewport: Partial<ICoreState[\"viewport\"]>,\n addToHistory = false\n ): void {\n this.#canvasStage.setViewport(viewport);\n\n const newViewport = {\n ...this.getState().viewport,\n ...viewport,\n };\n\n this._updateState(\n {\n viewport: newViewport,\n },\n addToHistory\n );\n\n // emit viewport 变化事件\n this.emit(\"viewport:change\", newViewport);\n\n // 计算并 emit transformer 位置 (由 transformer 内部处理)\n this.#canvasTransformer.emitPositionChange();\n }\n\n protected createNodes(nodes: INode[]): void {\n const canvasNodes = nodes\n .map((node) => createCanvasNodeByType(this, node.type, node))\n .filter((node): node is NonNullable<typeof node> => node !== null);\n\n canvasNodes.forEach((node) => {\n this.#mainLayer.add(node.getElement());\n });\n\n const newNodes = [...(this.getState().nodes || []), ...nodes];\n this._updateState(\n {\n nodes: newNodes,\n },\n true\n );\n }\n\n /**\n * 创建图片标注节点(内部使用)\n */\n protected createImageMarkerNode(\n parentImageId: string,\n startPosition: { x: number; y: number },\n endPosition: { x: number; y: number },\n imageBounds: { x: number; y: number; width: number; height: number }\n ): void {\n // 计算下一个标注编号\n const nodes = this.getState().nodes || [];\n let maxMarkerNumber = 0;\n nodes.forEach((node) => {\n if (\n node.type === \"image-marker\" &&\n node.meta.parent === parentImageId &&\n typeof node.meta.markerNumber === \"number\"\n ) {\n maxMarkerNumber = Math.max(maxMarkerNumber, node.meta.markerNumber);\n }\n });\n\n // 计算相对位置百分比\n const startPercentX =\n ((startPosition.x - imageBounds.x) / imageBounds.width) * 100;\n const startPercentY =\n ((startPosition.y - imageBounds.y) / imageBounds.height) * 100;\n const endPercentX =\n ((endPosition.x - imageBounds.x) / imageBounds.width) * 100;\n const endPercentY =\n ((endPosition.y - imageBounds.y) / imageBounds.height) * 100;\n\n // 计算标注的位置和尺寸\n const x = Math.min(startPosition.x, endPosition.x);\n const y = Math.min(startPosition.y, endPosition.y);\n const width = Math.abs(endPosition.x - startPosition.x);\n const height = Math.abs(endPosition.y - startPosition.y);\n\n const markerNode: INode<\"image-marker\"> = {\n id: uuid(),\n type: \"image-marker\",\n props: {\n x,\n y,\n width,\n height,\n rotation: 0,\n visible: true,\n },\n style: {\n color: \"#ff0000\",\n line: \"dashed\",\n size: \"medium\",\n opacity: 1,\n },\n meta: {\n parent: parentImageId,\n markerNumber: maxMarkerNumber + 1,\n relativePosition: {\n start: {\n percentX: Math.max(0, Math.min(100, startPercentX)),\n percentY: Math.max(0, Math.min(100, startPercentY)),\n },\n end: {\n percentX: Math.max(0, Math.min(100, endPercentX)),\n percentY: Math.max(0, Math.min(100, endPercentY)),\n },\n },\n },\n };\n\n this.createNodes([markerNode]);\n }\n\n /**\n * 在指定位置查找图片节点\n * @internal 仅供内部使用\n */\n findImageAtPosition(position: { x: number; y: number }): Konva.Image | null {\n const stage = this.#canvasStage.getStage();\n\n // 临时开启所有图片元素的 listening 状态\n const imageShapes = stage.find(\n (node: Konva.Node) => node.getClassName() === \"Image\"\n );\n const originalListeningStates = imageShapes.map((shape) =>\n shape.listening()\n );\n imageShapes.forEach((shape) => shape.listening(true));\n\n try {\n const shapes = stage.getAllIntersections(position);\n\n // 找到最上层的图片\n const imageShapesAtPos = shapes.filter(\n (shape) => shape.getClassName() === \"Image\"\n );\n if (imageShapesAtPos.length === 0) return null;\n\n return imageShapesAtPos[imageShapesAtPos.length - 1] as Konva.Image;\n } finally {\n // 恢复原始的 listening 状态\n imageShapes.forEach((shape, index) => {\n shape.listening(originalListeningStates[index]);\n });\n }\n }\n\n /**\n * @internal 仅供内部使用\n */\n createDraftNode(\n type: NodeType,\n position: { x: number; y: number },\n meta?: {\n parent?: string;\n bounds?: { x: number; y: number; width: number; height: number };\n startPosition?: { x: number; y: number };\n }\n ): void {\n if (this.#draftNode) {\n this.#draftNode.destroy();\n }\n\n const node = createNodeByType(type, position, undefined, meta);\n\n this.#draftNode = createCanvasNodeByType(this, type, node);\n\n console.log(this.#draftNode);\n if (!this.#draftNode) return;\n this.#mainLayer.add(this.#draftNode.getElement());\n }\n\n /**\n * @internal 仅供内部使用\n */\n updateDraftNode(\n position: { x: number; y: number },\n bounds?: { x: number; y: number; width: number; height: number }\n ): void {\n if (!this.#draftNode) return;\n const node = this.#draftNode.getNode();\n const updatedNode = updateNodeByType(node, position, bounds);\n this.#draftNode.updateNode(updatedNode);\n }\n\n /**\n * @internal 仅供内部使用\n */\n finalizeDraftNode(): void {\n if (!this.#draftNode) return;\n const id = uuid();\n\n const draftNode = this.#draftNode.getNode();\n\n // 处理 image-marker 的特殊逻辑\n if (draftNode.type === \"image-marker\" && draftNode.meta.parent) {\n const bounds = draftNode.meta.bounds as {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n const startPosition = draftNode.meta.startPosition as {\n x: number;\n y: number;\n };\n const endPosition = {\n x: draftNode.props.x + (draftNode.props.width || 0),\n y: draftNode.props.y + (draftNode.props.height || 0),\n };\n\n // 计算下一个标注编号\n const nodes = this.getState().nodes || [];\n let maxMarkerNumber = 0;\n nodes.forEach((node) => {\n if (\n node.type === \"image-marker\" &&\n node.meta.parent === draftNode.meta.parent &&\n typeof node.meta.markerNumber === \"number\"\n ) {\n maxMarkerNumber = Math.max(maxMarkerNumber, node.meta.markerNumber);\n }\n });\n\n // 计算相对位置百分比\n const startPercentX = ((startPosition.x - bounds.x) / bounds.width) * 100;\n const startPercentY =\n ((startPosition.y - bounds.y) / bounds.height) * 100;\n const endPercentX = ((endPosition.x - bounds.x) / bounds.width) * 100;\n const endPercentY = ((endPosition.y - bounds.y) / bounds.height) * 100;\n\n const node: INode<\"image-marker\"> = {\n ...draftNode,\n props: {\n ...draftNode.props,\n },\n style: {\n ...draftNode.style,\n },\n meta: {\n parent: draftNode.meta.parent,\n markerNumber: maxMarkerNumber + 1,\n relativePosition: {\n start: {\n percentX: Math.max(0, Math.min(100, startPercentX)),\n percentY: Math.max(0, Math.min(100, startPercentY)),\n },\n end: {\n percentX: Math.max(0, Math.min(100, endPercentX)),\n percentY: Math.max(0, Math.min(100, endPercentY)),\n },\n },\n },\n id,\n type: \"image-marker\",\n };\n\n this.createNodes([node]);\n this.#draftNode.destroy();\n this.#draftNode = null;\n this.setToolType(\"select\");\n return;\n }\n\n const node: INode = {\n ...draftNode,\n props: {\n ...draftNode.props,\n },\n style: {\n ...draftNode.style,\n },\n meta: {\n ...draftNode.meta,\n },\n id,\n };\n\n this.createNodes([node]);\n this.#draftNode.destroy();\n this.#draftNode = null;\n this.setToolType(\"select\");\n }\n\n /**\n * 选择节点\n * @internal 仅供内部使用,外部请使用 CanvasApi\n */\n selectNode(nodeId?: string, multiSelect: boolean = false): void {\n const curSelectedNodeIds = this.getState().selectedNodeIds ?? [];\n\n if (curSelectedNodeIds.length === 0 && !nodeId) {\n return;\n }\n\n if (!nodeId) {\n this.#canvasTransformer.clearNodes();\n this._updateState(\n {\n selectedNodeIds: [],\n },\n false\n );\n return;\n }\n\n let selectedNodeIds: string[] = [];\n if (multiSelect) {\n selectedNodeIds = curSelectedNodeIds.length\n ? [...curSelectedNodeIds, nodeId]\n : [nodeId];\n } else {\n selectedNodeIds = [nodeId];\n }\n\n const nodes = this.getStage()\n .find(`.${NODE_NAME_FOR_SELECT}`)\n .filter((node) => {\n const id = node.id();\n return selectedNodeIds.includes(id);\n });\n\n this.#canvasTransformer.setNodes(nodes);\n\n this._updateState(\n {\n selectedNodeIds,\n },\n false\n );\n }\n\n /**\n * 销毁 canvas\n */\n dispose(): void {\n this.getCanvasTransformer().destroy();\n this.getMainLayer().destroy();\n this.getCanvasStage().destroy();\n this._dispose();\n }\n\n /**\n * 从元素同步节点数据(供节点类内部使用)\n */\n _syncNodeFromElement(nodeId: string, updates: Partial<INode>): void {\n const nodes = this.getState().nodes || [];\n const nodeIndex = nodes.findIndex((n) => n.id === nodeId);\n\n if (nodeIndex === -1) return;\n\n const updatedNode = {\n ...nodes[nodeIndex],\n ...updates,\n props: {\n ...nodes[nodeIndex].props,\n ...updates.props,\n },\n style: {\n ...nodes[nodeIndex].style,\n ...updates.style,\n },\n meta: {\n ...nodes[nodeIndex].meta,\n ...updates.meta,\n },\n };\n\n const newNodes = [...nodes];\n newNodes[nodeIndex] = updatedNode;\n\n this._updateState(\n {\n nodes: newNodes,\n },\n true\n );\n }\n\n /**\n * 实现父类的状态同步方法\n * 当 undo/redo 时被调用\n */\n protected _syncState(state: ICoreState): void {\n this.#canvasStage.setViewport({\n x: state.viewport.x,\n y: state.viewport.y,\n scale: state.viewport.scale,\n width: state.viewport.width,\n height: state.viewport.height,\n });\n }\n}\n","import type { ICoreState, ToolType, INode } from \"./type\";\nimport { CanvasCore } from \"./core\";\nimport { v4 as uuid } from \"uuid\";\nimport { NODE_NAME_FOR_SELECT } from \"./utils/const\";\n\n/**\n * CanvasApi 是面向外部使用的公开 API 类\n * 继承自 CanvasCore,只暴露必要的公开方法\n */\nexport class CanvasApi extends CanvasCore {\n /**\n * 获取所有可用的工具类型\n */\n getAvailableTools(): ToolType[] {\n return [\"select\", \"hand\", \"rectangle\", \"image-marker\"];\n }\n\n /**\n * 设置当前工具类型\n */\n override setToolType(type: ToolType): void {\n super.setToolType(type);\n }\n\n /**\n * 手动创建多个节点\n * 如果你不知道自己在干什么,请使用更高层的封装方法,如 createImageNode\n */\n public override createNodes(nodes: INode[]): void {\n super.createNodes(nodes);\n }\n\n /**\n * 更新视口位置\n */\n updateViewport(\n viewport: Partial<ICoreState[\"viewport\"]>,\n addToHistory = false\n ): void {\n super.updateViewport(viewport, addToHistory);\n }\n\n /**\n * 创建图片节点\n */\n createImageNode(imageUrl: string, position?: { x: number; y: number }): void {\n const pos = position ?? { x: 100, y: 100 };\n\n const imageNode: INode<\"image\"> = {\n id: uuid(),\n type: \"image\",\n props: {\n x: pos.x,\n y: pos.y,\n width: undefined,\n height: undefined,\n rotation: 0,\n visible: true,\n },\n style: {\n color: \"#000000\",\n line: \"solid\",\n size: \"medium\",\n opacity: 1,\n },\n meta: {\n imageUrl,\n },\n };\n\n this.createNodes([imageNode]);\n }\n\n /**\n * 导出全部图形为图片\n * @param options - 导出配置\n * @returns DataURL 格式的图片数据\n */\n exportAsImage(options?: {\n pixelRatio?: number;\n mimeType?: string;\n quality?: number;\n }): string {\n const stage = this.getStage();\n const transformer = this.getCanvasTransformer().getTransformer();\n const transformerVisible = transformer.visible();\n transformer.visible(false);\n\n try {\n return stage.toDataURL({\n pixelRatio: options?.pixelRatio ?? 2,\n mimeType: options?.mimeType ?? \"image/png\",\n quality: options?.quality ?? 1,\n });\n } finally {\n transformer.visible(transformerVisible);\n }\n }\n\n /**\n * 导出当前选区为图片\n * @param options - 导出配置\n * @returns DataURL 格式的图片数据,如果没有选区则返回 null\n */\n exportSelectionAsImage(options?: {\n pixelRatio?: number;\n mimeType?: string;\n quality?: number;\n padding?: number;\n }): string | null {\n const position = this.getCanvasTransformer().getPosition();\n if (!position) {\n console.warn(\"No selection to export\");\n return null;\n }\n\n const stage = this.getStage();\n const padding = options?.padding ?? 0;\n const transformer = this.getCanvasTransformer().getTransformer();\n const transformerVisible = transformer.visible();\n transformer.visible(false);\n\n try {\n return stage.toDataURL({\n x: position.x - padding,\n y: position.y - padding,\n width: position.width + padding * 2,\n height: position.height + padding * 2,\n pixelRatio: options?.pixelRatio ?? 1,\n mimeType: options?.mimeType ?? \"image/png\",\n quality: options?.quality ?? 1,\n });\n } finally {\n transformer.visible(transformerVisible);\n }\n }\n\n /**\n * 删除当前选中的节点\n * 如果删除的是 image 节点,会同步删除所有关联的 image-marker\n */\n deleteSelectedNodes(): void {\n const selectedNodeIds = this.getState().selectedNodeIds || [];\n if (selectedNodeIds.length === 0) return;\n this.deleteNodes(selectedNodeIds);\n }\n\n /**\n * 删除指定的节点\n * 如果删除的是 image 节点,会同步删除所有关联的 image-marker\n * @param nodeIds - 要删除的节点 ID 数组\n */\n deleteNodes(nodeIds: string[]): void {\n if (nodeIds.length === 0) return;\n\n const nodes = this.getState().nodes || [];\n const idsToDelete = new Set(nodeIds);\n\n // 查找所有需要删除的节点(包括 image 关联的 image-marker)\n nodeIds.forEach((id) => {\n const node = nodes.find((n) => n.id === id);\n if (node?.type === \"image\") {\n nodes.forEach((n) => {\n if (n.type === \"image-marker\" && n.meta.parent === id) {\n idsToDelete.add(n.id);\n }\n });\n }\n });\n\n // 从 stage 中移除元素\n idsToDelete.forEach((id) => {\n const shape = this.getStage().findOne(`#${id}`);\n if (shape) {\n shape.destroy();\n }\n });\n\n // 从状态中移除节点\n const newNodes = nodes.filter((n) => !idsToDelete.has(n.id));\n\n // 清除选区\n this.getCanvasTransformer().clearNodes();\n\n this._updateState(\n {\n nodes: newNodes,\n selectedNodeIds: [],\n },\n true\n );\n }\n\n /**\n * 滚动到内容区域\n * - 如果提供了 nodeIds,将指定的节点居中显示\n * - 如果没有提供 nodeIds 但有选中的节点,将选中节点居中显示\n * - 如果没有选中节点,将所有内容居中显示\n * @param options - 配置选项\n * @param options.padding - 内容周围的留白,默认 50px\n * @param options.scale - 是否自动调整缩放以适应内容,默认 false\n * @param options.nodeIds - 要滚动到的节点 ID 数组\n */\n scrollToContent(options?: {\n padding?: number;\n scale?: boolean;\n nodeIds?: string[];\n }): void {\n const nodes = this.getState().nodes || [];\n if (nodes.length === 0) return;\n\n const padding = options?.padding ?? 50;\n const shouldScale = options?.scale === true;\n const targetNodeIds = options?.nodeIds;\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n const mainLayer = this.getMainLayer();\n const selectedNodeIds = this.getState().selectedNodeIds || [];\n\n // 确定要显示的节点:优先使用 targetNodeIds,其次是选中的节点\n const hasTargetIds = targetNodeIds && targetNodeIds.length > 0;\n const hasSelection = !hasTargetIds && selectedNodeIds.length > 0;\n const idsToShow = hasTargetIds\n ? targetNodeIds\n : hasSelection\n ? selectedNodeIds\n : null;\n\n mainLayer.children.forEach((child) => {\n if (\n child.visible() &&\n child.getClassName() !== \"Transformer\" &&\n child.hasName(NODE_NAME_FOR_SELECT)\n ) {\n if (idsToShow) {\n const id = child.id();\n if (!idsToShow.includes(id)) return;\n }\n\n const attrs = child.getAttrs();\n const x = attrs.x || 0;\n const y = attrs.y || 0;\n const width = attrs.width || 0;\n const height = attrs.height || 0;\n const rotation = attrs.rotation || 0;\n\n if (rotation) {\n const box = child.getClientRect({ skipTransform: false });\n const stage = this.getStage();\n const currentScale = stage.scaleX();\n const currentX = stage.x();\n const currentY = stage.y();\n\n const worldMinX = (box.x - currentX) / currentScale;\n const worldMinY = (box.y - currentY) / currentScale;\n const worldMaxX = (box.x + box.width - currentX) / currentScale;\n const worldMaxY = (box.y + box.height - currentY) / currentScale;\n\n minX = Math.min(minX, worldMinX);\n minY = Math.min(minY, worldMinY);\n maxX = Math.max(maxX, worldMaxX);\n maxY = Math.max(maxY, worldMaxY);\n } else {\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n maxX = Math.max(maxX, x + width);\n maxY = Math.max(maxY, y + height);\n }\n }\n });\n\n if (minX === Infinity || minY === Infinity) return;\n\n const contentWidth = maxX - minX;\n const contentHeight = maxY - minY;\n const contentCenterX = minX + contentWidth / 2;\n const contentCenterY = minY + contentHeight / 2;\n\n const viewport = this.getState().viewport;\n let newScale = viewport.scale;\n\n if (shouldScale) {\n const scaleX = (viewport.width - padding * 2) / contentWidth;\n const scaleY = (viewport.height - padding * 2) / contentHeight;\n newScale = Math.min(scaleX, scaleY, 1);\n }\n\n const x = viewport.width / 2 - contentCenterX * newScale;\n const y = viewport.height / 2 - contentCenterY * newScale;\n\n this.updateViewport({ x, y, scale: newScale }, true);\n }\n}\n","/**\n * Modulate a value between two ranges.\n *\n * @example\n *\n * ```ts\n * const A = modulate(0, [0, 1], [0, 100])\n * ```\n *\n * @param value - The interpolation value.\n * @param rangeA - From [low, high]\n * @param rangeB - To [low, high]\n * @param clamp - Whether to clamp the the result to [low, high]\n * @public\n */\nexport function modulate(\n value: number,\n rangeA: number[],\n rangeB: number[],\n clamp = false\n): number {\n const [fromLow, fromHigh] = rangeA;\n const [v0, v1] = rangeB;\n const result = v0 + ((value - fromLow) / (fromHigh - fromLow)) * (v1 - v0);\n\n return clamp\n ? v0 < v1\n ? Math.max(Math.min(result, v1), v0)\n : Math.max(Math.min(result, v0), v1)\n : result;\n}\n\nconst gridSteps = [\n {\n min: -1,\n mid: 0.15,\n step: 64,\n },\n {\n min: 0.05,\n mid: 0.375,\n step: 16,\n },\n {\n min: 0.15,\n mid: 1,\n step: 4,\n },\n {\n min: 0.7,\n mid: 2.5,\n step: 1,\n },\n];\n\ninterface GridBackgroundProps {\n viewportX: number;\n viewportY: number;\n scale: number;\n size?: number;\n showGrid?: boolean;\n}\n\nexport function GridBackground({\n viewportX,\n viewportY,\n scale,\n size = 20,\n showGrid = true,\n}: GridBackgroundProps) {\n const x = viewportX / scale;\n const y = viewportY / scale;\n const z = scale;\n\n if (!showGrid) {\n return null;\n }\n\n return (\n <svg\n className=\"canvas-grid w-full h-full absolute top-0 left-0\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n aria-hidden=\"true\"\n >\n <defs>\n {gridSteps.map(({ min, mid, step }, i) => {\n const s = step * size * z;\n const xo = 0.5 + x * z;\n const yo = 0.5 + y * z;\n const gxo = xo > 0 ? xo % s : s + (xo % s);\n const gyo = yo > 0 ? yo % s : s + (yo % s);\n const opacity = z < mid ? modulate(z, [min, mid], [0, 1]) : 1;\n\n return (\n <pattern\n key={i}\n id={`grid_${step}`}\n width={s}\n height={s}\n patternUnits=\"userSpaceOnUse\"\n >\n <circle\n className=\"tl-grid-dot\"\n cx={gxo}\n cy={gyo}\n r={1}\n opacity={opacity}\n />\n </pattern>\n );\n })}\n </defs>\n {gridSteps.map(({ step }, i) => (\n <rect key={i} width=\"100%\" height=\"100%\" fill={`url(#grid_${step})`} />\n ))}\n </svg>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","import { Button } from \"@/components/ui/button\";\nimport { Minus, Plus } from \"lucide-react\";\nimport type { CanvasApi } from \"../core/api\";\nimport type { ICoreState } from \"../core/type\";\nimport { useEffect, useState } from \"react\";\n\ninterface ZoomPanelProps {\n api: CanvasApi;\n}\n\nexport function ZoomPanel({ api }: ZoomPanelProps) {\n const [viewport, setViewport] = useState(api.getState().viewport);\n useEffect(() => {\n api.on(\"viewport:change\", (newViewport: ICoreState[\"viewport\"]) => {\n setViewport(newViewport);\n });\n }, [setViewport, api]);\n const updateScale = (scale: number) => {\n const halfWidth = viewport.width / 2;\n const halfHeight = viewport.height / 2;\n const worldCenterX = (halfWidth - viewport.x) / viewport.scale;\n const worldCenterY = (halfHeight - viewport.y) / viewport.scale;\n const x = halfWidth - worldCenterX * scale;\n const y = halfHeight - worldCenterY * scale;\n api.updateViewport({ x, y, scale });\n };\n\n const handleZoomIn = () => {\n const scale = Math.min(viewport.scale * 1.2, 5);\n updateScale(scale);\n };\n\n const handleZoomOut = () => {\n const scale = Math.max(viewport.scale / 1.2, 0.1);\n updateScale(scale);\n };\n\n const handleReset = () => {\n updateScale(1);\n };\n\n const percent = Math.round(viewport.scale * 100);\n\n return (\n <div className=\"zoom-panel flex items-center gap-2\">\n <Button\n size={\"sm\"}\n variant=\"secondary\"\n onClick={handleZoomOut}\n title=\"缩小\"\n >\n <Minus />\n </Button>\n <Button\n size={\"sm\"}\n variant=\"secondary\"\n onClick={handleReset}\n title={`${percent}%`}\n className=\"min-w-16\"\n >\n {percent}%\n </Button>\n <Button\n size={\"sm\"}\n variant=\"secondary\"\n onClick={handleZoomIn}\n title=\"放大\"\n >\n <Plus />\n </Button>\n </div>\n );\n}\n","import { Button } from \"@/components/ui/button\";\nimport { Undo2, Redo2 } from \"lucide-react\";\nimport type { CanvasApi } from \"../core/api\";\nimport { useState, useEffect } from \"react\";\n\ninterface HistoryPanelProps {\n api: CanvasApi;\n}\n\nexport function HistoryPanel({ api }: HistoryPanelProps) {\n const [canUndo, setCanUndo] = useState(api.canUndo());\n const [canRedo, setCanRedo] = useState(api.canRedo());\n\n useEffect(() => {\n // 监听状态变化\n const handleStateChange = () => {\n setCanUndo(api.canUndo());\n setCanRedo(api.canRedo());\n };\n\n api.on(\"state:change\", handleStateChange);\n\n return () => {\n api.off(\"state:change\", handleStateChange);\n };\n }, [api]);\n\n return (\n <div className=\"history-panel flex items-center gap-2\">\n <Button\n size={\"sm\"}\n variant=\"secondary\"\n disabled={!canUndo}\n onClick={() => api.undo()}\n title=\"撤销\"\n >\n <Undo2 />\n </Button>\n <Button\n size={\"sm\"}\n variant=\"secondary\"\n disabled={!canRedo}\n onClick={() => api.redo()}\n title=\"重做\"\n >\n <Redo2 />\n </Button>\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { CanvasApi } from \"./core/api\";\nimport { GridBackground } from \"./jsx/GridBackground\";\nimport { ZoomPanel } from \"./jsx/ZoomPanel\";\nimport { HistoryPanel } from \"./jsx/HistoryPanel\";\n\ninterface PureCanvasProps {\n setApi?: (core: CanvasApi) => void;\n}\n\nexport function PureCanvas({ setApi }: PureCanvasProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n const [_api, _setApi] = useState<CanvasApi | null>(null);\n\n const [viewport, setViewport] = useState({ x: 0, y: 0, scale: 1 });\n\n useEffect(() => {\n if (!containerRef.current) return;\n\n // 创建 Core 实例\n const core = new CanvasApi(containerRef.current);\n _setApi(core);\n setApi?.(core);\n\n // 设置事件处理器\n // core.subscribe((state) => {\n // console.log(\"Canvas state updated:\", state);\n // setViewport(state.viewport);\n // });\n\n core.on(\"viewport:change\", (newViewport) => {\n setViewport(newViewport);\n });\n\n core.on(\"transformer:positionChange\", (position) => {\n // 处理 Transformer 位置变化\n console.log(\"Transformer position changed:\", position);\n });\n\n // 清理\n return () => {\n core.dispose();\n };\n }, [setApi]);\n\n return (\n <div className=\"pure-canvas relative size-full\">\n <GridBackground\n viewportX={viewport.x}\n viewportY={viewport.y}\n scale={viewport.scale}\n />\n <div ref={containerRef} className=\"size-full\" />\n {_api && (\n <>\n <div className=\"history-panel-wrapper absolute bottom-4 left-4 z-10\">\n <HistoryPanel api={_api} />\n </div>\n <div className=\"zoom-panel-wrapper absolute bottom-4 right-4 z-10\">\n <ZoomPanel api={_api} />\n </div>\n </>\n )}\n </div>\n );\n}\n"],"names":["CanvasStage","core","config","__privateAdd","_CanvasStage_instances","_core","_stage","_viewport","_handleWheel","pointer","__privateGet","oldScale","mousePointTo","scaleBy","direction","steps","newScale","i","scale","newPos","deltaX","deltaY","_handlePointerDown","event","toolType","clickedOnEmpty","pointerPos","nodeId","imageShape","width","height","imageBounds","_handlePointerMove","_handlePointerUp","_handleDragStart","_handleDragMove","_handleDragEnd","__privateSet","Konva","__privateMethod","setupEventListeners_fn","viewport","newViewport","draggable","cursor","container","CanvasTransformer","_CanvasTransformer_instances","_transformer","_handleTransformStart","_handleTransform","_handleTransformEnd","box","nodes","position","CanvasState","initialState","__publicField","mitt","handler","data","previous","newPast","next","newFuture","partial","addToHistory","newState","_state","NODE_NAME_FOR_SELECT","RECT","IMAGE","calculatePerimeter","cornerRadius","getDashValue","shapeLength","strokeWidth","lineStyle","ratio","dashLength","dashGap","dashCount","getSizeValue","key","getTotalDashLength","dash","getRectSize","rect","BaseCanvasNode","node","isSelect","createRectAnimation","totalDashLength","anim","frame","dashOffset","RectNode","_RectNode_instances","_animation","initAnimation_fn","setupEventHandlers_fn","destroyAnimation_fn","element","totalLength","d","newProps","ImageNode","_ImageNode_instances","loadImage_fn","placeholder","img","imageUrl","syncImageMarkers_fn","syncImageMarkersToState_fn","layer","imgX","imgY","imgWidth","imgHeight","imageMarkerElements","nodeElement","nodeData","n","start","end","startX","startY","endX","endY","newX","newY","newWidth","newHeight","child","ImageMarkerNode","_ImageMarkerNode_instances","_rect","_markerGroup","_circle","_text","group","markerGroup","radius","circle","text","isFocus","isSelected","createCanvasNodeByType","type","createNodeByType","style","meta","baseNode","uuid","updateNodeByType","bounds","finalPosition","p1","p2","normalizePoints","p1x","p1y","p2x","p2y","CanvasCore","el","_canvasStage","_mainLayer","_canvasTransformer","_draftNode","newNodes","parentImageId","startPosition","endPosition","maxMarkerNumber","startPercentX","startPercentY","endPercentX","endPercentY","x","y","markerNode","stage","imageShapes","originalListeningStates","shape","imageShapesAtPos","index","updatedNode","id","draftNode","multiSelect","curSelectedNodeIds","selectedNodeIds","updates","nodeIndex","state","CanvasApi","pos","imageNode","options","transformer","transformerVisible","padding","nodeIds","idsToDelete","shouldScale","targetNodeIds","minX","minY","maxX","maxY","mainLayer","hasTargetIds","hasSelection","idsToShow","attrs","currentScale","currentX","currentY","worldMinX","worldMinY","worldMaxX","worldMaxY","contentWidth","contentHeight","contentCenterX","contentCenterY","scaleX","scaleY","modulate","value","rangeA","rangeB","clamp","fromLow","fromHigh","v0","v1","result","gridSteps","GridBackground","viewportX","viewportY","size","showGrid","z","jsxs","jsx","min","mid","step","s","xo","yo","gxo","gyo","opacity","cn","inputs","twMerge","clsx","buttonVariants","cva","Button","className","variant","asChild","props","Slot","ZoomPanel","api","setViewport","useState","useEffect","updateScale","halfWidth","halfHeight","worldCenterX","worldCenterY","handleZoomIn","handleZoomOut","handleReset","percent","Minus","Plus","HistoryPanel","canUndo","setCanUndo","canRedo","setCanRedo","handleStateChange","Undo2","Redo2","PureCanvas","setApi","containerRef","useRef","_api","_setApi","Fragment"],"mappings":"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"}
|
package/dist/index.umd.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
(function(d,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("react/jsx-runtime"),require("react"),require("konva"),require("mitt"),require("uuid"),require("@radix-ui/react-slot"),require("class-variance-authority"),require("clsx"),require("tailwind-merge"),require("lucide-react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","konva","mitt","uuid","@radix-ui/react-slot","class-variance-authority","clsx","tailwind-merge","lucide-react"],h):(d=typeof globalThis<"u"?globalThis:d||self,h(d.konvaWhiteboard={},d.jsxRuntime,d.React,d.Konva,d.mitt,d.uuid,d.ReactSlot,d.ClassVarianceAuthority,d.clsx,d.tailwindMerge,d.LucideReact))})(this,(function(d,h,f,C,Ft,$,jt,qt,Wt,$t,tt){"use strict";var Se=Object.defineProperty;var Rt=d=>{throw TypeError(d)};var Ne=(d,h,f)=>h in d?Se(d,h,{enumerable:!0,configurable:!0,writable:!0,value:f}):d[h]=f;var V=(d,h,f)=>Ne(d,typeof h!="symbol"?h+"":h,f),bt=(d,h,f)=>h.has(d)||Rt("Cannot "+f);var a=(d,h,f)=>(bt(d,h,"read from private field"),f?f.call(d):h.get(d)),u=(d,h,f)=>h.has(d)?Rt("Cannot add the same private member more than once"):h instanceof WeakSet?h.add(d):h.set(d,f),N=(d,h,f,C)=>(bt(d,h,"write to private field"),C?C.call(d,f):h.set(d,f),f),_=(d,h,f)=>(bt(d,h,"access private method"),f);var w,p,Y,et,rt,it,ot,at,st,nt,lt,Ut,B,x,ct,ht,dt,gt,pt,ut,mt,Vt,I,X,kt,St,Lt,z,Nt,Ot,Mt,_t,L,P,J,Q,ft,Ht,b,Z,R,S;var It=document.createElement("style");It.textContent=`@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-cyan-500:oklch(71.5% .143 215.221);--color-cyan-600:oklch(60.9% .126 221.723);--color-cyan-700:oklch(52% .105 223.128);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-medium:500;--font-weight-bold:700;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){*{outline-color:color-mix(in oklab,var(--ring)50%,transparent)}}body{background-color:var(--background);color:var(--foreground)}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.static{position:static}.top-0{top:calc(var(--spacing)*0)}.top-4{top:calc(var(--spacing)*4)}.right-4{right:calc(var(--spacing)*4)}.bottom-4{bottom:calc(var(--spacing)*4)}.left-0{left:calc(var(--spacing)*0)}.left-4{left:calc(var(--spacing)*4)}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.size-8{width:calc(var(--spacing)*8);height:calc(var(--spacing)*8)}.size-9{width:calc(var(--spacing)*9);height:calc(var(--spacing)*9)}.size-10{width:calc(var(--spacing)*10);height:calc(var(--spacing)*10)}.size-full{width:100%;height:100%}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-\\[500px\\]{height:500px}.h-full{height:100%}.max-h-40{max-height:calc(var(--spacing)*40)}.w-\\[700px\\]{width:700px}.w-full{width:100%}.max-w-xs{max-width:var(--container-xs)}.min-w-16{min-width:calc(var(--spacing)*16)}.shrink-0{flex-shrink:0}.-translate-x-1\\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.touch-none{touch-action:none}.resize{resize:both}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.gap-1\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.overflow-auto{overflow:auto}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.bg-background{background-color:var(--background)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-cyan-500{background-color:var(--color-cyan-500)}.bg-cyan-600{background-color:var(--color-cyan-600)}.bg-destructive{background-color:var(--destructive)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-green-500{background-color:var(--color-green-500)}.bg-indigo-500{background-color:var(--color-indigo-500)}.bg-primary{background-color:var(--primary)}.bg-purple-500{background-color:var(--color-purple-500)}.bg-red-500{background-color:var(--color-red-500)}.bg-secondary{background-color:var(--secondary)}.bg-white{background-color:var(--color-white)}.p-2{padding:calc(var(--spacing)*2)}.p-4{padding:calc(var(--spacing)*4)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-2{padding-block:calc(var(--spacing)*2)}.pt-4{padding-top:calc(var(--spacing)*4)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-gray-400{color:var(--color-gray-400)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-white{color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}@media(hover:hover){.hover\\:bg-accent:hover{background-color:var(--accent)}.hover\\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\\:bg-cyan-600:hover{background-color:var(--color-cyan-600)}.hover\\:bg-cyan-700:hover{background-color:var(--color-cyan-700)}.hover\\:bg-destructive\\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\\:bg-destructive\\/90:hover{background-color:color-mix(in oklab,var(--destructive)90%,transparent)}}.hover\\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\\:bg-green-600:hover{background-color:var(--color-green-600)}.hover\\:bg-indigo-600:hover{background-color:var(--color-indigo-600)}.hover\\:bg-primary\\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\\:bg-primary\\/90:hover{background-color:color-mix(in oklab,var(--primary)90%,transparent)}}.hover\\:bg-purple-600:hover{background-color:var(--color-purple-600)}.hover\\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\\:bg-secondary\\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\\:bg-secondary\\/80:hover{background-color:color-mix(in oklab,var(--secondary)80%,transparent)}}.hover\\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\\:underline:hover{text-decoration-line:underline}}.focus-visible\\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\\:ring-\\[3px\\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(3px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:color-mix(in oklab,var(--ring)50%,transparent)}}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:opacity-50:disabled{opacity:.5}.has-\\[\\>svg\\]\\:px-2\\.5:has(>svg){padding-inline:calc(var(--spacing)*2.5)}.has-\\[\\>svg\\]\\:px-3:has(>svg){padding-inline:calc(var(--spacing)*3)}.has-\\[\\>svg\\]\\:px-4:has(>svg){padding-inline:calc(var(--spacing)*4)}.aria-invalid\\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.dark\\:border-input:is(.dark *){border-color:var(--input)}.dark\\:bg-destructive\\/60:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\\:bg-destructive\\/60:is(.dark *){background-color:color-mix(in oklab,var(--destructive)60%,transparent)}}.dark\\:bg-input\\/30:is(.dark *){background-color:var(--input)}@supports (color:color-mix(in lab,red,red)){.dark\\:bg-input\\/30:is(.dark *){background-color:color-mix(in oklab,var(--input)30%,transparent)}}@media(hover:hover){.dark\\:hover\\:bg-accent\\/50:is(.dark *):hover{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.dark\\:hover\\:bg-accent\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--accent)50%,transparent)}}.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:var(--input)}@supports (color:color-mix(in lab,red,red)){.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--input)50%,transparent)}}}.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&_svg\\:not\\(\\[class\\*\\=\\'size-\\'\\]\\)\\]\\:size-4 svg:not([class*=size-]){width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}:root{--radius:.625rem;--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--border:oklch(92.2% 0 0);--input:oklch(92.2% 0 0);--ring:oklch(70.8% 0 0);--chart-1:oklch(64.6% .222 41.116);--chart-2:oklch(60% .118 184.704);--chart-3:oklch(39.8% .07 227.392);--chart-4:oklch(82.8% .189 84.429);--chart-5:oklch(76.9% .188 70.08);--sidebar:oklch(98.5% 0 0);--sidebar-foreground:oklch(14.5% 0 0);--sidebar-primary:oklch(20.5% 0 0);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(97% 0 0);--sidebar-accent-foreground:oklch(20.5% 0 0);--sidebar-border:oklch(92.2% 0 0);--sidebar-ring:oklch(70.8% 0 0)}.dark{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.6% 0 0);--chart-1:oklch(48.8% .243 264.376);--chart-2:oklch(69.6% .17 162.48);--chart-3:oklch(76.9% .188 70.08);--chart-4:oklch(62.7% .265 303.9);--chart-5:oklch(64.5% .246 16.439);--sidebar:oklch(20.5% 0 0);--sidebar-foreground:oklch(98.5% 0 0);--sidebar-primary:oklch(48.8% .243 264.376);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(26.9% 0 0);--sidebar-accent-foreground:oklch(98.5% 0 0);--sidebar-border:oklch(100% 0 0/.1);--sidebar-ring:oklch(55.6% 0 0)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}
|
|
2
|
-
/*$vite$:1*/`,document.head.appendChild(It);class Gt{constructor(r,t){u(this,lt);u(this,w);u(this,p);u(this,Y,{x:0,y:0,scale:1});u(this,et,r=>{r.evt.preventDefault();const e=a(this,p).getPointerPosition();if(e)if(r.evt.ctrlKey){const i=a(this,Y).scale,o={x:(e.x-a(this,Y).x)/i,y:(e.y-a(this,Y).y)/i},s=1.01,l=r.evt.deltaY>0?-1:1,c=Math.min(Math.abs(r.evt.deltaY),10);let g=i;for(let y=0;y<c;y++)g=l>0?g*s:g/s;const m=Math.max(.1,Math.min(5,g)),k={x:e.x-o.x*m,y:e.y-o.y*m};a(this,w).updateViewport({x:k.x,y:k.y,scale:m})}else{const i=r.evt.shiftKey?r.evt.deltaY:r.evt.deltaX,o=r.evt.shiftKey?0:r.evt.deltaY;a(this,w).updateViewport({x:a(this,Y).x-i,y:a(this,Y).y-o})}});u(this,rt,r=>{const t=a(this,w).getState().toolType;if(r.evt.button!==0||t==="hand")return;const e=r.target===a(this,p),i=a(this,p).getRelativePointerPosition();if(t==="select"&&!e){const o=r.target.id();o&&a(this,w).selectNode(o,r.evt.shiftKey);return}if(t==="rectangle"&&i&&a(this,w).createDraftNode(t,i),t==="image-marker"&&i){const o=a(this,w).findImageAtPosition(i);if(console.log(o,"imageShape"),o){const s=o.width(),l=o.height();if(s&&l){const c={x:o.x(),y:o.y(),width:s,height:l};a(this,w).createDraftNode(t,i,{parent:o.id(),bounds:c,startPosition:i})}}}a(this,w).selectNode()});u(this,it,()=>{const r=a(this,w).getState().toolType;if(r==="hand")return;const t=a(this,p).getRelativePointerPosition();(r==="rectangle"||r==="image-marker")&&t&&a(this,w).updateDraftNode(t)});u(this,ot,()=>{const r=a(this,w).getState().toolType;r!=="hand"&&(r==="rectangle"||r==="image-marker")&&a(this,w).finalizeDraftNode()});u(this,at,r=>{if(r.target!==a(this,p))return;const t=a(this,w).getState().toolType;t==="hand"?this.setCursor("grabbing"):t==="select"&&this.setCursor("all-scroll")});u(this,st,r=>{r.target===a(this,p)&&a(this,w).updateViewport({x:a(this,p).x(),y:a(this,p).y()})});u(this,nt,r=>{r.target===a(this,p)&&(a(this,w).updateViewport({x:a(this,p).x(),y:a(this,p).y()}),this.resetCursor())});N(this,w,r),N(this,p,new C.Stage({container:t.container,width:t.width,height:t.height,x:0,y:0,scaleX:1,scaleY:1,draggable:t.draggable??!1,className:t.className})),_(this,lt,Ut).call(this)}getStage(){return a(this,p)}getViewport(){return{...a(this,Y)}}setViewport(r){const t={...a(this,Y),...r};N(this,Y,t),r.x!==void 0&&a(this,p).x(r.x),r.y!==void 0&&a(this,p).y(r.y),r.scale!==void 0&&(a(this,p).scaleX(r.scale),a(this,p).scaleY(r.scale)),r.width!==void 0&&a(this,p).width(r.width),r.height!==void 0&&a(this,p).height(r.height)}setDraggable(r){a(this,p).draggable(r)}setCursor(r){const t=a(this,p).container();t.style.cursor=r}resetCursor(){const r=a(this,p).container();if(a(this,w).getState().toolType==="hand"){r.style.cursor="grab";return}r.style.cursor="default"}destroy(){a(this,p).destroy()}}w=new WeakMap,p=new WeakMap,Y=new WeakMap,et=new WeakMap,rt=new WeakMap,it=new WeakMap,ot=new WeakMap,at=new WeakMap,st=new WeakMap,nt=new WeakMap,lt=new WeakSet,Ut=function(){a(this,p).on("wheel",a(this,et)),a(this,p).on("pointerdown",a(this,rt)),a(this,p).on("pointermove",a(this,it)),a(this,p).on("pointerup",a(this,ot)),a(this,p).on("dragstart",a(this,at)),a(this,p).on("dragmove",a(this,st)),a(this,p).on("dragend",a(this,nt))};class Bt{constructor(r,t){u(this,mt);u(this,B);u(this,x);u(this,ct,()=>{this.emitPositionChange()});u(this,ht,()=>{console.log("transforming..."),this.emitPositionChange()});u(this,dt,()=>{this.emitPositionChange()});u(this,gt,()=>{this.emitPositionChange()});u(this,pt,()=>{this.emitPositionChange()});u(this,ut,()=>{this.emitPositionChange()});N(this,B,r),N(this,x,new C.Transformer({rotateEnabled:t?.rotateEnabled??!0,ignoreStroke:t?.ignoreStroke??!0,anchorSize:t?.anchorSize??8,borderDash:t?.borderDash??[4,4],anchorCornerRadius:t?.anchorCornerRadius??4,padding:t?.padding??6})),_(this,mt,Vt).call(this)}getTransformer(){return a(this,x)}getPosition(){if(a(this,x).nodes().length===0)return null;const t=a(this,x).getClientRect();return{x:t.x,y:t.y,width:t.width,height:t.height,rotation:a(this,x).rotation()}}setNodes(r){if(r.length===0){this.clearNodes();return}a(this,x).nodes(r),a(this,x).moveToTop(),this.emitPositionChange()}getNodes(){return a(this,x).nodes()}clearNodes(){a(this,x).nodes([]),a(this,x).moveToBottom(),this.emitPositionChange()}emitPositionChange(){const r=this.getPosition();a(this,B).emitEvent("transformer:positionChange",r)}destroy(){a(this,x).destroy()}}B=new WeakMap,x=new WeakMap,ct=new WeakMap,ht=new WeakMap,dt=new WeakMap,gt=new WeakMap,pt=new WeakMap,ut=new WeakMap,mt=new WeakSet,Vt=function(){a(this,x).on("transformstart",a(this,ct)),a(this,x).on("transform",a(this,ht)),a(this,x).on("transformend",a(this,dt)),a(this,x).on("dragstart",a(this,gt)),a(this,x).on("dragmove",a(this,pt)),a(this,x).on("dragend",a(this,ut))};class Jt{constructor(r){V(this,"_past",[]);V(this,"_present");V(this,"_future",[]);V(this,"_emitter");this._present=r,this._emitter=Ft()}getState(){return{...this._present}}getHistory(){return{past:[...this._past],present:{...this._present},future:[...this._future]}}canUndo(){return this._past.length>0}canRedo(){return this._future.length>0}on(r,t){this._emitter.on(r,t)}off(r,t){this._emitter.off(r,t)}emit(r,t){this._emitter.emit(r,t)}undo(){if(this._past.length===0)return;const r=this._past[this._past.length-1],t=this._past.slice(0,this._past.length-1);this._past=t,this._future=[this._present,...this._future],this._present=r,this._syncState(r),this._emitter.emit("state:undo",r),this._emitter.emit("state:change",r)}redo(){if(this._future.length===0)return;const r=this._future[0],t=this._future.slice(1);this._past=[...this._past,this._present],this._future=t,this._present=r,this._syncState(r),this._emitter.emit("state:redo",r),this._emitter.emit("state:change",r)}resetHistory(){this._past=[],this._future=[],this._emitter.emit("state:reset",this._present),this._emitter.emit("state:change",this._present)}_updateState(r,t=!0){const e={...this._present,...r};t&&(this._past=[...this._past,this._present],this._future=[]),this._present=e,this._emitter.emit("state:change",e)}_syncState(r){}_dispose(){this._emitter.all.clear()}}const q="shapeNameForSelect",v={CORNER_RADIUS:6,MIN_SIZE:10},W={MIN_SIZE:10},Et={MIN_SIZE:10};function Qt(n,r,t){return 2*(r+n-t*(4-Math.PI))}function Kt(n,r,t){let e=1,i=0,o=0;switch(t){case"dashed":i=Math.min(r*2,n/4);break;case"dotted":e=8,i=r/e;break;default:return[]}let s=Math.floor(n/i/(2*e));return s=Math.max(s,3),i=n/s/(2*e),o=(n-s*i)/s,[i,o]}function te(n){switch(n){case"small":return 2;case"medium":return 3;case"large":return 5;case"extra-large":return 8;default:return 3}}function ee(n){return Array.isArray(n)&&n.length>1?n[0]+n[1]:0}function Ct(n){return{width:Math.max(Et.MIN_SIZE,n.width()*n.scaleX()),height:Math.max(Et.MIN_SIZE,n.height()*n.scaleY())}}class vt{constructor(r,t){V(this,"core");V(this,"node");V(this,"element");V(this,"toolTypeChangeHandler");this.core=r,this.node=t,this.element=this.createElement(),this.toolTypeChangeHandler=e=>{const i=e==="select";this.element.listening(i)},this.toolTypeChangeHandler(this.core.getToolType()),this.core.on("toolType:change",this.toolTypeChangeHandler)}getElement(){return this.element}getNode(){return this.node}destroy(){this.core.off("toolType:change",this.toolTypeChangeHandler),this.element.destroy()}}function re(n,r){if(!r||r===0)return null;const t=new C.Animation(e=>{if(!e)return;const i=-e.time/10%r;n.dashOffset(i)},n.getLayer());return{start:()=>t.start(),stop:()=>t.stop(),isRunning:()=>t.isRunning()}}class ie extends vt{constructor(t,e){super(t,e);u(this,X);u(this,I,null);e.style.animated&&_(this,X,kt).call(this),_(this,X,Lt).call(this,this.getElement())}createElement(){const t=Math.max(this.node.props.width??v.MIN_SIZE,v.MIN_SIZE),e=Math.max(this.node.props.height??v.MIN_SIZE,v.MIN_SIZE),i={id:this.node.id,...this.node.props,...this.node.style,width:t,height:e,cornerRadius:v.CORNER_RADIUS,name:q,draggable:!0,stroke:"black",strokeWidth:2},o=new C.Rect(i);return o.setAttrs({width:t,height:e}),o}getElement(){return this.element}updateNode(t){this.node={...this.node,...t,props:{...this.node.props,...t.props},style:{...this.node.style,...t.style}};const e=this.getElement();e.x(this.node.props.x),e.y(this.node.props.y);const i=Math.max(this.node.props.width??v.MIN_SIZE,v.MIN_SIZE),o=Math.max(this.node.props.height??v.MIN_SIZE,v.MIN_SIZE);e.width(i),e.height(o),this.node.style.animated&&!a(this,I)?_(this,X,kt).call(this):!this.node.style.animated&&a(this,I)&&_(this,X,St).call(this)}destroy(){_(this,X,St).call(this),super.destroy()}}I=new WeakMap,X=new WeakSet,kt=function(){const t=this.getElement(),e=t.dash();if(!e||e.length===0)return;const i=ee(e);N(this,I,re(t,i)),a(this,I)&&a(this,I).start()},St=function(){a(this,I)&&(a(this,I).stop(),N(this,I,null))},Lt=function(t=void 0){const e=t??this.getElement();e.on("transformstart",()=>{this.node.style.animated&&a(this,I)&&a(this,I).stop()}),e.on("transform",i=>{const o=i.target,{width:s,height:l}=Ct(o),c=Qt(s,l,v.CORNER_RADIUS),g=Kt(c,te(this.node.style.size),this.node.style.line);o.scale({x:1,y:1}),o.width(s),o.height(l),o.dash(g.map(m=>m*this.core.getStageScale()))}),e.on("transformend",i=>{const o=i.target,{width:s,height:l}=Ct(o),c={...this.node.props,x:o.x(),y:o.y(),width:s,height:l,rotation:o.rotation()};this.node.props=c,this.core._syncNodeFromElement(this.node.id,{props:c}),this.node.style.animated&&a(this,I)?.isRunning()===!1&&a(this,I).start()}),e.on("dragend",i=>{const o=i.target,s={...this.node.props,x:o.x(),y:o.y()};this.node.props=s,this.core._syncNodeFromElement(this.node.id,{props:s})})};class oe extends vt{constructor(t,e){super(t,e);u(this,z);_(this,z,Nt).call(this),_(this,z,Ot).call(this,this.getElement())}createElement(){const t=document.createElement("canvas");return t.width=1,t.height=1,new C.Image({id:this.node.id,x:this.node.props.x,y:this.node.props.y,name:q,draggable:!0,image:t})}getElement(){return this.element}updateNode(t){this.node={...this.node,...t,props:{...this.node.props,...t.props},style:{...this.node.style,...t.style},meta:{...this.node.meta,...t.meta}};const e=this.getElement();if(e.x(this.node.props.x),e.y(this.node.props.y),this.node.props.width&&this.node.props.height){const i=Math.max(this.node.props.width,W.MIN_SIZE),o=Math.max(this.node.props.height,W.MIN_SIZE);e.width(i),e.height(o)}this.node.props.rotation!==void 0&&e.rotation(this.node.props.rotation),t.meta?.imageUrl&&t.meta.imageUrl!==this.node.meta.imageUrl&&_(this,z,Nt).call(this)}destroy(){super.destroy()}}z=new WeakSet,Nt=function(){const t=this.node.meta.imageUrl;if(!t){console.warn("Image URL is missing");return}const e=new window.Image;e.crossOrigin="anonymous",e.src=t,e.onload=()=>{this.getElement().image(e);const i=this.node.props.width??e.width,o=this.node.props.height??e.height;this.getElement().width(Math.max(i,W.MIN_SIZE)),this.getElement().height(Math.max(o,W.MIN_SIZE))},e.onerror=()=>{console.error("Failed to load image:",t)}},Ot=function(t){t.on("transform",e=>{const i=e.target,o=Math.max(W.MIN_SIZE,i.width()*i.scaleX()),s=Math.max(W.MIN_SIZE,i.height()*i.scaleY());i.scale({x:1,y:1}),i.width(o),i.height(s),_(this,z,Mt).call(this)}),t.on("transformend",e=>{const i=e.target,o={...this.node.props,x:i.x(),y:i.y(),width:i.width(),height:i.height(),rotation:i.rotation()};this.node.props=o,this.core._syncNodeFromElement(this.node.id,{props:o}),_(this,z,_t).call(this)}),t.on("dragmove",()=>{_(this,z,Mt).call(this)}),t.on("dragend",e=>{const i=e.target,o={...this.node.props,x:i.x(),y:i.y()};this.node.props=o,this.core._syncNodeFromElement(this.node.id,{props:o}),_(this,z,_t).call(this)})},Mt=function(){const t=this.getElement(),e=t.getLayer();if(!e)return;const i=t.x(),o=t.y(),s=t.width(),l=t.height(),c=e.find(m=>m.hasName(this.node.id)),g=this.core.getState().nodes||[];c.forEach(m=>{const k=g.find(y=>y.id===m.id());if(k?.type==="image-marker"&&k.meta.relativePosition){const{start:y,end:M}=k.meta.relativePosition,E=i+y.percentX/100*s,T=o+y.percentY/100*l,U=i+M.percentX/100*s,D=o+M.percentY/100*l,wt=Math.min(E,U),F=Math.min(T,D),O=Math.abs(U-E),K=Math.abs(D-T);m.position({x:wt,y:F}),m.setAttrs({width:O,height:K}),m.getChildren().forEach(A=>{A.getClassName()==="Rect"?A.setAttrs({width:O,height:K}):A.getClassName()==="Group"&&A.setAttrs({x:O,y:K})})}})},_t=function(){const e=this.getElement().getLayer();if(!e)return;e.find(o=>o.hasName(this.node.id)).forEach(o=>{this.core._syncNodeFromElement(o.id(),{props:{x:o.x(),y:o.y(),width:o.width(),height:o.height()}})})};class ae extends vt{constructor(t,e){super(t,e);u(this,ft);u(this,L);u(this,P);u(this,J);u(this,Q);const i=this.getElement();N(this,L,i.findOne(".rect")),N(this,P,i.findOne(".marker-group")),N(this,J,a(this,P).findOne("Circle")),N(this,Q,a(this,P).findOne("Text")),_(this,ft,Ht).call(this)}createElement(){const t=Math.max(this.node.props.width??v.MIN_SIZE,v.MIN_SIZE),e=Math.max(this.node.props.height??v.MIN_SIZE,v.MIN_SIZE),i=new C.Group({id:this.node.id,name:`static ${this.node.meta.parent}`,x:this.node.props.x,y:this.node.props.y,width:t,height:e}),o=new C.Rect({name:"rect",x:0,y:0,width:t,height:e,stroke:this.node.style.color,strokeWidth:2,dash:[5,5],fill:"transparent",cornerRadius:v.CORNER_RADIUS}),s=new C.Group({name:"marker-group",x:t,y:e}),c=16/this.core.getStageScale(),g=new C.Circle({radius:c,fill:"red",stroke:"black",strokeWidth:2}),m=new C.Text({x:-c,y:-c,width:c*2,height:c*2,text:String(this.node.meta.markerNumber||""),align:"center",verticalAlign:"middle",fontSize:16,fill:"white"});return s.add(g),s.add(m),i.add(o),i.add(s),i}getElement(){return this.element}updateNode(t){this.node={...this.node,...t,props:{...this.node.props,...t.props},style:{...this.node.style,...t.style},meta:{...this.node.meta,...t.meta}};const e=this.getElement();e.x(this.node.props.x),e.y(this.node.props.y);const i=Math.max(this.node.props.width??v.MIN_SIZE,v.MIN_SIZE),o=Math.max(this.node.props.height??v.MIN_SIZE,v.MIN_SIZE);e.width(i),e.height(o),a(this,L).width(i),a(this,L).height(o),a(this,P).x(i),a(this,P).y(o),t.style?.color&&a(this,L).stroke(t.style.color),t.meta?.markerNumber!==void 0&&a(this,Q).text(String(t.meta.markerNumber))}destroy(){super.destroy()}setFocusState(t){const e=t?3:2,i=t?1.2:1;a(this,L).strokeWidth(e),a(this,J).strokeWidth(e),a(this,P).scaleX(i),a(this,P).scaleY(i)}}L=new WeakMap,P=new WeakMap,J=new WeakMap,Q=new WeakMap,ft=new WeakSet,Ht=function(){a(this,P).on("pointerover",()=>{this.setFocusState(!0),this.core.setCursor("pointer")}),a(this,P).on("pointerout",()=>{const e=(this.core.getState().selectedNodeIds||[]).includes(this.node.id);this.setFocusState(e),this.core.resetCursor()}),a(this,P).on("pointerdown",()=>{this.core.selectNode(this.node.id)})};function Tt(n,r,t){switch(r){case"rectangle":return new ie(n,t);case"image":return new oe(n,t);case"image-marker":return new ae(n,t);default:return null}}const se=(n,r,t,e)=>{const i={type:n,id:$.v4(),text:null,style:{opacity:1,line:"solid",color:"black",size:"medium",animated:!1},props:{x:r.x,y:r.y,rotation:0,visible:!0},meta:e??{}};return n==="image-marker"?{...i,style:{...i.style,color:"#ff0000",line:"dashed"}}:i};function ne(n,r,t){let e=r;n.type==="image-marker"&&t&&(e={x:Math.max(t.x,Math.min(t.x+t.width,r.x)),y:Math.max(t.y,Math.min(t.y+t.height,r.y))});const[i,o]=le({x:n.props.x,y:n.props.y},e);return n.type==="rectangle"||n.type==="image-marker"?{...n,props:{...n.props,x:i.x,y:i.y,width:Math.max(o.x-i.x,v.MIN_SIZE),height:Math.max(o.y-i.y,v.MIN_SIZE)}}:n}function le(n,r){let t=n.x,e=n.y,i=r.x,o=r.y,s;return t>i&&(s=Math.abs(t-i),t=i,i=t+s),e>o&&(s=Math.abs(e-o),e=o,o=e+s),[{x:t,y:e},{x:i,y:o}]}class ce extends Jt{constructor(t){super({viewport:{x:0,y:0,width:t.clientWidth,height:t.clientHeight,scale:1},toolType:"select",nodes:[]});u(this,b);u(this,Z);u(this,R);u(this,S,null);N(this,b,new Gt(this,{container:t,width:t.clientWidth,height:t.clientHeight,draggable:!1,className:"touch-none"})),N(this,Z,new C.Layer),N(this,R,new Bt(this)),a(this,b).getStage().add(a(this,Z)),a(this,Z).add(a(this,R).getTransformer()),this.updateViewport(this.getState().viewport,!1)}getCanvasStage(){return a(this,b)}getCanvasTransformer(){return a(this,R)}emitEvent(t,e){this.emit(t,e)}getStage(){return a(this,b).getStage()}getContainer(){return a(this,b).getStage().container()}getMainLayer(){return a(this,Z)}getToolType(){return this.getState().toolType}setToolType(t){this.selectNode(),this._updateState({toolType:t},!1),this.emit("toolType:change",t),t==="hand"?(a(this,b).setDraggable(!0),a(this,b).setCursor("grab")):(a(this,b).setDraggable(!1),a(this,b).resetCursor())}setDraggable(t){a(this,b).setDraggable(t)}setCursor(t){a(this,b).setCursor(t)}resetCursor(){a(this,b).resetCursor()}getStageScale(){return a(this,b).getStage().scaleX()}updateViewport(t,e=!1){a(this,b).setViewport(t);const i={...this.getState().viewport,...t};this._updateState({viewport:i},e),this.emit("viewport:change",i),a(this,R).emitPositionChange()}createNodes(t){t.map(o=>Tt(this,o.type,o)).filter(o=>o!==null).forEach(o=>{a(this,Z).add(o.getElement())});const i=[...this.getState().nodes||[],...t];this._updateState({nodes:i},!0)}createImageMarkerNode(t,e,i,o){const s=this.getState().nodes||[];let l=0;s.forEach(D=>{D.type==="image-marker"&&D.meta.parent===t&&typeof D.meta.markerNumber=="number"&&(l=Math.max(l,D.meta.markerNumber))});const c=(e.x-o.x)/o.width*100,g=(e.y-o.y)/o.height*100,m=(i.x-o.x)/o.width*100,k=(i.y-o.y)/o.height*100,y=Math.min(e.x,i.x),M=Math.min(e.y,i.y),E=Math.abs(i.x-e.x),T=Math.abs(i.y-e.y),U={id:$.v4(),type:"image-marker",props:{x:y,y:M,width:E,height:T,rotation:0,visible:!0},style:{color:"#ff0000",line:"dashed",size:"medium",opacity:1},meta:{parent:t,markerNumber:l+1,relativePosition:{start:{percentX:Math.max(0,Math.min(100,c)),percentY:Math.max(0,Math.min(100,g))},end:{percentX:Math.max(0,Math.min(100,m)),percentY:Math.max(0,Math.min(100,k))}}}};this.createNodes([U])}findImageAtPosition(t){const e=a(this,b).getStage(),i=e.find(s=>s.getClassName()==="Image"),o=i.map(s=>s.listening());i.forEach(s=>s.listening(!0));try{const l=e.getAllIntersections(t).filter(c=>c.getClassName()==="Image");return l.length===0?null:l[l.length-1]}finally{i.forEach((s,l)=>{s.listening(o[l])})}}createDraftNode(t,e,i){a(this,S)&&a(this,S).destroy();const o=se(t,e,void 0,i);N(this,S,Tt(this,t,o)),console.log(a(this,S)),a(this,S)&&a(this,Z).add(a(this,S).getElement())}updateDraftNode(t,e){if(!a(this,S))return;const i=a(this,S).getNode(),o=ne(i,t,e);a(this,S).updateNode(o)}finalizeDraftNode(){if(!a(this,S))return;const t=$.v4(),e=a(this,S).getNode();if(e.type==="image-marker"&&e.meta.parent){const o=e.meta.bounds,s=e.meta.startPosition,l={x:e.props.x+(e.props.width||0),y:e.props.y+(e.props.height||0)},c=this.getState().nodes||[];let g=0;c.forEach(T=>{T.type==="image-marker"&&T.meta.parent===e.meta.parent&&typeof T.meta.markerNumber=="number"&&(g=Math.max(g,T.meta.markerNumber))});const m=(s.x-o.x)/o.width*100,k=(s.y-o.y)/o.height*100,y=(l.x-o.x)/o.width*100,M=(l.y-o.y)/o.height*100,E={...e,props:{...e.props},style:{...e.style},meta:{parent:e.meta.parent,markerNumber:g+1,relativePosition:{start:{percentX:Math.max(0,Math.min(100,m)),percentY:Math.max(0,Math.min(100,k))},end:{percentX:Math.max(0,Math.min(100,y)),percentY:Math.max(0,Math.min(100,M))}}},id:t,type:"image-marker"};this.createNodes([E]),a(this,S).destroy(),N(this,S,null),this.setToolType("select");return}const i={...e,props:{...e.props},style:{...e.style},meta:{...e.meta},id:t};this.createNodes([i]),a(this,S).destroy(),N(this,S,null),this.setToolType("select")}selectNode(t,e=!1){const i=this.getState().selectedNodeIds??[];if(i.length===0&&!t)return;if(!t){a(this,R).clearNodes(),this._updateState({selectedNodeIds:[]},!1);return}let o=[];e?o=i.length?[...i,t]:[t]:o=[t];const s=this.getStage().find(`.${q}`).filter(l=>{const c=l.id();return o.includes(c)});a(this,R).setNodes(s),this._updateState({selectedNodeIds:o},!1)}dispose(){this.getCanvasTransformer().destroy(),this.getCanvasStage().destroy(),this._dispose()}_syncNodeFromElement(t,e){const i=this.getState().nodes||[],o=i.findIndex(c=>c.id===t);if(o===-1)return;const s={...i[o],...e,props:{...i[o].props,...e.props},style:{...i[o].style,...e.style},meta:{...i[o].meta,...e.meta}},l=[...i];l[o]=s,this._updateState({nodes:l},!0)}_syncState(t){a(this,b).setViewport({x:t.viewport.x,y:t.viewport.y,scale:t.viewport.scale,width:t.viewport.width,height:t.viewport.height})}}b=new WeakMap,Z=new WeakMap,R=new WeakMap,S=new WeakMap;class zt extends ce{getAvailableTools(){return["select","hand","rectangle","image-marker"]}setToolType(r){super.setToolType(r)}createNodes(r){super.createNodes(r)}updateViewport(r,t=!1){super.updateViewport(r,t)}createImageNode(r,t){const e=t??{x:100,y:100},i={id:$.v4(),type:"image",props:{x:e.x,y:e.y,width:void 0,height:void 0,rotation:0,visible:!0},style:{color:"#000000",line:"solid",size:"medium",opacity:1},meta:{imageUrl:r}};this.createNodes([i])}insertImageAtBottomLeft(r,t){const e=this.getState().nodes||[];let i={x:0,y:0};if(e.length>0){const s=this.getMainLayer();let l=1/0,c=-1/0;s.children.forEach(g=>{if(g.visible()&&g.getClassName()!=="Transformer"&&g.hasName(q)){const m=g.getAttrs(),k=m.x||0,y=m.y||0,M=m.height||0;l=Math.min(l,k),c=Math.max(c,y+M)}}),l!==1/0&&c!==-1/0&&(i={x:l,y:c+20})}else{const s=this.getState().viewport;i={x:(s.width/2-s.x)/s.scale,y:(s.height/2-s.y)/s.scale}}const o={id:$.v4(),type:"image",props:{x:i.x,y:i.y,width:t?.width,height:t?.height,rotation:0,visible:!0},style:{color:"#000000",line:"solid",size:"medium",opacity:1},meta:{imageUrl:r}};this.createNodes([o]),requestAnimationFrame(()=>{this.scrollToContent({scale:!0})})}exportAsImage(r){const t=this.getStage(),e=this.getCanvasTransformer().getTransformer(),i=e.visible();e.visible(!1);try{return t.toDataURL({pixelRatio:r?.pixelRatio??2,mimeType:r?.mimeType??"image/png",quality:r?.quality??1})}finally{e.visible(i)}}exportSelectionAsImage(r){const t=this.getCanvasTransformer().getPosition();if(!t)return console.warn("No selection to export"),null;const e=this.getStage(),i=r?.padding??10,o=this.getCanvasTransformer().getTransformer(),s=o.visible();o.visible(!1);try{return e.toDataURL({x:t.x-i,y:t.y-i,width:t.width+i*2,height:t.height+i*2,pixelRatio:r?.pixelRatio??2,mimeType:r?.mimeType??"image/png",quality:r?.quality??1})}finally{o.visible(s)}}deleteSelectedNodes(){const r=this.getState().selectedNodeIds||[];r.length!==0&&this.deleteNodes(r)}deleteNodes(r){if(r.length===0)return;const t=this.getState().nodes||[],e=new Set(r);r.forEach(o=>{t.find(l=>l.id===o)?.type==="image"&&t.forEach(l=>{l.type==="image-marker"&&l.meta.parent===o&&e.add(l.id)})}),e.forEach(o=>{const s=this.getStage().findOne(`#${o}`);s&&s.destroy()});const i=t.filter(o=>!e.has(o.id));this.getCanvasTransformer().clearNodes(),this._updateState({nodes:i,selectedNodeIds:[]},!0)}scrollToContent(r){if((this.getState().nodes||[]).length===0)return;const e=r?.padding??50,i=r?.scale===!0,o=r?.nodeIds;let s=1/0,l=1/0,c=-1/0,g=-1/0;const m=this.getMainLayer(),k=this.getState().selectedNodeIds||[],y=o&&o.length>0,M=!y&&k.length>0,E=y?o:M?k:null;if(m.children.forEach(A=>{if(A.visible()&&A.getClassName()!=="Transformer"&&A.hasName(q)){if(E){const H=A.id();if(!E.includes(H))return}const j=A.getAttrs(),Yt=j.x||0,Dt=j.y||0,ye=j.width||0,ve=j.height||0;if(j.rotation||0){const H=A.getClientRect({skipTransform:!1}),xt=this.getStage(),yt=xt.scaleX(),Xt=xt.x(),Zt=xt.y(),we=(H.x-Xt)/yt,xe=(H.y-Zt)/yt,be=(H.x+H.width-Xt)/yt,ke=(H.y+H.height-Zt)/yt;s=Math.min(s,we),l=Math.min(l,xe),c=Math.max(c,be),g=Math.max(g,ke)}else s=Math.min(s,Yt),l=Math.min(l,Dt),c=Math.max(c,Yt+ye),g=Math.max(g,Dt+ve)}}),s===1/0||l===1/0)return;const T=c-s,U=g-l,D=s+T/2,wt=l+U/2,F=this.getState().viewport;let O=F.scale;if(i){const A=(F.width-e*2)/T,j=(F.height-e*2)/U;O=Math.min(A,j,1)}const K=F.width/2-D*O,At=F.height/2-wt*O;this.updateViewport({x:K,y:At,scale:O},!0)}}function he(n,r,t,e=!1){const[i,o]=r,[s,l]=t,c=s+(n-i)/(o-i)*(l-s);return e?s<l?Math.max(Math.min(c,l),s):Math.max(Math.min(c,s),l):c}const Pt=[{min:-1,mid:.15,step:64},{min:.05,mid:.375,step:16},{min:.15,mid:1,step:4},{min:.7,mid:2.5,step:1}];function de({viewportX:n,viewportY:r,scale:t,size:e=20,showGrid:i=!0}){const o=n/t,s=r/t,l=t;return i?h.jsxs("svg",{className:"canvas-grid w-full h-full absolute top-0 left-0",version:"1.1",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[h.jsx("defs",{children:Pt.map(({min:c,mid:g,step:m},k)=>{const y=m*e*l,M=.5+o*l,E=.5+s*l,T=M>0?M%y:y+M%y,U=E>0?E%y:y+E%y,D=l<g?he(l,[c,g],[0,1]):1;return h.jsx("pattern",{id:`grid_${m}`,width:y,height:y,patternUnits:"userSpaceOnUse",children:h.jsx("circle",{className:"tl-grid-dot",cx:T,cy:U,r:1,opacity:D})},k)})}),Pt.map(({step:c},g)=>h.jsx("rect",{width:"100%",height:"100%",fill:`url(#grid_${c})`},g))]}):null}function ge(...n){return $t.twMerge(Wt.clsx(n))}const pe=qt.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",{variants:{variant:{default:"bg-primary text-primary-foreground hover:bg-primary/90",destructive:"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",outline:"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2 has-[>svg]:px-3",sm:"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",lg:"h-10 rounded-md px-6 has-[>svg]:px-4",icon:"size-9","icon-sm":"size-8","icon-lg":"size-10"}},defaultVariants:{variant:"default",size:"default"}});function G({className:n,variant:r="default",size:t="default",asChild:e=!1,...i}){const o=e?jt.Slot:"button";return h.jsx(o,{"data-slot":"button","data-variant":r,"data-size":t,className:ge(pe({variant:r,size:t,className:n})),...i})}function ue({api:n}){const[r,t]=f.useState(n.getState().viewport);f.useEffect(()=>{n.on("viewport:change",c=>{t(c)})},[t,n]);const e=c=>{const g=r.width/2,m=r.height/2,k=(g-r.x)/r.scale,y=(m-r.y)/r.scale,M=g-k*c,E=m-y*c;n.updateViewport({x:M,y:E,scale:c})},i=()=>{const c=Math.min(r.scale*1.2,5);e(c)},o=()=>{const c=Math.max(r.scale/1.2,.1);e(c)},s=()=>{e(1)},l=Math.round(r.scale*100);return h.jsxs("div",{className:"zoom-panel flex items-center gap-2",children:[h.jsx(G,{size:"sm",variant:"secondary",onClick:o,title:"缩小",children:h.jsx(tt.Minus,{})}),h.jsxs(G,{size:"sm",variant:"secondary",onClick:s,title:`${l}%`,className:"min-w-16",children:[l,"%"]}),h.jsx(G,{size:"sm",variant:"secondary",onClick:i,title:"放大",children:h.jsx(tt.Plus,{})})]})}function me({api:n}){const[r,t]=f.useState(n.canUndo()),[e,i]=f.useState(n.canRedo());return f.useEffect(()=>{const o=()=>{t(n.canUndo()),i(n.canRedo())};return n.on("state:change",o),()=>{n.off("state:change",o)}},[n]),h.jsxs("div",{className:"history-panel flex items-center gap-2",children:[h.jsx(G,{size:"sm",variant:"secondary",disabled:!r,onClick:()=>n.undo(),title:"撤销",children:h.jsx(tt.Undo2,{})}),h.jsx(G,{size:"sm",variant:"secondary",disabled:!e,onClick:()=>n.redo(),title:"重做",children:h.jsx(tt.Redo2,{})})]})}function fe({setApi:n}){const r=f.useRef(null),[t,e]=f.useState(null),[i,o]=f.useState({x:0,y:0,scale:1});return f.useEffect(()=>{if(!r.current)return;const s=new zt(r.current);return e(s),n?.(s),s.on("viewport:change",l=>{o(l)}),s.on("transformer:positionChange",l=>{console.log("Transformer position changed:",l)}),()=>{s.dispose()}},[n]),h.jsxs("div",{className:"pure-canvas relative size-full",children:[h.jsx(de,{viewportX:i.x,viewportY:i.y,scale:i.scale}),h.jsx("div",{ref:r,className:"size-full"}),t&&h.jsxs(h.Fragment,{children:[h.jsx("div",{className:"history-panel-wrapper absolute bottom-4 left-4 z-10",children:h.jsx(me,{api:t})}),h.jsx("div",{className:"zoom-panel-wrapper absolute bottom-4 right-4 z-10",children:h.jsx(ue,{api:t})})]})]})}d.CanvasApi=zt,d.NODE_NAME_FOR_SELECT=q,d.PureCanvas=fe,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})}));
|
|
1
|
+
(function(d,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("react/jsx-runtime"),require("react"),require("konva"),require("mitt"),require("uuid"),require("@radix-ui/react-slot"),require("class-variance-authority"),require("clsx"),require("tailwind-merge"),require("lucide-react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","konva","mitt","uuid","@radix-ui/react-slot","class-variance-authority","clsx","tailwind-merge","lucide-react"],c):(d=typeof globalThis<"u"?globalThis:d||self,c(d.konvaWhiteboard={},d.jsxRuntime,d.React,d.Konva,d.mitt,d.uuid,d.ReactSlot,d.ClassVarianceAuthority,d.clsx,d.tailwindMerge,d.LucideReact))})(this,(function(d,c,m,I,jt,K,Ft,qt,Wt,$t,tt){"use strict";var Se=Object.defineProperty;var Rt=d=>{throw TypeError(d)};var Ne=(d,c,m)=>c in d?Se(d,c,{enumerable:!0,configurable:!0,writable:!0,value:m}):d[c]=m;var V=(d,c,m)=>Ne(d,typeof c!="symbol"?c+"":c,m),bt=(d,c,m)=>c.has(d)||Rt("Cannot "+m);var a=(d,c,m)=>(bt(d,c,"read from private field"),m?m.call(d):c.get(d)),p=(d,c,m)=>c.has(d)?Rt("Cannot add the same private member more than once"):c instanceof WeakSet?c.add(d):c.set(d,m),S=(d,c,m,I)=>(bt(d,c,"write to private field"),I?I.call(d,m):c.set(d,m),m),M=(d,c,m)=>(bt(d,c,"access private method"),m);var w,g,Y,et,rt,it,ot,at,st,nt,lt,Ut,G,x,ct,ht,dt,gt,pt,ut,mt,Vt,_,Z,kt,St,Lt,z,Nt,Ot,Mt,_t,L,P,B,J,ft,Ht,b,A,R,k;var Et=document.createElement("style");Et.textContent=`@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-cyan-500:oklch(71.5% .143 215.221);--color-cyan-600:oklch(60.9% .126 221.723);--color-cyan-700:oklch(52% .105 223.128);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-purple-500:oklch(62.7% .265 303.9);--color-purple-600:oklch(55.8% .288 302.321);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-medium:500;--font-weight-bold:700;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){*{outline-color:color-mix(in oklab,var(--ring)50%,transparent)}}body{background-color:var(--background);color:var(--foreground)}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.static{position:static}.top-0{top:calc(var(--spacing)*0)}.top-4{top:calc(var(--spacing)*4)}.right-4{right:calc(var(--spacing)*4)}.bottom-4{bottom:calc(var(--spacing)*4)}.left-0{left:calc(var(--spacing)*0)}.left-4{left:calc(var(--spacing)*4)}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.size-8{width:calc(var(--spacing)*8);height:calc(var(--spacing)*8)}.size-9{width:calc(var(--spacing)*9);height:calc(var(--spacing)*9)}.size-10{width:calc(var(--spacing)*10);height:calc(var(--spacing)*10)}.size-full{width:100%;height:100%}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-\\[500px\\]{height:500px}.h-full{height:100%}.max-h-40{max-height:calc(var(--spacing)*40)}.w-\\[700px\\]{width:700px}.w-full{width:100%}.max-w-xs{max-width:var(--container-xs)}.min-w-16{min-width:calc(var(--spacing)*16)}.shrink-0{flex-shrink:0}.-translate-x-1\\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.touch-none{touch-action:none}.resize{resize:both}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.gap-1\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.overflow-auto{overflow:auto}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.bg-background{background-color:var(--background)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-cyan-500{background-color:var(--color-cyan-500)}.bg-cyan-600{background-color:var(--color-cyan-600)}.bg-destructive{background-color:var(--destructive)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-green-500{background-color:var(--color-green-500)}.bg-indigo-500{background-color:var(--color-indigo-500)}.bg-primary{background-color:var(--primary)}.bg-purple-500{background-color:var(--color-purple-500)}.bg-red-500{background-color:var(--color-red-500)}.bg-secondary{background-color:var(--secondary)}.bg-white{background-color:var(--color-white)}.p-2{padding:calc(var(--spacing)*2)}.p-4{padding:calc(var(--spacing)*4)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-2{padding-block:calc(var(--spacing)*2)}.pt-4{padding-top:calc(var(--spacing)*4)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-gray-400{color:var(--color-gray-400)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-white{color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}@media(hover:hover){.hover\\:bg-accent:hover{background-color:var(--accent)}.hover\\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\\:bg-cyan-600:hover{background-color:var(--color-cyan-600)}.hover\\:bg-cyan-700:hover{background-color:var(--color-cyan-700)}.hover\\:bg-destructive\\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.hover\\:bg-destructive\\/90:hover{background-color:color-mix(in oklab,var(--destructive)90%,transparent)}}.hover\\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\\:bg-green-600:hover{background-color:var(--color-green-600)}.hover\\:bg-indigo-600:hover{background-color:var(--color-indigo-600)}.hover\\:bg-primary\\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab,red,red)){.hover\\:bg-primary\\/90:hover{background-color:color-mix(in oklab,var(--primary)90%,transparent)}}.hover\\:bg-purple-600:hover{background-color:var(--color-purple-600)}.hover\\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\\:bg-secondary\\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab,red,red)){.hover\\:bg-secondary\\/80:hover{background-color:color-mix(in oklab,var(--secondary)80%,transparent)}}.hover\\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\\:underline:hover{text-decoration-line:underline}}.focus-visible\\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\\:ring-\\[3px\\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(3px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab,red,red)){.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:color-mix(in oklab,var(--ring)50%,transparent)}}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:opacity-50:disabled{opacity:.5}.has-\\[\\>svg\\]\\:px-2\\.5:has(>svg){padding-inline:calc(var(--spacing)*2.5)}.has-\\[\\>svg\\]\\:px-3:has(>svg){padding-inline:calc(var(--spacing)*3)}.has-\\[\\>svg\\]\\:px-4:has(>svg){padding-inline:calc(var(--spacing)*4)}.aria-invalid\\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.dark\\:border-input:is(.dark *){border-color:var(--input)}.dark\\:bg-destructive\\/60:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\\:bg-destructive\\/60:is(.dark *){background-color:color-mix(in oklab,var(--destructive)60%,transparent)}}.dark\\:bg-input\\/30:is(.dark *){background-color:var(--input)}@supports (color:color-mix(in lab,red,red)){.dark\\:bg-input\\/30:is(.dark *){background-color:color-mix(in oklab,var(--input)30%,transparent)}}@media(hover:hover){.dark\\:hover\\:bg-accent\\/50:is(.dark *):hover{background-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.dark\\:hover\\:bg-accent\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--accent)50%,transparent)}}.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:var(--input)}@supports (color:color-mix(in lab,red,red)){.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--input)50%,transparent)}}}.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab,red,red)){.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&_svg\\:not\\(\\[class\\*\\=\\'size-\\'\\]\\)\\]\\:size-4 svg:not([class*=size-]){width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}:root{--radius:.625rem;--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--border:oklch(92.2% 0 0);--input:oklch(92.2% 0 0);--ring:oklch(70.8% 0 0);--chart-1:oklch(64.6% .222 41.116);--chart-2:oklch(60% .118 184.704);--chart-3:oklch(39.8% .07 227.392);--chart-4:oklch(82.8% .189 84.429);--chart-5:oklch(76.9% .188 70.08);--sidebar:oklch(98.5% 0 0);--sidebar-foreground:oklch(14.5% 0 0);--sidebar-primary:oklch(20.5% 0 0);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(97% 0 0);--sidebar-accent-foreground:oklch(20.5% 0 0);--sidebar-border:oklch(92.2% 0 0);--sidebar-ring:oklch(70.8% 0 0)}.dark{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.6% 0 0);--chart-1:oklch(48.8% .243 264.376);--chart-2:oklch(69.6% .17 162.48);--chart-3:oklch(76.9% .188 70.08);--chart-4:oklch(62.7% .265 303.9);--chart-5:oklch(64.5% .246 16.439);--sidebar:oklch(20.5% 0 0);--sidebar-foreground:oklch(98.5% 0 0);--sidebar-primary:oklch(48.8% .243 264.376);--sidebar-primary-foreground:oklch(98.5% 0 0);--sidebar-accent:oklch(26.9% 0 0);--sidebar-accent-foreground:oklch(98.5% 0 0);--sidebar-border:oklch(100% 0 0/.1);--sidebar-ring:oklch(55.6% 0 0)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}
|
|
2
|
+
/*$vite$:1*/`,document.head.appendChild(Et);class Gt{constructor(r,t){p(this,lt);p(this,w);p(this,g);p(this,Y,{x:0,y:0,scale:1});p(this,et,r=>{r.evt.preventDefault();const e=a(this,g).getPointerPosition();if(e)if(r.evt.ctrlKey){const i=a(this,Y).scale,o={x:(e.x-a(this,Y).x)/i,y:(e.y-a(this,Y).y)/i},s=1.01,l=r.evt.deltaY>0?-1:1,h=Math.min(Math.abs(r.evt.deltaY),10);let u=i;for(let y=0;y<h;y++)u=l>0?u*s:u/s;const f=Math.max(.1,Math.min(5,u)),N={x:e.x-o.x*f,y:e.y-o.y*f};a(this,w).updateViewport({x:N.x,y:N.y,scale:f})}else{const i=r.evt.shiftKey?r.evt.deltaY:r.evt.deltaX,o=r.evt.shiftKey?0:r.evt.deltaY;a(this,w).updateViewport({x:a(this,Y).x-i,y:a(this,Y).y-o})}});p(this,rt,r=>{const t=a(this,w).getState().toolType;if(r.evt.button!==0||t==="hand")return;const e=r.target===a(this,g),i=a(this,g).getRelativePointerPosition();if(t==="select"&&!e){const o=r.target.id();o&&a(this,w).selectNode(o,r.evt.shiftKey);return}if(t==="rectangle"&&i&&a(this,w).createDraftNode(t,i),t==="image-marker"&&i){const o=a(this,w).findImageAtPosition(i);if(console.log(o,"imageShape"),o){const s=o.width(),l=o.height();if(s&&l){const h={x:o.x(),y:o.y(),width:s,height:l};a(this,w).createDraftNode(t,i,{parent:o.id(),bounds:h,startPosition:i})}}}a(this,w).selectNode()});p(this,it,()=>{const r=a(this,w).getState().toolType;if(r==="hand")return;const t=a(this,g).getRelativePointerPosition();(r==="rectangle"||r==="image-marker")&&t&&a(this,w).updateDraftNode(t)});p(this,ot,()=>{const r=a(this,w).getState().toolType;r!=="hand"&&(r==="rectangle"||r==="image-marker")&&a(this,w).finalizeDraftNode()});p(this,at,r=>{if(r.target!==a(this,g))return;const t=a(this,w).getState().toolType;t==="hand"?this.setCursor("grabbing"):t==="select"&&this.setCursor("all-scroll")});p(this,st,r=>{r.target===a(this,g)&&a(this,w).updateViewport({x:a(this,g).x(),y:a(this,g).y()})});p(this,nt,r=>{r.target===a(this,g)&&(a(this,w).updateViewport({x:a(this,g).x(),y:a(this,g).y()}),this.resetCursor())});S(this,w,r),S(this,g,new I.Stage({container:t.container,width:t.width,height:t.height,x:0,y:0,scaleX:1,scaleY:1,draggable:t.draggable??!1,className:t.className})),M(this,lt,Ut).call(this)}getStage(){return a(this,g)}getViewport(){return{...a(this,Y)}}setViewport(r){const t={...a(this,Y),...r};S(this,Y,t),r.x!==void 0&&a(this,g).x(r.x),r.y!==void 0&&a(this,g).y(r.y),r.scale!==void 0&&(a(this,g).scaleX(r.scale),a(this,g).scaleY(r.scale)),r.width!==void 0&&a(this,g).width(r.width),r.height!==void 0&&a(this,g).height(r.height)}setDraggable(r){a(this,g).draggable(r)}setCursor(r){const t=a(this,g).container();t.style.cursor=r}resetCursor(){const r=a(this,g).container();if(a(this,w).getState().toolType==="hand"){r.style.cursor="grab";return}r.style.cursor="default"}destroy(){a(this,g).destroy()}}w=new WeakMap,g=new WeakMap,Y=new WeakMap,et=new WeakMap,rt=new WeakMap,it=new WeakMap,ot=new WeakMap,at=new WeakMap,st=new WeakMap,nt=new WeakMap,lt=new WeakSet,Ut=function(){a(this,g).on("wheel",a(this,et)),a(this,g).on("pointerdown",a(this,rt)),a(this,g).on("pointermove",a(this,it)),a(this,g).on("pointerup",a(this,ot)),a(this,g).on("dragstart",a(this,at)),a(this,g).on("dragmove",a(this,st)),a(this,g).on("dragend",a(this,nt))};class Bt{constructor(r,t){p(this,mt);p(this,G);p(this,x);p(this,ct,()=>{this.emitPositionChange()});p(this,ht,()=>{console.log("transforming..."),this.emitPositionChange()});p(this,dt,()=>{this.emitPositionChange()});p(this,gt,()=>{this.emitPositionChange()});p(this,pt,()=>{this.emitPositionChange()});p(this,ut,()=>{this.emitPositionChange()});S(this,G,r),S(this,x,new I.Transformer({rotateEnabled:t?.rotateEnabled??!0,ignoreStroke:t?.ignoreStroke??!0,anchorSize:t?.anchorSize??8,borderDash:t?.borderDash??[4,4],anchorCornerRadius:t?.anchorCornerRadius??4,padding:t?.padding??6})),M(this,mt,Vt).call(this)}getTransformer(){return a(this,x)}getPosition(){if(a(this,x).nodes().length===0)return null;const t=a(this,x).getClientRect();return{x:t.x,y:t.y,width:t.width,height:t.height,rotation:a(this,x).rotation()}}setNodes(r){if(r.length===0){this.clearNodes();return}a(this,x).nodes(r),a(this,x).moveToTop(),this.emitPositionChange()}getNodes(){return a(this,x).nodes()}clearNodes(){a(this,x).nodes([]),a(this,x).moveToBottom(),this.emitPositionChange()}emitPositionChange(){const r=this.getPosition();a(this,G).emitEvent("transformer:positionChange",r)}destroy(){a(this,x).destroy()}}G=new WeakMap,x=new WeakMap,ct=new WeakMap,ht=new WeakMap,dt=new WeakMap,gt=new WeakMap,pt=new WeakMap,ut=new WeakMap,mt=new WeakSet,Vt=function(){a(this,x).on("transformstart",a(this,ct)),a(this,x).on("transform",a(this,ht)),a(this,x).on("transformend",a(this,dt)),a(this,x).on("dragstart",a(this,gt)),a(this,x).on("dragmove",a(this,pt)),a(this,x).on("dragend",a(this,ut))};class Jt{constructor(r){V(this,"_past",[]);V(this,"_present");V(this,"_future",[]);V(this,"_emitter");this._present=r,this._emitter=jt()}getState(){return{...this._present}}getHistory(){return{past:[...this._past],present:{...this._present},future:[...this._future]}}canUndo(){return this._past.length>0}canRedo(){return this._future.length>0}on(r,t){this._emitter.on(r,t)}off(r,t){this._emitter.off(r,t)}emit(r,t){this._emitter.emit(r,t)}undo(){if(this._past.length===0)return;const r=this._past[this._past.length-1],t=this._past.slice(0,this._past.length-1);this._past=t,this._future=[this._present,...this._future],this._present=r,this._syncState(r),this._emitter.emit("state:undo",r),this._emitter.emit("state:change",r)}redo(){if(this._future.length===0)return;const r=this._future[0],t=this._future.slice(1);this._past=[...this._past,this._present],this._future=t,this._present=r,this._syncState(r),this._emitter.emit("state:redo",r),this._emitter.emit("state:change",r)}resetHistory(){this._past=[],this._future=[],this._emitter.emit("state:reset",this._present),this._emitter.emit("state:change",this._present)}_updateState(r,t=!0){const e={...this._present,...r};t&&(this._past=[...this._past,this._present],this._future=[]),this._present=e,this._emitter.emit("state:change",e)}_syncState(r){}_dispose(){this._emitter.all.clear()}}const W="shapeNameForSelect",v={CORNER_RADIUS:6,MIN_SIZE:10},q={MIN_SIZE:10},It={MIN_SIZE:10};function Qt(n,r,t){return 2*(r+n-t*(4-Math.PI))}function Kt(n,r,t){let e=1,i=0,o=0;switch(t){case"dashed":i=Math.min(r*2,n/4);break;case"dotted":e=8,i=r/e;break;default:return[]}let s=Math.floor(n/i/(2*e));return s=Math.max(s,3),i=n/s/(2*e),o=(n-s*i)/s,[i,o]}function te(n){switch(n){case"small":return 2;case"medium":return 3;case"large":return 5;case"extra-large":return 8;default:return 3}}function ee(n){return Array.isArray(n)&&n.length>1?n[0]+n[1]:0}function Ct(n){return{width:Math.max(It.MIN_SIZE,n.width()*n.scaleX()),height:Math.max(It.MIN_SIZE,n.height()*n.scaleY())}}class vt{constructor(r,t){V(this,"core");V(this,"node");V(this,"element");V(this,"toolTypeChangeHandler");this.core=r,this.node=t,this.element=this.createElement(),this.toolTypeChangeHandler=e=>{const i=e==="select";this.element.listening(i)},this.toolTypeChangeHandler(this.core.getToolType()),this.core.on("toolType:change",this.toolTypeChangeHandler)}getElement(){return this.element}getNode(){return this.node}destroy(){this.core.off("toolType:change",this.toolTypeChangeHandler),this.element.destroy()}}function re(n,r){if(!r||r===0)return null;const t=new I.Animation(e=>{if(!e)return;const i=-e.time/10%r;n.dashOffset(i)},n.getLayer());return{start:()=>t.start(),stop:()=>t.stop(),isRunning:()=>t.isRunning()}}class ie extends vt{constructor(t,e){super(t,e);p(this,Z);p(this,_,null);e.style.animated&&M(this,Z,kt).call(this),M(this,Z,Lt).call(this,this.getElement())}createElement(){const t=Math.max(this.node.props.width??v.MIN_SIZE,v.MIN_SIZE),e=Math.max(this.node.props.height??v.MIN_SIZE,v.MIN_SIZE),i={id:this.node.id,...this.node.props,...this.node.style,width:t,height:e,cornerRadius:v.CORNER_RADIUS,name:W,draggable:!0,stroke:"black",strokeWidth:2},o=new I.Rect(i);return o.setAttrs({width:t,height:e}),o}getElement(){return this.element}updateNode(t){this.node={...this.node,...t,props:{...this.node.props,...t.props},style:{...this.node.style,...t.style}};const e=this.getElement();e.x(this.node.props.x),e.y(this.node.props.y);const i=Math.max(this.node.props.width??v.MIN_SIZE,v.MIN_SIZE),o=Math.max(this.node.props.height??v.MIN_SIZE,v.MIN_SIZE);e.width(i),e.height(o),this.node.style.animated&&!a(this,_)?M(this,Z,kt).call(this):!this.node.style.animated&&a(this,_)&&M(this,Z,St).call(this)}destroy(){M(this,Z,St).call(this),super.destroy()}}_=new WeakMap,Z=new WeakSet,kt=function(){const t=this.getElement(),e=t.dash();if(!e||e.length===0)return;const i=ee(e);S(this,_,re(t,i)),a(this,_)&&a(this,_).start()},St=function(){a(this,_)&&(a(this,_).stop(),S(this,_,null))},Lt=function(t=void 0){const e=t??this.getElement();e.on("transformstart",()=>{this.node.style.animated&&a(this,_)&&a(this,_).stop()}),e.on("transform",i=>{const o=i.target,{width:s,height:l}=Ct(o),h=Qt(s,l,v.CORNER_RADIUS),u=Kt(h,te(this.node.style.size),this.node.style.line);o.scale({x:1,y:1}),o.width(s),o.height(l),o.dash(u.map(f=>f*this.core.getStageScale()))}),e.on("transformend",i=>{const o=i.target,{width:s,height:l}=Ct(o),h={...this.node.props,x:o.x(),y:o.y(),width:s,height:l,rotation:o.rotation()};this.node.props=h,this.core._syncNodeFromElement(this.node.id,{props:h}),this.node.style.animated&&a(this,_)?.isRunning()===!1&&a(this,_).start()}),e.on("dragend",i=>{const o=i.target,s={...this.node.props,x:o.x(),y:o.y()};this.node.props=s,this.core._syncNodeFromElement(this.node.id,{props:s})})};class oe extends vt{constructor(t,e){super(t,e);p(this,z);M(this,z,Nt).call(this),M(this,z,Ot).call(this,this.getElement())}createElement(){const t=document.createElement("canvas");return t.width=1,t.height=1,new I.Image({id:this.node.id,x:this.node.props.x,y:this.node.props.y,name:W,draggable:!0,image:t})}getElement(){return this.element}updateNode(t){this.node={...this.node,...t,props:{...this.node.props,...t.props},style:{...this.node.style,...t.style},meta:{...this.node.meta,...t.meta}};const e=this.getElement();if(e.x(this.node.props.x),e.y(this.node.props.y),this.node.props.width&&this.node.props.height){const i=Math.max(this.node.props.width,q.MIN_SIZE),o=Math.max(this.node.props.height,q.MIN_SIZE);e.width(i),e.height(o)}this.node.props.rotation!==void 0&&e.rotation(this.node.props.rotation),t.meta?.imageUrl&&t.meta.imageUrl!==this.node.meta.imageUrl&&M(this,z,Nt).call(this)}destroy(){super.destroy()}}z=new WeakSet,Nt=function(){const t=this.node.meta.imageUrl;if(!t){console.warn("Image URL is missing");return}const e=new window.Image;e.crossOrigin="anonymous",e.src=t,e.onload=()=>{this.getElement().image(e);const i=this.node.props.width??e.width,o=this.node.props.height??e.height;this.getElement().width(Math.max(i,q.MIN_SIZE)),this.getElement().height(Math.max(o,q.MIN_SIZE))},e.onerror=()=>{console.error("Failed to load image:",t)}},Ot=function(t){t.on("transform",e=>{const i=e.target,o=Math.max(q.MIN_SIZE,i.width()*i.scaleX()),s=Math.max(q.MIN_SIZE,i.height()*i.scaleY());i.scale({x:1,y:1}),i.width(o),i.height(s),M(this,z,Mt).call(this)}),t.on("transformend",e=>{const i=e.target,o={...this.node.props,x:i.x(),y:i.y(),width:i.width(),height:i.height(),rotation:i.rotation()};this.node.props=o,this.core._syncNodeFromElement(this.node.id,{props:o}),M(this,z,_t).call(this)}),t.on("dragmove",()=>{M(this,z,Mt).call(this)}),t.on("dragend",e=>{const i=e.target,o={...this.node.props,x:i.x(),y:i.y()};this.node.props=o,this.core._syncNodeFromElement(this.node.id,{props:o}),M(this,z,_t).call(this)})},Mt=function(){const t=this.getElement(),e=t.getLayer();if(!e)return;const i=t.x(),o=t.y(),s=t.width(),l=t.height(),h=e.find(f=>f.hasName(this.node.id)),u=this.core.getState().nodes||[];h.forEach(f=>{const N=u.find(y=>y.id===f.id());if(N?.type==="image-marker"&&N.meta.relativePosition){const{start:y,end:C}=N.meta.relativePosition,E=i+y.percentX/100*s,T=o+y.percentY/100*l,U=i+C.percentX/100*s,X=o+C.percentY/100*l,wt=Math.min(E,U),j=Math.min(T,X),O=Math.abs(U-E),Q=Math.abs(X-T);f.position({x:wt,y:j}),f.setAttrs({width:O,height:Q}),f.getChildren().forEach(D=>{D.getClassName()==="Rect"?D.setAttrs({width:O,height:Q}):D.getClassName()==="Group"&&D.setAttrs({x:O,y:Q})})}})},_t=function(){const e=this.getElement().getLayer();if(!e)return;e.find(o=>o.hasName(this.node.id)).forEach(o=>{this.core._syncNodeFromElement(o.id(),{props:{x:o.x(),y:o.y(),width:o.width(),height:o.height()}})})};class ae extends vt{constructor(t,e){super(t,e);p(this,ft);p(this,L);p(this,P);p(this,B);p(this,J);const i=this.getElement();S(this,L,i.findOne(".rect")),S(this,P,i.findOne(".marker-group")),S(this,B,a(this,P).findOne("Circle")),S(this,J,a(this,P).findOne("Text")),M(this,ft,Ht).call(this)}createElement(){const t=Math.max(this.node.props.width??v.MIN_SIZE,v.MIN_SIZE),e=Math.max(this.node.props.height??v.MIN_SIZE,v.MIN_SIZE),i=new I.Group({id:this.node.id,name:`static ${this.node.meta.parent}`,x:this.node.props.x,y:this.node.props.y,width:t,height:e}),o=new I.Rect({name:"rect",x:0,y:0,width:t,height:e,stroke:this.node.style.color,strokeWidth:2,dash:[5,5],fill:"transparent",cornerRadius:v.CORNER_RADIUS}),s=new I.Group({name:"marker-group",x:t,y:e}),h=16/this.core.getStageScale(),u=new I.Circle({radius:h,fill:"red",stroke:"black",strokeWidth:2}),f=new I.Text({x:-h,y:-h,width:h*2,height:h*2,text:String(this.node.meta.markerNumber||""),align:"center",verticalAlign:"middle",fontSize:16,fill:"white"});return s.add(u),s.add(f),i.add(o),i.add(s),i}getElement(){return this.element}updateNode(t){this.node={...this.node,...t,props:{...this.node.props,...t.props},style:{...this.node.style,...t.style},meta:{...this.node.meta,...t.meta}};const e=this.getElement();e.x(this.node.props.x),e.y(this.node.props.y);const i=Math.max(this.node.props.width??v.MIN_SIZE,v.MIN_SIZE),o=Math.max(this.node.props.height??v.MIN_SIZE,v.MIN_SIZE);e.width(i),e.height(o),a(this,L).width(i),a(this,L).height(o),a(this,P).x(i),a(this,P).y(o),t.style?.color&&a(this,L).stroke(t.style.color),t.meta?.markerNumber!==void 0&&a(this,J).text(String(t.meta.markerNumber))}destroy(){super.destroy()}setFocusState(t){const e=t?3:2,i=t?1.2:1;a(this,L).strokeWidth(e),a(this,B).strokeWidth(e),a(this,P).scaleX(i),a(this,P).scaleY(i)}}L=new WeakMap,P=new WeakMap,B=new WeakMap,J=new WeakMap,ft=new WeakSet,Ht=function(){a(this,P).on("pointerover",()=>{this.setFocusState(!0),this.core.setCursor("pointer")}),a(this,P).on("pointerout",()=>{const e=(this.core.getState().selectedNodeIds||[]).includes(this.node.id);this.setFocusState(e),this.core.resetCursor()}),a(this,P).on("pointerdown",()=>{this.core.selectNode(this.node.id)})};function Tt(n,r,t){switch(r){case"rectangle":return new ie(n,t);case"image":return new oe(n,t);case"image-marker":return new ae(n,t);default:return null}}const se=(n,r,t,e)=>{const i={type:n,id:K.v4(),text:null,style:{opacity:1,line:"solid",color:"black",size:"medium",animated:!1},props:{x:r.x,y:r.y,rotation:0,visible:!0},meta:e??{}};return n==="image-marker"?{...i,style:{...i.style,color:"#ff0000",line:"dashed"}}:i};function ne(n,r,t){let e=r;n.type==="image-marker"&&t&&(e={x:Math.max(t.x,Math.min(t.x+t.width,r.x)),y:Math.max(t.y,Math.min(t.y+t.height,r.y))});const[i,o]=le({x:n.props.x,y:n.props.y},e);return n.type==="rectangle"||n.type==="image-marker"?{...n,props:{...n.props,x:i.x,y:i.y,width:Math.max(o.x-i.x,v.MIN_SIZE),height:Math.max(o.y-i.y,v.MIN_SIZE)}}:n}function le(n,r){let t=n.x,e=n.y,i=r.x,o=r.y,s;return t>i&&(s=Math.abs(t-i),t=i,i=t+s),e>o&&(s=Math.abs(e-o),e=o,o=e+s),[{x:t,y:e},{x:i,y:o}]}class ce extends Jt{constructor(t){super({viewport:{x:0,y:0,width:t.clientWidth,height:t.clientHeight,scale:1},toolType:"select",nodes:[]});p(this,b);p(this,A);p(this,R);p(this,k,null);S(this,b,new Gt(this,{container:t,width:t.clientWidth,height:t.clientHeight,draggable:!1,className:"touch-none"})),S(this,A,new I.Layer),S(this,R,new Bt(this)),a(this,b).getStage().add(a(this,A)),a(this,A).add(a(this,R).getTransformer()),this.updateViewport(this.getState().viewport,!1)}getCanvasStage(){return a(this,b)}getCanvasTransformer(){return a(this,R)}emitEvent(t,e){this.emit(t,e)}getStage(){return a(this,b).getStage()}getContainer(){return a(this,b).getStage().container()}getMainLayer(){return a(this,A)}getToolType(){return this.getState().toolType}setToolType(t){this.selectNode(),this._updateState({toolType:t},!1),this.emit("toolType:change",t),t==="hand"?(a(this,b).setDraggable(!0),a(this,b).setCursor("grab")):(a(this,b).setDraggable(!1),a(this,b).resetCursor())}setDraggable(t){a(this,b).setDraggable(t)}setCursor(t){a(this,b).setCursor(t)}resetCursor(){a(this,b).resetCursor()}getStageScale(){return a(this,b).getStage().scaleX()}updateViewport(t,e=!1){a(this,b).setViewport(t);const i={...this.getState().viewport,...t};this._updateState({viewport:i},e),this.emit("viewport:change",i),a(this,R).emitPositionChange()}createNodes(t){t.map(o=>Tt(this,o.type,o)).filter(o=>o!==null).forEach(o=>{a(this,A).add(o.getElement())});const i=[...this.getState().nodes||[],...t];this._updateState({nodes:i},!0)}createImageMarkerNode(t,e,i,o){const s=this.getState().nodes||[];let l=0;s.forEach(X=>{X.type==="image-marker"&&X.meta.parent===t&&typeof X.meta.markerNumber=="number"&&(l=Math.max(l,X.meta.markerNumber))});const h=(e.x-o.x)/o.width*100,u=(e.y-o.y)/o.height*100,f=(i.x-o.x)/o.width*100,N=(i.y-o.y)/o.height*100,y=Math.min(e.x,i.x),C=Math.min(e.y,i.y),E=Math.abs(i.x-e.x),T=Math.abs(i.y-e.y),U={id:K.v4(),type:"image-marker",props:{x:y,y:C,width:E,height:T,rotation:0,visible:!0},style:{color:"#ff0000",line:"dashed",size:"medium",opacity:1},meta:{parent:t,markerNumber:l+1,relativePosition:{start:{percentX:Math.max(0,Math.min(100,h)),percentY:Math.max(0,Math.min(100,u))},end:{percentX:Math.max(0,Math.min(100,f)),percentY:Math.max(0,Math.min(100,N))}}}};this.createNodes([U])}findImageAtPosition(t){const e=a(this,b).getStage(),i=e.find(s=>s.getClassName()==="Image"),o=i.map(s=>s.listening());i.forEach(s=>s.listening(!0));try{const l=e.getAllIntersections(t).filter(h=>h.getClassName()==="Image");return l.length===0?null:l[l.length-1]}finally{i.forEach((s,l)=>{s.listening(o[l])})}}createDraftNode(t,e,i){a(this,k)&&a(this,k).destroy();const o=se(t,e,void 0,i);S(this,k,Tt(this,t,o)),console.log(a(this,k)),a(this,k)&&a(this,A).add(a(this,k).getElement())}updateDraftNode(t,e){if(!a(this,k))return;const i=a(this,k).getNode(),o=ne(i,t,e);a(this,k).updateNode(o)}finalizeDraftNode(){if(!a(this,k))return;const t=K.v4(),e=a(this,k).getNode();if(e.type==="image-marker"&&e.meta.parent){const o=e.meta.bounds,s=e.meta.startPosition,l={x:e.props.x+(e.props.width||0),y:e.props.y+(e.props.height||0)},h=this.getState().nodes||[];let u=0;h.forEach(T=>{T.type==="image-marker"&&T.meta.parent===e.meta.parent&&typeof T.meta.markerNumber=="number"&&(u=Math.max(u,T.meta.markerNumber))});const f=(s.x-o.x)/o.width*100,N=(s.y-o.y)/o.height*100,y=(l.x-o.x)/o.width*100,C=(l.y-o.y)/o.height*100,E={...e,props:{...e.props},style:{...e.style},meta:{parent:e.meta.parent,markerNumber:u+1,relativePosition:{start:{percentX:Math.max(0,Math.min(100,f)),percentY:Math.max(0,Math.min(100,N))},end:{percentX:Math.max(0,Math.min(100,y)),percentY:Math.max(0,Math.min(100,C))}}},id:t,type:"image-marker"};this.createNodes([E]),a(this,k).destroy(),S(this,k,null),this.setToolType("select");return}const i={...e,props:{...e.props},style:{...e.style},meta:{...e.meta},id:t};this.createNodes([i]),a(this,k).destroy(),S(this,k,null),this.setToolType("select")}selectNode(t,e=!1){const i=this.getState().selectedNodeIds??[];if(i.length===0&&!t)return;if(!t){a(this,R).clearNodes(),this._updateState({selectedNodeIds:[]},!1);return}let o=[];e?o=i.length?[...i,t]:[t]:o=[t];const s=this.getStage().find(`.${W}`).filter(l=>{const h=l.id();return o.includes(h)});a(this,R).setNodes(s),this._updateState({selectedNodeIds:o},!1)}dispose(){this.getCanvasTransformer().destroy(),this.getMainLayer().destroy(),this.getCanvasStage().destroy(),this._dispose()}_syncNodeFromElement(t,e){const i=this.getState().nodes||[],o=i.findIndex(h=>h.id===t);if(o===-1)return;const s={...i[o],...e,props:{...i[o].props,...e.props},style:{...i[o].style,...e.style},meta:{...i[o].meta,...e.meta}},l=[...i];l[o]=s,this._updateState({nodes:l},!0)}_syncState(t){a(this,b).setViewport({x:t.viewport.x,y:t.viewport.y,scale:t.viewport.scale,width:t.viewport.width,height:t.viewport.height})}}b=new WeakMap,A=new WeakMap,R=new WeakMap,k=new WeakMap;class zt extends ce{getAvailableTools(){return["select","hand","rectangle","image-marker"]}setToolType(r){super.setToolType(r)}createNodes(r){super.createNodes(r)}updateViewport(r,t=!1){super.updateViewport(r,t)}createImageNode(r,t){const e=t??{x:100,y:100},i={id:K.v4(),type:"image",props:{x:e.x,y:e.y,width:void 0,height:void 0,rotation:0,visible:!0},style:{color:"#000000",line:"solid",size:"medium",opacity:1},meta:{imageUrl:r}};this.createNodes([i])}exportAsImage(r){const t=this.getStage(),e=this.getCanvasTransformer().getTransformer(),i=e.visible();e.visible(!1);try{return t.toDataURL({pixelRatio:r?.pixelRatio??2,mimeType:r?.mimeType??"image/png",quality:r?.quality??1})}finally{e.visible(i)}}exportSelectionAsImage(r){const t=this.getCanvasTransformer().getPosition();if(!t)return console.warn("No selection to export"),null;const e=this.getStage(),i=r?.padding??0,o=this.getCanvasTransformer().getTransformer(),s=o.visible();o.visible(!1);try{return e.toDataURL({x:t.x-i,y:t.y-i,width:t.width+i*2,height:t.height+i*2,pixelRatio:r?.pixelRatio??1,mimeType:r?.mimeType??"image/png",quality:r?.quality??1})}finally{o.visible(s)}}deleteSelectedNodes(){const r=this.getState().selectedNodeIds||[];r.length!==0&&this.deleteNodes(r)}deleteNodes(r){if(r.length===0)return;const t=this.getState().nodes||[],e=new Set(r);r.forEach(o=>{t.find(l=>l.id===o)?.type==="image"&&t.forEach(l=>{l.type==="image-marker"&&l.meta.parent===o&&e.add(l.id)})}),e.forEach(o=>{const s=this.getStage().findOne(`#${o}`);s&&s.destroy()});const i=t.filter(o=>!e.has(o.id));this.getCanvasTransformer().clearNodes(),this._updateState({nodes:i,selectedNodeIds:[]},!0)}scrollToContent(r){if((this.getState().nodes||[]).length===0)return;const e=r?.padding??50,i=r?.scale===!0,o=r?.nodeIds;let s=1/0,l=1/0,h=-1/0,u=-1/0;const f=this.getMainLayer(),N=this.getState().selectedNodeIds||[],y=o&&o.length>0,C=!y&&N.length>0,E=y?o:C?N:null;if(f.children.forEach(D=>{if(D.visible()&&D.getClassName()!=="Transformer"&&D.hasName(W)){if(E){const H=D.id();if(!E.includes(H))return}const F=D.getAttrs(),Yt=F.x||0,Xt=F.y||0,ye=F.width||0,ve=F.height||0;if(F.rotation||0){const H=D.getClientRect({skipTransform:!1}),xt=this.getStage(),yt=xt.scaleX(),Zt=xt.x(),At=xt.y(),we=(H.x-Zt)/yt,xe=(H.y-At)/yt,be=(H.x+H.width-Zt)/yt,ke=(H.y+H.height-At)/yt;s=Math.min(s,we),l=Math.min(l,xe),h=Math.max(h,be),u=Math.max(u,ke)}else s=Math.min(s,Yt),l=Math.min(l,Xt),h=Math.max(h,Yt+ye),u=Math.max(u,Xt+ve)}}),s===1/0||l===1/0)return;const T=h-s,U=u-l,X=s+T/2,wt=l+U/2,j=this.getState().viewport;let O=j.scale;if(i){const D=(j.width-e*2)/T,F=(j.height-e*2)/U;O=Math.min(D,F,1)}const Q=j.width/2-X*O,Dt=j.height/2-wt*O;this.updateViewport({x:Q,y:Dt,scale:O},!0)}}function he(n,r,t,e=!1){const[i,o]=r,[s,l]=t,h=s+(n-i)/(o-i)*(l-s);return e?s<l?Math.max(Math.min(h,l),s):Math.max(Math.min(h,s),l):h}const Pt=[{min:-1,mid:.15,step:64},{min:.05,mid:.375,step:16},{min:.15,mid:1,step:4},{min:.7,mid:2.5,step:1}];function de({viewportX:n,viewportY:r,scale:t,size:e=20,showGrid:i=!0}){const o=n/t,s=r/t,l=t;return i?c.jsxs("svg",{className:"canvas-grid w-full h-full absolute top-0 left-0",version:"1.1",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[c.jsx("defs",{children:Pt.map(({min:h,mid:u,step:f},N)=>{const y=f*e*l,C=.5+o*l,E=.5+s*l,T=C>0?C%y:y+C%y,U=E>0?E%y:y+E%y,X=l<u?he(l,[h,u],[0,1]):1;return c.jsx("pattern",{id:`grid_${f}`,width:y,height:y,patternUnits:"userSpaceOnUse",children:c.jsx("circle",{className:"tl-grid-dot",cx:T,cy:U,r:1,opacity:X})},N)})}),Pt.map(({step:h},u)=>c.jsx("rect",{width:"100%",height:"100%",fill:`url(#grid_${h})`},u))]}):null}function ge(...n){return $t.twMerge(Wt.clsx(n))}const pe=qt.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",{variants:{variant:{default:"bg-primary text-primary-foreground hover:bg-primary/90",destructive:"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",outline:"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2 has-[>svg]:px-3",sm:"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",lg:"h-10 rounded-md px-6 has-[>svg]:px-4",icon:"size-9","icon-sm":"size-8","icon-lg":"size-10"}},defaultVariants:{variant:"default",size:"default"}});function $({className:n,variant:r="default",size:t="default",asChild:e=!1,...i}){const o=e?Ft.Slot:"button";return c.jsx(o,{"data-slot":"button","data-variant":r,"data-size":t,className:ge(pe({variant:r,size:t,className:n})),...i})}function ue({api:n}){const[r,t]=m.useState(n.getState().viewport);m.useEffect(()=>{n.on("viewport:change",h=>{t(h)})},[t,n]);const e=h=>{const u=r.width/2,f=r.height/2,N=(u-r.x)/r.scale,y=(f-r.y)/r.scale,C=u-N*h,E=f-y*h;n.updateViewport({x:C,y:E,scale:h})},i=()=>{const h=Math.min(r.scale*1.2,5);e(h)},o=()=>{const h=Math.max(r.scale/1.2,.1);e(h)},s=()=>{e(1)},l=Math.round(r.scale*100);return c.jsxs("div",{className:"zoom-panel flex items-center gap-2",children:[c.jsx($,{size:"sm",variant:"secondary",onClick:o,title:"缩小",children:c.jsx(tt.Minus,{})}),c.jsxs($,{size:"sm",variant:"secondary",onClick:s,title:`${l}%`,className:"min-w-16",children:[l,"%"]}),c.jsx($,{size:"sm",variant:"secondary",onClick:i,title:"放大",children:c.jsx(tt.Plus,{})})]})}function me({api:n}){const[r,t]=m.useState(n.canUndo()),[e,i]=m.useState(n.canRedo());return m.useEffect(()=>{const o=()=>{t(n.canUndo()),i(n.canRedo())};return n.on("state:change",o),()=>{n.off("state:change",o)}},[n]),c.jsxs("div",{className:"history-panel flex items-center gap-2",children:[c.jsx($,{size:"sm",variant:"secondary",disabled:!r,onClick:()=>n.undo(),title:"撤销",children:c.jsx(tt.Undo2,{})}),c.jsx($,{size:"sm",variant:"secondary",disabled:!e,onClick:()=>n.redo(),title:"重做",children:c.jsx(tt.Redo2,{})})]})}function fe({setApi:n}){const r=m.useRef(null),[t,e]=m.useState(null),[i,o]=m.useState({x:0,y:0,scale:1});return m.useEffect(()=>{if(!r.current)return;const s=new zt(r.current);return e(s),n?.(s),s.on("viewport:change",l=>{o(l)}),s.on("transformer:positionChange",l=>{console.log("Transformer position changed:",l)}),()=>{s.dispose()}},[n]),c.jsxs("div",{className:"pure-canvas relative size-full",children:[c.jsx(de,{viewportX:i.x,viewportY:i.y,scale:i.scale}),c.jsx("div",{ref:r,className:"size-full"}),t&&c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"history-panel-wrapper absolute bottom-4 left-4 z-10",children:c.jsx(me,{api:t})}),c.jsx("div",{className:"zoom-panel-wrapper absolute bottom-4 right-4 z-10",children:c.jsx(ue,{api:t})})]})]})}d.CanvasApi=zt,d.NODE_NAME_FOR_SELECT=W,d.PureCanvas=fe,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})}));
|
|
3
|
+
//# sourceMappingURL=index.umd.js.map
|