@coderyo/drawings 1.0.2 → 1.1.0
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 +2 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
package/dist/index.d.ts
CHANGED
|
@@ -76,6 +76,8 @@ declare class DrawingManager {
|
|
|
76
76
|
setTool(tool: DrawingTool): void;
|
|
77
77
|
getSelectedId(): string | null;
|
|
78
78
|
deleteSelected(): boolean;
|
|
79
|
+
/** Remove every drawing for the current symbol/interval. */
|
|
80
|
+
clearAll(): number;
|
|
79
81
|
deselect(): void;
|
|
80
82
|
getSelected(): DrawingRecord | null;
|
|
81
83
|
copySelected(): DrawingRecord | null;
|
package/dist/index.js
CHANGED
|
@@ -110,6 +110,20 @@ var DrawingManager = class {
|
|
|
110
110
|
this.emitSelection();
|
|
111
111
|
return true;
|
|
112
112
|
}
|
|
113
|
+
/** Remove every drawing for the current symbol/interval. */
|
|
114
|
+
clearAll() {
|
|
115
|
+
const count = this.drawings.length;
|
|
116
|
+
if (count === 0 && !this.draft) return 0;
|
|
117
|
+
this.drawings = [];
|
|
118
|
+
this.draft = null;
|
|
119
|
+
this.selectedId = null;
|
|
120
|
+
this.drag = null;
|
|
121
|
+
this.labelDragIndex = null;
|
|
122
|
+
this.persist();
|
|
123
|
+
this.redraw();
|
|
124
|
+
this.emitSelection();
|
|
125
|
+
return count;
|
|
126
|
+
}
|
|
113
127
|
deselect() {
|
|
114
128
|
this.selectedId = null;
|
|
115
129
|
this.drag = null;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/storage.ts","../src/drawing-style.ts","../src/drawing-manager.ts"],"sourcesContent":["const STORAGE_VERSION = 1;\n\nexport interface DrawingRecord {\n id: string;\n type: string;\n symbol: string;\n interval: string;\n points: Array<{ t: number; price: number }>;\n meta?: Record<string, unknown>;\n}\n\nexport interface DrawingStore {\n version: number;\n drawings: DrawingRecord[];\n}\n\nexport function storageKey(chartId: string, symbol: string, interval: string): string {\n return `tradview:drawings:v${STORAGE_VERSION}:${chartId}:${symbol}:${interval}`;\n}\n\nexport function loadDrawings(key: string): DrawingStore {\n try {\n const raw = localStorage.getItem(key);\n if (!raw) return { version: STORAGE_VERSION, drawings: [] };\n const parsed = JSON.parse(raw) as DrawingStore;\n if (parsed.version !== STORAGE_VERSION) return { version: STORAGE_VERSION, drawings: [] };\n return parsed;\n } catch {\n return { version: STORAGE_VERSION, drawings: [] };\n }\n}\n\nexport function saveDrawings(key: string, store: DrawingStore): void {\n localStorage.setItem(key, JSON.stringify(store));\n}","import type { DrawingRecord } from './storage.js';\n\nexport interface DrawingStyleMeta {\n color?: string;\n lineWidth?: number;\n locked?: boolean;\n text?: string;\n}\n\nexport const DEFAULT_DRAWING_STYLE: Required<Pick<DrawingStyleMeta, 'color' | 'lineWidth'>> = {\n color: '#58a6ff',\n lineWidth: 2,\n};\n\nexport function getDrawingStyle(d: DrawingRecord): DrawingStyleMeta & {\n color: string;\n lineWidth: number;\n locked: boolean;\n} {\n const m = (d.meta ?? {}) as DrawingStyleMeta;\n return {\n color: m.color ?? DEFAULT_DRAWING_STYLE.color,\n lineWidth: m.lineWidth ?? DEFAULT_DRAWING_STYLE.lineWidth,\n locked: Boolean(m.locked),\n text: m.text,\n };\n}\n\nexport function setDrawingStyle(d: DrawingRecord, patch: DrawingStyleMeta): void {\n d.meta = { ...(d.meta ?? {}), ...patch };\n}","import { getDrawingStyle, setDrawingStyle, type DrawingStyleMeta } from './drawing-style.js';\nimport type { DrawingRecord } from './storage.js';\nimport { loadDrawings, saveDrawings, storageKey } from './storage.js';\n\nexport type { DrawingRecord, DrawingStyleMeta };\n\nexport type DrawingTool =\n | 'cursor'\n | 'trendline'\n | 'hline'\n | 'vline'\n | 'rectangle'\n | 'fibonacci'\n | 'text';\n\nconst FIB_LEVELS = [0, 0.236, 0.382, 0.5, 0.618, 1];\n\nexport interface DrawingManagerOptions {\n canvas: HTMLCanvasElement;\n /** Main chart pane (overlay parent); cursor-mode hit tests use capture here while overlay is pass-through. */\n interactionHost?: HTMLElement;\n chartId: string;\n symbol: string;\n interval: string;\n priceToY: (price: number) => number | null;\n timeToX: (tMs: number) => number | null;\n xToTime?: (x: number) => number | null;\n yToPrice?: (y: number) => number | null;\n returnToCursorAfterDraw?: boolean;\n onSelectionChange?: (id: string | null, record: DrawingRecord | null) => void;\n onRequestCursorTool?: () => void;\n onContextMenu?: (payload: {\n clientX: number;\n clientY: number;\n drawing: DrawingRecord | null;\n }) => void;\n}\n\ninterface DrawingContext {\n chartId: string;\n symbol: string;\n interval: string;\n}\n\ntype DragState =\n | { kind: 'anchor'; drawingId: string; pointIndex: number }\n | {\n kind: 'body';\n drawingId: string;\n startPoints: Array<{ t: number; price: number }>;\n startT: number;\n startPrice: number;\n };\n\nexport class DrawingManager {\n private tool: DrawingTool = 'cursor';\n private drawings: DrawingRecord[] = [];\n private draft: DrawingRecord | null = null;\n private selectedId: string | null = null;\n private drag: DragState | null = null;\n private activePointerId: number | null = null;\n private key: string;\n private readonly ctx: DrawingContext;\n private readonly handleRadius: number;\n private labelDragIndex: number | null = null;\n private readonly interactionHost: HTMLElement | null;\n private hostListenersAttached = false;\n private moveListenerTarget: HTMLElement | null = null;\n private layerVisible = true;\n private persistenceEnabled = true;\n\n constructor(private readonly opts: DrawingManagerOptions) {\n this.interactionHost = opts.interactionHost ?? opts.canvas.parentElement;\n this.ctx = {\n chartId: opts.chartId,\n symbol: opts.symbol,\n interval: opts.interval,\n };\n this.key = storageKey(this.ctx.chartId, this.ctx.symbol, this.ctx.interval);\n this.drawings = loadDrawings(this.key).drawings;\n this.handleRadius = 6 * devicePixelRatio;\n opts.canvas.addEventListener('pointerdown', this.onDown);\n window.addEventListener('keydown', this.onKeyDown);\n opts.canvas.addEventListener('contextmenu', this.onContextMenu);\n opts.canvas.style.touchAction = 'none';\n if (this.interactionHost) this.interactionHost.style.touchAction = 'none';\n this.applyPointerMode();\n }\n\n getTool(): DrawingTool {\n return this.tool;\n }\n\n setLayerVisible(visible: boolean): void {\n this.layerVisible = visible;\n this.opts.canvas.style.visibility = visible ? 'visible' : 'hidden';\n if (!visible) {\n this.opts.canvas.style.pointerEvents = 'none';\n } else {\n this.applyPointerMode();\n }\n }\n\n setPersistence(enabled: boolean): void {\n this.persistenceEnabled = enabled;\n }\n\n setTool(tool: DrawingTool): void {\n this.tool = tool;\n if (tool !== 'cursor') {\n this.selectedId = null;\n this.drag = null;\n }\n this.applyPointerMode();\n this.redraw();\n }\n\n getSelectedId(): string | null {\n return this.selectedId;\n }\n\n deleteSelected(): boolean {\n if (!this.selectedId) return false;\n this.drawings = this.drawings.filter((d) => d.id !== this.selectedId);\n this.selectedId = null;\n this.drag = null;\n this.persist();\n this.redraw();\n this.emitSelection();\n return true;\n }\n\n deselect(): void {\n this.selectedId = null;\n this.drag = null;\n this.redraw();\n this.emitSelection();\n }\n\n getSelected(): DrawingRecord | null {\n return this.selectedId ? (this.getDrawing(this.selectedId) ?? null) : null;\n }\n\n copySelected(): DrawingRecord | null {\n const src = this.getSelected();\n if (!src) return null;\n const intervalMs = 3_600_000;\n const copy: DrawingRecord = {\n ...src,\n id: `d-${Date.now()}`,\n points: src.points.map((p) => ({ t: p.t + intervalMs * 0.02, price: p.price * 1.001 })),\n meta: { ...(src.meta ?? {}) },\n };\n this.drawings.push(copy);\n this.selectedId = copy.id;\n this.persist();\n this.redraw();\n this.emitSelection();\n return copy;\n }\n\n toggleLockSelected(): boolean {\n const d = this.getSelected();\n if (!d) return false;\n const style = getDrawingStyle(d);\n setDrawingStyle(d, { locked: !style.locked });\n this.persist();\n this.redraw();\n this.emitSelection();\n return !style.locked;\n }\n\n updateSelectedStyle(patch: DrawingStyleMeta): void {\n const d = this.getSelected();\n if (!d) return;\n setDrawingStyle(d, patch);\n this.persist();\n this.redraw();\n this.emitSelection();\n }\n\n setReturnToCursorAfterDraw(v: boolean): void {\n (this.opts as { returnToCursorAfterDraw?: boolean }).returnToCursorAfterDraw = v;\n }\n\n private applyPointerMode(): void {\n const cursor = this.tool === 'cursor';\n this.opts.canvas.style.pointerEvents = cursor ? 'none' : 'auto';\n const moveTarget = cursor && this.interactionHost ? this.interactionHost : this.opts.canvas;\n this.setMoveListeners(moveTarget);\n\n if (!this.interactionHost) return;\n if (cursor && !this.hostListenersAttached) {\n this.interactionHost.addEventListener('pointerdown', this.onHostPointerDown, true);\n this.interactionHost.addEventListener('contextmenu', this.onHostContextMenu, true);\n this.hostListenersAttached = true;\n } else if (!cursor && this.hostListenersAttached) {\n this.interactionHost.removeEventListener('pointerdown', this.onHostPointerDown, true);\n this.interactionHost.removeEventListener('contextmenu', this.onHostContextMenu, true);\n this.hostListenersAttached = false;\n }\n }\n\n private setMoveListeners(target: HTMLElement): void {\n if (this.moveListenerTarget === target) return;\n if (this.moveListenerTarget) {\n this.moveListenerTarget.removeEventListener('pointermove', this.onMove);\n this.moveListenerTarget.removeEventListener('pointerup', this.onUp);\n this.moveListenerTarget.removeEventListener('pointercancel', this.onUp);\n }\n this.moveListenerTarget = target;\n target.addEventListener('pointermove', this.onMove);\n target.addEventListener('pointerup', this.onUp);\n target.addEventListener('pointercancel', this.onUp);\n }\n\n setContext(symbol: string, interval: string): void {\n this.ctx.symbol = symbol;\n this.ctx.interval = interval;\n this.key = storageKey(this.ctx.chartId, symbol, interval);\n this.drawings = loadDrawings(this.key).drawings;\n this.selectedId = null;\n this.draft = null;\n this.drag = null;\n this.redraw();\n }\n\n redraw(): void {\n const canvas = this.opts.canvas;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n for (const d of [...this.drawings, ...(this.draft ? [this.draft] : [])]) {\n const selected = d.id === this.selectedId;\n const style = getDrawingStyle(d);\n ctx.strokeStyle = selected ? '#f78166' : style.color;\n ctx.fillStyle = selected ? '#f7816688' : `${style.color}44`;\n ctx.lineWidth = (selected ? style.lineWidth + 1 : style.lineWidth) * devicePixelRatio;\n ctx.font = `${12 * devicePixelRatio}px sans-serif`;\n this.paint(ctx, d);\n if (selected && !this.draft && this.tool === 'cursor') this.paintHandles(ctx, d);\n }\n\n if (\n this.labelDragIndex != null &&\n this.selectedId &&\n this.drag?.kind === 'anchor'\n ) {\n const d = this.getDrawing(this.selectedId);\n const p = d?.points[this.labelDragIndex];\n if (d && p) this.paintAnchorLabel(ctx, p.t, p.price);\n }\n }\n\n private paintAnchorLabel(ctx: CanvasRenderingContext2D, t: number, price: number): void {\n const x = this.opts.timeToX(t);\n const y = this.opts.priceToY(price);\n if (x == null || y == null) return;\n const label = `${new Date(t).toLocaleString()} ${price.toLocaleString(undefined, { maximumFractionDigits: 4 })}`;\n ctx.font = `${11 * devicePixelRatio}px sans-serif`;\n ctx.fillStyle = '#0d1117';\n const pad = 4 * devicePixelRatio;\n const tw = ctx.measureText(label).width;\n ctx.fillRect(x + 8, y - 20, tw + pad * 2, 16 * devicePixelRatio);\n ctx.fillStyle = '#e6edf3';\n ctx.fillText(label, x + 8 + pad, y - 8);\n }\n\n destroy(): void {\n this.opts.canvas.removeEventListener('pointerdown', this.onDown);\n if (this.moveListenerTarget) {\n this.moveListenerTarget.removeEventListener('pointermove', this.onMove);\n this.moveListenerTarget.removeEventListener('pointerup', this.onUp);\n this.moveListenerTarget.removeEventListener('pointercancel', this.onUp);\n this.moveListenerTarget = null;\n }\n this.opts.canvas.removeEventListener('contextmenu', this.onContextMenu);\n if (this.interactionHost && this.hostListenersAttached) {\n this.interactionHost.removeEventListener('pointerdown', this.onHostPointerDown, true);\n this.interactionHost.removeEventListener('contextmenu', this.onHostContextMenu, true);\n this.hostListenersAttached = false;\n }\n window.removeEventListener('keydown', this.onKeyDown);\n }\n\n private emitSelection(): void {\n this.opts.onSelectionChange?.(this.selectedId, this.getSelected());\n }\n\n private onContextMenu = (e: MouseEvent) => {\n if (this.tool !== 'cursor') return;\n this.openDrawingContextMenu(e);\n };\n\n private onHostContextMenu = (e: MouseEvent) => {\n if (this.tool !== 'cursor') return;\n const pt = this.hitPointFromClient(e.clientX, e.clientY);\n if (!pt) return;\n const onDrawing =\n this.hitTestAnchorAny(pt.x, pt.y) != null || this.hitTestDrawing(pt.x, pt.y) != null;\n if (!onDrawing) return;\n e.preventDefault();\n e.stopPropagation();\n this.openDrawingContextMenu(e);\n };\n\n private openDrawingContextMenu(e: MouseEvent): void {\n e.preventDefault();\n const pt = this.hitPointFromClient(e.clientX, e.clientY);\n if (pt) {\n const hit = this.hitTestDrawing(pt.x, pt.y);\n if (hit) this.selectedId = hit;\n this.redraw();\n this.emitSelection();\n }\n this.opts.onContextMenu?.({\n clientX: e.clientX,\n clientY: e.clientY,\n drawing: this.getSelected(),\n });\n };\n\n private onHostPointerDown = (e: PointerEvent) => {\n if (!this.layerVisible || this.tool !== 'cursor') return;\n if (this.handleCursorPointerDown(e)) {\n e.stopPropagation();\n e.preventDefault();\n }\n };\n\n private paint(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n switch (d.type) {\n case 'hline':\n this.paintHLine(ctx, d);\n break;\n case 'vline':\n this.paintVLine(ctx, d);\n break;\n case 'trendline':\n this.paintTrendline(ctx, d);\n break;\n case 'rectangle':\n this.paintRectangle(ctx, d);\n break;\n case 'fibonacci':\n this.paintFibonacci(ctx, d);\n break;\n case 'text':\n this.paintText(ctx, d);\n break;\n }\n }\n\n private paintHandles(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n for (const p of d.points) {\n const x = this.opts.timeToX(p.t);\n const y = this.opts.priceToY(p.price);\n if (x == null || y == null) continue;\n ctx.beginPath();\n ctx.fillStyle = '#f78166';\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.arc(x, y, this.handleRadius, 0, Math.PI * 2);\n ctx.fill();\n ctx.stroke();\n }\n }\n\n private paintHLine(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n const p = d.points[0];\n if (!p) return;\n const y = this.opts.priceToY(p.price);\n if (y == null) return;\n ctx.beginPath();\n ctx.moveTo(0, y);\n ctx.lineTo(this.opts.canvas.width, y);\n ctx.stroke();\n }\n\n private paintVLine(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n const p = d.points[0];\n if (!p) return;\n const x = this.opts.timeToX(p.t);\n if (x == null) return;\n ctx.beginPath();\n ctx.moveTo(x, 0);\n ctx.lineTo(x, this.opts.canvas.height);\n ctx.stroke();\n }\n\n private paintTrendline(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n if (d.points.length < 2) return;\n const x1 = this.opts.timeToX(d.points[0]!.t);\n const y1 = this.opts.priceToY(d.points[0]!.price);\n const x2 = this.opts.timeToX(d.points[1]!.t);\n const y2 = this.opts.priceToY(d.points[1]!.price);\n if (x1 == null || y1 == null || x2 == null || y2 == null) return;\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n }\n\n private paintRectangle(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n if (d.points.length < 2) return;\n const x1 = this.opts.timeToX(d.points[0]!.t);\n const y1 = this.opts.priceToY(d.points[0]!.price);\n const x2 = this.opts.timeToX(d.points[1]!.t);\n const y2 = this.opts.priceToY(d.points[1]!.price);\n if (x1 == null || y1 == null || x2 == null || y2 == null) return;\n const left = Math.min(x1, x2);\n const top = Math.min(y1, y2);\n const w = Math.abs(x2 - x1);\n const h = Math.abs(y2 - y1);\n ctx.fillRect(left, top, w, h);\n ctx.strokeRect(left, top, w, h);\n }\n\n private paintFibonacci(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n if (d.points.length < 2) return;\n const p0 = d.points[0]!;\n const p1 = d.points[1]!;\n const y0 = this.opts.priceToY(p0.price);\n const y1 = this.opts.priceToY(p1.price);\n if (y0 == null || y1 == null) return;\n const minY = Math.min(y0, y1);\n const maxY = Math.max(y0, y1);\n const range = maxY - minY;\n ctx.setLineDash([4 * devicePixelRatio, 4 * devicePixelRatio]);\n for (const lvl of FIB_LEVELS) {\n const y = maxY - range * lvl;\n ctx.beginPath();\n ctx.moveTo(0, y);\n ctx.lineTo(this.opts.canvas.width, y);\n ctx.stroke();\n ctx.fillStyle = '#8b949e';\n ctx.fillText(`${(lvl * 100).toFixed(1)}%`, 4, y - 2);\n ctx.fillStyle = '#58a6ff44';\n }\n ctx.setLineDash([]);\n }\n\n private paintText(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n const p = d.points[0];\n if (!p) return;\n const x = this.opts.timeToX(p.t);\n const y = this.opts.priceToY(p.price);\n if (x == null || y == null) return;\n const label = String(d.meta?.text ?? 'Text');\n ctx.fillStyle = '#e6edf3';\n ctx.fillText(label, x + 4, y - 4);\n }\n\n private persist(): void {\n if (!this.persistenceEnabled) return;\n saveDrawings(this.key, { version: 1, drawings: this.drawings });\n }\n\n private onKeyDown = (e: KeyboardEvent) => {\n const tag = (e.target as HTMLElement)?.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;\n if (this.tool !== 'cursor' || !this.selectedId) return;\n if (e.key === 'Delete' || e.key === 'Backspace') {\n this.deleteSelected();\n e.preventDefault();\n }\n };\n\n private handleCursorPointerDown(e: PointerEvent): boolean {\n const pt = this.hitPoint(e);\n if (!pt) return false;\n\n const anchor = this.hitTestAnchorAny(pt.x, pt.y);\n if (anchor) {\n const d = this.getDrawing(anchor.drawingId);\n if (d && getDrawingStyle(d).locked) return true;\n this.selectedId = anchor.drawingId;\n this.drag = { kind: 'anchor', drawingId: anchor.drawingId, pointIndex: anchor.pointIndex };\n this.labelDragIndex = anchor.pointIndex;\n this.capturePointer(e);\n this.redraw();\n this.emitSelection();\n return true;\n }\n\n const id = this.hitTestDrawing(pt.x, pt.y);\n this.selectedId = id;\n if (id) {\n const d = this.getDrawing(id);\n if (d && !getDrawingStyle(d).locked) {\n this.drag = {\n kind: 'body',\n drawingId: id,\n startPoints: d.points.map((p) => ({ ...p })),\n startT: pt.t,\n startPrice: pt.price,\n };\n this.capturePointer(e);\n }\n this.redraw();\n this.emitSelection();\n return true;\n }\n\n if (this.selectedId) {\n this.selectedId = null;\n this.drag = null;\n this.redraw();\n this.emitSelection();\n }\n return false;\n }\n\n private onDown = (e: PointerEvent) => {\n if (!this.layerVisible || this.tool === 'cursor') return;\n\n const pt = this.hitPoint(e);\n if (!pt) return;\n\n const type = this.tool === 'hline' ? 'hline' : this.tool;\n this.draft = {\n id: `d-${Date.now()}`,\n type,\n symbol: this.ctx.symbol,\n interval: this.ctx.interval,\n points: [pt],\n meta: type === 'text' ? { text: 'Note' } : undefined,\n };\n this.capturePointer(e);\n };\n\n private onMove = (e: PointerEvent) => {\n if (this.drag && this.activePointerId === e.pointerId) {\n const pt = this.hitPoint(e);\n if (!pt) return;\n const d = this.getDrawing(this.drag.drawingId);\n if (!d || getDrawingStyle(d).locked) return;\n\n if (this.drag.kind === 'anchor') {\n this.labelDragIndex = this.drag.pointIndex;\n d.points[this.drag.pointIndex] = { t: pt.t, price: pt.price };\n } else {\n const dt = pt.t - this.drag.startT;\n const dp = pt.price - this.drag.startPrice;\n d.points = this.drag.startPoints.map((p) => ({\n t: p.t + dt,\n price: p.price + dp,\n }));\n }\n this.redraw();\n return;\n }\n\n if (!this.draft) return;\n const pt = this.hitPoint(e);\n if (!pt) return;\n\n if (this.draft.type === 'hline') {\n this.draft.points = [{ t: pt.t, price: pt.price }];\n } else if (this.draft.type === 'vline' || this.draft.type === 'text') {\n this.draft.points = [{ t: pt.t, price: pt.price }];\n } else if (this.draft.points.length === 1) {\n this.draft.points = [this.draft.points[0]!, pt];\n } else {\n this.draft.points[1] = pt;\n }\n this.redraw();\n };\n\n private onUp = (e: PointerEvent) => {\n if (this.activePointerId === e.pointerId) {\n this.releasePointer(e);\n }\n\n if (this.drag) {\n const changed = this.drag.kind === 'anchor' || this.drag.kind === 'body';\n this.drag = null;\n this.labelDragIndex = null;\n if (changed) this.persist();\n this.redraw();\n return;\n }\n\n if (!this.draft) return;\n const needsTwo = ['trendline', 'rectangle', 'fibonacci'].includes(this.draft.type);\n if (needsTwo && this.draft.points.length < 2) {\n this.draft = null;\n return;\n }\n const finishedTool = this.tool;\n this.drawings.push(this.draft);\n this.selectedId = this.draft.id;\n this.draft = null;\n this.persist();\n this.redraw();\n this.emitSelection();\n if (this.opts.returnToCursorAfterDraw && finishedTool !== 'cursor') {\n this.setTool('cursor');\n this.opts.onRequestCursorTool?.();\n }\n };\n\n private capturePointer(e: PointerEvent): void {\n this.activePointerId = e.pointerId;\n const target =\n this.tool === 'cursor' && this.interactionHost ? this.interactionHost : this.opts.canvas;\n try {\n target.setPointerCapture(e.pointerId);\n } catch {\n /* ignore */\n }\n }\n\n private releasePointer(e: PointerEvent): void {\n this.activePointerId = null;\n const target =\n this.tool === 'cursor' && this.interactionHost ? this.interactionHost : this.opts.canvas;\n try {\n if (target.hasPointerCapture(e.pointerId)) {\n target.releasePointerCapture(e.pointerId);\n }\n } catch {\n /* ignore */\n }\n }\n\n private getDrawing(id: string): DrawingRecord | undefined {\n return this.drawings.find((d) => d.id === id);\n }\n\n private hitPoint(e: PointerEvent): { t: number; price: number; x: number; y: number } | null {\n return this.hitPointFromClient(e.clientX, e.clientY);\n }\n\n private hitPointFromClient(\n clientX: number,\n clientY: number,\n ): { t: number; price: number; x: number; y: number } | null {\n const rect = this.opts.canvas.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return null;\n const x = ((clientX - rect.left) / rect.width) * this.opts.canvas.width;\n const y = ((clientY - rect.top) / rect.height) * this.opts.canvas.height;\n const t = this.opts.xToTime?.(x) ?? null;\n const price = this.opts.yToPrice?.(y) ?? null;\n if (t == null || price == null) return null;\n return { t, price, x, y };\n }\n\n private hitTestAnchorAny(x: number, y: number): { drawingId: string; pointIndex: number } | null {\n const r = this.handleRadius + 4 * devicePixelRatio;\n let best: { drawingId: string; pointIndex: number; dist: number } | null = null;\n\n for (const d of this.drawings) {\n for (let i = 0; i < d.points.length; i++) {\n const p = d.points[i]!;\n const px = this.opts.timeToX(p.t);\n const py = this.opts.priceToY(p.price);\n if (px == null || py == null) continue;\n const dist = Math.hypot(x - px, y - py);\n if (dist > r) continue;\n if (!best || dist < best.dist) {\n best = { drawingId: d.id, pointIndex: i, dist };\n }\n }\n }\n return best ? { drawingId: best.drawingId, pointIndex: best.pointIndex } : null;\n }\n\n private hitTestDrawing(x: number, y: number): string | null {\n const tol = 10 * devicePixelRatio;\n let best: { id: string; dist: number } | null = null;\n\n for (const d of this.drawings) {\n const dist = this.distanceToDrawing(d, x, y);\n if (dist == null || dist > tol) continue;\n if (!best || dist < best.dist) best = { id: d.id, dist };\n }\n return best?.id ?? null;\n }\n\n private distanceToDrawing(d: DrawingRecord, x: number, y: number): number | null {\n if (d.type === 'hline' && d.points[0]) {\n const py = this.opts.priceToY(d.points[0].price);\n return py == null ? null : Math.abs(y - py);\n }\n if (d.type === 'vline' && d.points[0]) {\n const px = this.opts.timeToX(d.points[0].t);\n return px == null ? null : Math.abs(x - px);\n }\n if (d.type === 'trendline' && d.points.length >= 2) {\n return this.distToSegment(d, x, y);\n }\n if ((d.type === 'rectangle' || d.type === 'fibonacci') && d.points.length >= 2) {\n const x1 = this.opts.timeToX(d.points[0]!.t);\n const y1 = this.opts.priceToY(d.points[0]!.price);\n const x2 = this.opts.timeToX(d.points[1]!.t);\n const y2 = this.opts.priceToY(d.points[1]!.price);\n if (x1 == null || y1 == null || x2 == null || y2 == null) return null;\n const left = Math.min(x1, x2);\n const right = Math.max(x1, x2);\n const top = Math.min(y1, y2);\n const bottom = Math.max(y1, y2);\n const inside = x >= left && x <= right && y >= top && y <= bottom;\n const edge = Math.min(\n Math.abs(x - left),\n Math.abs(x - right),\n Math.abs(y - top),\n Math.abs(y - bottom),\n );\n return inside ? 0 : edge;\n }\n if (d.type === 'text' && d.points[0]) {\n const px = this.opts.timeToX(d.points[0].t);\n const py = this.opts.priceToY(d.points[0].price);\n if (px == null || py == null) return null;\n return Math.hypot(x - px, y - py);\n }\n return null;\n }\n\n private distToSegment(d: DrawingRecord, x: number, y: number): number | null {\n const x1 = this.opts.timeToX(d.points[0]!.t);\n const y1 = this.opts.priceToY(d.points[0]!.price);\n const x2 = this.opts.timeToX(d.points[1]!.t);\n const y2 = this.opts.priceToY(d.points[1]!.price);\n if (x1 == null || y1 == null || x2 == null || y2 == null) return null;\n const dx = x2 - x1;\n const dy = y2 - y1;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) return Math.hypot(x - x1, y - y1);\n const t = Math.max(0, Math.min(1, ((x - x1) * dx + (y - y1) * dy) / len2));\n const px = x1 + t * dx;\n const py = y1 + t * dy;\n return Math.hypot(x - px, y - py);\n }\n}"],"mappings":"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","names":["pt"]}
|
|
1
|
+
{"version":3,"sources":["../src/storage.ts","../src/drawing-style.ts","../src/drawing-manager.ts"],"sourcesContent":["const STORAGE_VERSION = 1;\n\nexport interface DrawingRecord {\n id: string;\n type: string;\n symbol: string;\n interval: string;\n points: Array<{ t: number; price: number }>;\n meta?: Record<string, unknown>;\n}\n\nexport interface DrawingStore {\n version: number;\n drawings: DrawingRecord[];\n}\n\nexport function storageKey(chartId: string, symbol: string, interval: string): string {\n return `tradview:drawings:v${STORAGE_VERSION}:${chartId}:${symbol}:${interval}`;\n}\n\nexport function loadDrawings(key: string): DrawingStore {\n try {\n const raw = localStorage.getItem(key);\n if (!raw) return { version: STORAGE_VERSION, drawings: [] };\n const parsed = JSON.parse(raw) as DrawingStore;\n if (parsed.version !== STORAGE_VERSION) return { version: STORAGE_VERSION, drawings: [] };\n return parsed;\n } catch {\n return { version: STORAGE_VERSION, drawings: [] };\n }\n}\n\nexport function saveDrawings(key: string, store: DrawingStore): void {\n localStorage.setItem(key, JSON.stringify(store));\n}","import type { DrawingRecord } from './storage.js';\n\nexport interface DrawingStyleMeta {\n color?: string;\n lineWidth?: number;\n locked?: boolean;\n text?: string;\n}\n\nexport const DEFAULT_DRAWING_STYLE: Required<Pick<DrawingStyleMeta, 'color' | 'lineWidth'>> = {\n color: '#58a6ff',\n lineWidth: 2,\n};\n\nexport function getDrawingStyle(d: DrawingRecord): DrawingStyleMeta & {\n color: string;\n lineWidth: number;\n locked: boolean;\n} {\n const m = (d.meta ?? {}) as DrawingStyleMeta;\n return {\n color: m.color ?? DEFAULT_DRAWING_STYLE.color,\n lineWidth: m.lineWidth ?? DEFAULT_DRAWING_STYLE.lineWidth,\n locked: Boolean(m.locked),\n text: m.text,\n };\n}\n\nexport function setDrawingStyle(d: DrawingRecord, patch: DrawingStyleMeta): void {\n d.meta = { ...(d.meta ?? {}), ...patch };\n}","import { getDrawingStyle, setDrawingStyle, type DrawingStyleMeta } from './drawing-style.js';\nimport type { DrawingRecord } from './storage.js';\nimport { loadDrawings, saveDrawings, storageKey } from './storage.js';\n\nexport type { DrawingRecord, DrawingStyleMeta };\n\nexport type DrawingTool =\n | 'cursor'\n | 'trendline'\n | 'hline'\n | 'vline'\n | 'rectangle'\n | 'fibonacci'\n | 'text';\n\nconst FIB_LEVELS = [0, 0.236, 0.382, 0.5, 0.618, 1];\n\nexport interface DrawingManagerOptions {\n canvas: HTMLCanvasElement;\n /** Main chart pane (overlay parent); cursor-mode hit tests use capture here while overlay is pass-through. */\n interactionHost?: HTMLElement;\n chartId: string;\n symbol: string;\n interval: string;\n priceToY: (price: number) => number | null;\n timeToX: (tMs: number) => number | null;\n xToTime?: (x: number) => number | null;\n yToPrice?: (y: number) => number | null;\n returnToCursorAfterDraw?: boolean;\n onSelectionChange?: (id: string | null, record: DrawingRecord | null) => void;\n onRequestCursorTool?: () => void;\n onContextMenu?: (payload: {\n clientX: number;\n clientY: number;\n drawing: DrawingRecord | null;\n }) => void;\n}\n\ninterface DrawingContext {\n chartId: string;\n symbol: string;\n interval: string;\n}\n\ntype DragState =\n | { kind: 'anchor'; drawingId: string; pointIndex: number }\n | {\n kind: 'body';\n drawingId: string;\n startPoints: Array<{ t: number; price: number }>;\n startT: number;\n startPrice: number;\n };\n\nexport class DrawingManager {\n private tool: DrawingTool = 'cursor';\n private drawings: DrawingRecord[] = [];\n private draft: DrawingRecord | null = null;\n private selectedId: string | null = null;\n private drag: DragState | null = null;\n private activePointerId: number | null = null;\n private key: string;\n private readonly ctx: DrawingContext;\n private readonly handleRadius: number;\n private labelDragIndex: number | null = null;\n private readonly interactionHost: HTMLElement | null;\n private hostListenersAttached = false;\n private moveListenerTarget: HTMLElement | null = null;\n private layerVisible = true;\n private persistenceEnabled = true;\n\n constructor(private readonly opts: DrawingManagerOptions) {\n this.interactionHost = opts.interactionHost ?? opts.canvas.parentElement;\n this.ctx = {\n chartId: opts.chartId,\n symbol: opts.symbol,\n interval: opts.interval,\n };\n this.key = storageKey(this.ctx.chartId, this.ctx.symbol, this.ctx.interval);\n this.drawings = loadDrawings(this.key).drawings;\n this.handleRadius = 6 * devicePixelRatio;\n opts.canvas.addEventListener('pointerdown', this.onDown);\n window.addEventListener('keydown', this.onKeyDown);\n opts.canvas.addEventListener('contextmenu', this.onContextMenu);\n opts.canvas.style.touchAction = 'none';\n if (this.interactionHost) this.interactionHost.style.touchAction = 'none';\n this.applyPointerMode();\n }\n\n getTool(): DrawingTool {\n return this.tool;\n }\n\n setLayerVisible(visible: boolean): void {\n this.layerVisible = visible;\n this.opts.canvas.style.visibility = visible ? 'visible' : 'hidden';\n if (!visible) {\n this.opts.canvas.style.pointerEvents = 'none';\n } else {\n this.applyPointerMode();\n }\n }\n\n setPersistence(enabled: boolean): void {\n this.persistenceEnabled = enabled;\n }\n\n setTool(tool: DrawingTool): void {\n this.tool = tool;\n if (tool !== 'cursor') {\n this.selectedId = null;\n this.drag = null;\n }\n this.applyPointerMode();\n this.redraw();\n }\n\n getSelectedId(): string | null {\n return this.selectedId;\n }\n\n deleteSelected(): boolean {\n if (!this.selectedId) return false;\n this.drawings = this.drawings.filter((d) => d.id !== this.selectedId);\n this.selectedId = null;\n this.drag = null;\n this.persist();\n this.redraw();\n this.emitSelection();\n return true;\n }\n\n /** Remove every drawing for the current symbol/interval. */\n clearAll(): number {\n const count = this.drawings.length;\n if (count === 0 && !this.draft) return 0;\n this.drawings = [];\n this.draft = null;\n this.selectedId = null;\n this.drag = null;\n this.labelDragIndex = null;\n this.persist();\n this.redraw();\n this.emitSelection();\n return count;\n }\n\n deselect(): void {\n this.selectedId = null;\n this.drag = null;\n this.redraw();\n this.emitSelection();\n }\n\n getSelected(): DrawingRecord | null {\n return this.selectedId ? (this.getDrawing(this.selectedId) ?? null) : null;\n }\n\n copySelected(): DrawingRecord | null {\n const src = this.getSelected();\n if (!src) return null;\n const intervalMs = 3_600_000;\n const copy: DrawingRecord = {\n ...src,\n id: `d-${Date.now()}`,\n points: src.points.map((p) => ({ t: p.t + intervalMs * 0.02, price: p.price * 1.001 })),\n meta: { ...(src.meta ?? {}) },\n };\n this.drawings.push(copy);\n this.selectedId = copy.id;\n this.persist();\n this.redraw();\n this.emitSelection();\n return copy;\n }\n\n toggleLockSelected(): boolean {\n const d = this.getSelected();\n if (!d) return false;\n const style = getDrawingStyle(d);\n setDrawingStyle(d, { locked: !style.locked });\n this.persist();\n this.redraw();\n this.emitSelection();\n return !style.locked;\n }\n\n updateSelectedStyle(patch: DrawingStyleMeta): void {\n const d = this.getSelected();\n if (!d) return;\n setDrawingStyle(d, patch);\n this.persist();\n this.redraw();\n this.emitSelection();\n }\n\n setReturnToCursorAfterDraw(v: boolean): void {\n (this.opts as { returnToCursorAfterDraw?: boolean }).returnToCursorAfterDraw = v;\n }\n\n private applyPointerMode(): void {\n const cursor = this.tool === 'cursor';\n this.opts.canvas.style.pointerEvents = cursor ? 'none' : 'auto';\n const moveTarget = cursor && this.interactionHost ? this.interactionHost : this.opts.canvas;\n this.setMoveListeners(moveTarget);\n\n if (!this.interactionHost) return;\n if (cursor && !this.hostListenersAttached) {\n this.interactionHost.addEventListener('pointerdown', this.onHostPointerDown, true);\n this.interactionHost.addEventListener('contextmenu', this.onHostContextMenu, true);\n this.hostListenersAttached = true;\n } else if (!cursor && this.hostListenersAttached) {\n this.interactionHost.removeEventListener('pointerdown', this.onHostPointerDown, true);\n this.interactionHost.removeEventListener('contextmenu', this.onHostContextMenu, true);\n this.hostListenersAttached = false;\n }\n }\n\n private setMoveListeners(target: HTMLElement): void {\n if (this.moveListenerTarget === target) return;\n if (this.moveListenerTarget) {\n this.moveListenerTarget.removeEventListener('pointermove', this.onMove);\n this.moveListenerTarget.removeEventListener('pointerup', this.onUp);\n this.moveListenerTarget.removeEventListener('pointercancel', this.onUp);\n }\n this.moveListenerTarget = target;\n target.addEventListener('pointermove', this.onMove);\n target.addEventListener('pointerup', this.onUp);\n target.addEventListener('pointercancel', this.onUp);\n }\n\n setContext(symbol: string, interval: string): void {\n this.ctx.symbol = symbol;\n this.ctx.interval = interval;\n this.key = storageKey(this.ctx.chartId, symbol, interval);\n this.drawings = loadDrawings(this.key).drawings;\n this.selectedId = null;\n this.draft = null;\n this.drag = null;\n this.redraw();\n }\n\n redraw(): void {\n const canvas = this.opts.canvas;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n for (const d of [...this.drawings, ...(this.draft ? [this.draft] : [])]) {\n const selected = d.id === this.selectedId;\n const style = getDrawingStyle(d);\n ctx.strokeStyle = selected ? '#f78166' : style.color;\n ctx.fillStyle = selected ? '#f7816688' : `${style.color}44`;\n ctx.lineWidth = (selected ? style.lineWidth + 1 : style.lineWidth) * devicePixelRatio;\n ctx.font = `${12 * devicePixelRatio}px sans-serif`;\n this.paint(ctx, d);\n if (selected && !this.draft && this.tool === 'cursor') this.paintHandles(ctx, d);\n }\n\n if (\n this.labelDragIndex != null &&\n this.selectedId &&\n this.drag?.kind === 'anchor'\n ) {\n const d = this.getDrawing(this.selectedId);\n const p = d?.points[this.labelDragIndex];\n if (d && p) this.paintAnchorLabel(ctx, p.t, p.price);\n }\n }\n\n private paintAnchorLabel(ctx: CanvasRenderingContext2D, t: number, price: number): void {\n const x = this.opts.timeToX(t);\n const y = this.opts.priceToY(price);\n if (x == null || y == null) return;\n const label = `${new Date(t).toLocaleString()} ${price.toLocaleString(undefined, { maximumFractionDigits: 4 })}`;\n ctx.font = `${11 * devicePixelRatio}px sans-serif`;\n ctx.fillStyle = '#0d1117';\n const pad = 4 * devicePixelRatio;\n const tw = ctx.measureText(label).width;\n ctx.fillRect(x + 8, y - 20, tw + pad * 2, 16 * devicePixelRatio);\n ctx.fillStyle = '#e6edf3';\n ctx.fillText(label, x + 8 + pad, y - 8);\n }\n\n destroy(): void {\n this.opts.canvas.removeEventListener('pointerdown', this.onDown);\n if (this.moveListenerTarget) {\n this.moveListenerTarget.removeEventListener('pointermove', this.onMove);\n this.moveListenerTarget.removeEventListener('pointerup', this.onUp);\n this.moveListenerTarget.removeEventListener('pointercancel', this.onUp);\n this.moveListenerTarget = null;\n }\n this.opts.canvas.removeEventListener('contextmenu', this.onContextMenu);\n if (this.interactionHost && this.hostListenersAttached) {\n this.interactionHost.removeEventListener('pointerdown', this.onHostPointerDown, true);\n this.interactionHost.removeEventListener('contextmenu', this.onHostContextMenu, true);\n this.hostListenersAttached = false;\n }\n window.removeEventListener('keydown', this.onKeyDown);\n }\n\n private emitSelection(): void {\n this.opts.onSelectionChange?.(this.selectedId, this.getSelected());\n }\n\n private onContextMenu = (e: MouseEvent) => {\n if (this.tool !== 'cursor') return;\n this.openDrawingContextMenu(e);\n };\n\n private onHostContextMenu = (e: MouseEvent) => {\n if (this.tool !== 'cursor') return;\n const pt = this.hitPointFromClient(e.clientX, e.clientY);\n if (!pt) return;\n const onDrawing =\n this.hitTestAnchorAny(pt.x, pt.y) != null || this.hitTestDrawing(pt.x, pt.y) != null;\n if (!onDrawing) return;\n e.preventDefault();\n e.stopPropagation();\n this.openDrawingContextMenu(e);\n };\n\n private openDrawingContextMenu(e: MouseEvent): void {\n e.preventDefault();\n const pt = this.hitPointFromClient(e.clientX, e.clientY);\n if (pt) {\n const hit = this.hitTestDrawing(pt.x, pt.y);\n if (hit) this.selectedId = hit;\n this.redraw();\n this.emitSelection();\n }\n this.opts.onContextMenu?.({\n clientX: e.clientX,\n clientY: e.clientY,\n drawing: this.getSelected(),\n });\n };\n\n private onHostPointerDown = (e: PointerEvent) => {\n if (!this.layerVisible || this.tool !== 'cursor') return;\n if (this.handleCursorPointerDown(e)) {\n e.stopPropagation();\n e.preventDefault();\n }\n };\n\n private paint(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n switch (d.type) {\n case 'hline':\n this.paintHLine(ctx, d);\n break;\n case 'vline':\n this.paintVLine(ctx, d);\n break;\n case 'trendline':\n this.paintTrendline(ctx, d);\n break;\n case 'rectangle':\n this.paintRectangle(ctx, d);\n break;\n case 'fibonacci':\n this.paintFibonacci(ctx, d);\n break;\n case 'text':\n this.paintText(ctx, d);\n break;\n }\n }\n\n private paintHandles(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n for (const p of d.points) {\n const x = this.opts.timeToX(p.t);\n const y = this.opts.priceToY(p.price);\n if (x == null || y == null) continue;\n ctx.beginPath();\n ctx.fillStyle = '#f78166';\n ctx.strokeStyle = '#fff';\n ctx.lineWidth = 2;\n ctx.arc(x, y, this.handleRadius, 0, Math.PI * 2);\n ctx.fill();\n ctx.stroke();\n }\n }\n\n private paintHLine(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n const p = d.points[0];\n if (!p) return;\n const y = this.opts.priceToY(p.price);\n if (y == null) return;\n ctx.beginPath();\n ctx.moveTo(0, y);\n ctx.lineTo(this.opts.canvas.width, y);\n ctx.stroke();\n }\n\n private paintVLine(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n const p = d.points[0];\n if (!p) return;\n const x = this.opts.timeToX(p.t);\n if (x == null) return;\n ctx.beginPath();\n ctx.moveTo(x, 0);\n ctx.lineTo(x, this.opts.canvas.height);\n ctx.stroke();\n }\n\n private paintTrendline(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n if (d.points.length < 2) return;\n const x1 = this.opts.timeToX(d.points[0]!.t);\n const y1 = this.opts.priceToY(d.points[0]!.price);\n const x2 = this.opts.timeToX(d.points[1]!.t);\n const y2 = this.opts.priceToY(d.points[1]!.price);\n if (x1 == null || y1 == null || x2 == null || y2 == null) return;\n ctx.beginPath();\n ctx.moveTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.stroke();\n }\n\n private paintRectangle(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n if (d.points.length < 2) return;\n const x1 = this.opts.timeToX(d.points[0]!.t);\n const y1 = this.opts.priceToY(d.points[0]!.price);\n const x2 = this.opts.timeToX(d.points[1]!.t);\n const y2 = this.opts.priceToY(d.points[1]!.price);\n if (x1 == null || y1 == null || x2 == null || y2 == null) return;\n const left = Math.min(x1, x2);\n const top = Math.min(y1, y2);\n const w = Math.abs(x2 - x1);\n const h = Math.abs(y2 - y1);\n ctx.fillRect(left, top, w, h);\n ctx.strokeRect(left, top, w, h);\n }\n\n private paintFibonacci(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n if (d.points.length < 2) return;\n const p0 = d.points[0]!;\n const p1 = d.points[1]!;\n const y0 = this.opts.priceToY(p0.price);\n const y1 = this.opts.priceToY(p1.price);\n if (y0 == null || y1 == null) return;\n const minY = Math.min(y0, y1);\n const maxY = Math.max(y0, y1);\n const range = maxY - minY;\n ctx.setLineDash([4 * devicePixelRatio, 4 * devicePixelRatio]);\n for (const lvl of FIB_LEVELS) {\n const y = maxY - range * lvl;\n ctx.beginPath();\n ctx.moveTo(0, y);\n ctx.lineTo(this.opts.canvas.width, y);\n ctx.stroke();\n ctx.fillStyle = '#8b949e';\n ctx.fillText(`${(lvl * 100).toFixed(1)}%`, 4, y - 2);\n ctx.fillStyle = '#58a6ff44';\n }\n ctx.setLineDash([]);\n }\n\n private paintText(ctx: CanvasRenderingContext2D, d: DrawingRecord): void {\n const p = d.points[0];\n if (!p) return;\n const x = this.opts.timeToX(p.t);\n const y = this.opts.priceToY(p.price);\n if (x == null || y == null) return;\n const label = String(d.meta?.text ?? 'Text');\n ctx.fillStyle = '#e6edf3';\n ctx.fillText(label, x + 4, y - 4);\n }\n\n private persist(): void {\n if (!this.persistenceEnabled) return;\n saveDrawings(this.key, { version: 1, drawings: this.drawings });\n }\n\n private onKeyDown = (e: KeyboardEvent) => {\n const tag = (e.target as HTMLElement)?.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;\n if (this.tool !== 'cursor' || !this.selectedId) return;\n if (e.key === 'Delete' || e.key === 'Backspace') {\n this.deleteSelected();\n e.preventDefault();\n }\n };\n\n private handleCursorPointerDown(e: PointerEvent): boolean {\n const pt = this.hitPoint(e);\n if (!pt) return false;\n\n const anchor = this.hitTestAnchorAny(pt.x, pt.y);\n if (anchor) {\n const d = this.getDrawing(anchor.drawingId);\n if (d && getDrawingStyle(d).locked) return true;\n this.selectedId = anchor.drawingId;\n this.drag = { kind: 'anchor', drawingId: anchor.drawingId, pointIndex: anchor.pointIndex };\n this.labelDragIndex = anchor.pointIndex;\n this.capturePointer(e);\n this.redraw();\n this.emitSelection();\n return true;\n }\n\n const id = this.hitTestDrawing(pt.x, pt.y);\n this.selectedId = id;\n if (id) {\n const d = this.getDrawing(id);\n if (d && !getDrawingStyle(d).locked) {\n this.drag = {\n kind: 'body',\n drawingId: id,\n startPoints: d.points.map((p) => ({ ...p })),\n startT: pt.t,\n startPrice: pt.price,\n };\n this.capturePointer(e);\n }\n this.redraw();\n this.emitSelection();\n return true;\n }\n\n if (this.selectedId) {\n this.selectedId = null;\n this.drag = null;\n this.redraw();\n this.emitSelection();\n }\n return false;\n }\n\n private onDown = (e: PointerEvent) => {\n if (!this.layerVisible || this.tool === 'cursor') return;\n\n const pt = this.hitPoint(e);\n if (!pt) return;\n\n const type = this.tool === 'hline' ? 'hline' : this.tool;\n this.draft = {\n id: `d-${Date.now()}`,\n type,\n symbol: this.ctx.symbol,\n interval: this.ctx.interval,\n points: [pt],\n meta: type === 'text' ? { text: 'Note' } : undefined,\n };\n this.capturePointer(e);\n };\n\n private onMove = (e: PointerEvent) => {\n if (this.drag && this.activePointerId === e.pointerId) {\n const pt = this.hitPoint(e);\n if (!pt) return;\n const d = this.getDrawing(this.drag.drawingId);\n if (!d || getDrawingStyle(d).locked) return;\n\n if (this.drag.kind === 'anchor') {\n this.labelDragIndex = this.drag.pointIndex;\n d.points[this.drag.pointIndex] = { t: pt.t, price: pt.price };\n } else {\n const dt = pt.t - this.drag.startT;\n const dp = pt.price - this.drag.startPrice;\n d.points = this.drag.startPoints.map((p) => ({\n t: p.t + dt,\n price: p.price + dp,\n }));\n }\n this.redraw();\n return;\n }\n\n if (!this.draft) return;\n const pt = this.hitPoint(e);\n if (!pt) return;\n\n if (this.draft.type === 'hline') {\n this.draft.points = [{ t: pt.t, price: pt.price }];\n } else if (this.draft.type === 'vline' || this.draft.type === 'text') {\n this.draft.points = [{ t: pt.t, price: pt.price }];\n } else if (this.draft.points.length === 1) {\n this.draft.points = [this.draft.points[0]!, pt];\n } else {\n this.draft.points[1] = pt;\n }\n this.redraw();\n };\n\n private onUp = (e: PointerEvent) => {\n if (this.activePointerId === e.pointerId) {\n this.releasePointer(e);\n }\n\n if (this.drag) {\n const changed = this.drag.kind === 'anchor' || this.drag.kind === 'body';\n this.drag = null;\n this.labelDragIndex = null;\n if (changed) this.persist();\n this.redraw();\n return;\n }\n\n if (!this.draft) return;\n const needsTwo = ['trendline', 'rectangle', 'fibonacci'].includes(this.draft.type);\n if (needsTwo && this.draft.points.length < 2) {\n this.draft = null;\n return;\n }\n const finishedTool = this.tool;\n this.drawings.push(this.draft);\n this.selectedId = this.draft.id;\n this.draft = null;\n this.persist();\n this.redraw();\n this.emitSelection();\n if (this.opts.returnToCursorAfterDraw && finishedTool !== 'cursor') {\n this.setTool('cursor');\n this.opts.onRequestCursorTool?.();\n }\n };\n\n private capturePointer(e: PointerEvent): void {\n this.activePointerId = e.pointerId;\n const target =\n this.tool === 'cursor' && this.interactionHost ? this.interactionHost : this.opts.canvas;\n try {\n target.setPointerCapture(e.pointerId);\n } catch {\n /* ignore */\n }\n }\n\n private releasePointer(e: PointerEvent): void {\n this.activePointerId = null;\n const target =\n this.tool === 'cursor' && this.interactionHost ? this.interactionHost : this.opts.canvas;\n try {\n if (target.hasPointerCapture(e.pointerId)) {\n target.releasePointerCapture(e.pointerId);\n }\n } catch {\n /* ignore */\n }\n }\n\n private getDrawing(id: string): DrawingRecord | undefined {\n return this.drawings.find((d) => d.id === id);\n }\n\n private hitPoint(e: PointerEvent): { t: number; price: number; x: number; y: number } | null {\n return this.hitPointFromClient(e.clientX, e.clientY);\n }\n\n private hitPointFromClient(\n clientX: number,\n clientY: number,\n ): { t: number; price: number; x: number; y: number } | null {\n const rect = this.opts.canvas.getBoundingClientRect();\n if (rect.width <= 0 || rect.height <= 0) return null;\n const x = ((clientX - rect.left) / rect.width) * this.opts.canvas.width;\n const y = ((clientY - rect.top) / rect.height) * this.opts.canvas.height;\n const t = this.opts.xToTime?.(x) ?? null;\n const price = this.opts.yToPrice?.(y) ?? null;\n if (t == null || price == null) return null;\n return { t, price, x, y };\n }\n\n private hitTestAnchorAny(x: number, y: number): { drawingId: string; pointIndex: number } | null {\n const r = this.handleRadius + 4 * devicePixelRatio;\n let best: { drawingId: string; pointIndex: number; dist: number } | null = null;\n\n for (const d of this.drawings) {\n for (let i = 0; i < d.points.length; i++) {\n const p = d.points[i]!;\n const px = this.opts.timeToX(p.t);\n const py = this.opts.priceToY(p.price);\n if (px == null || py == null) continue;\n const dist = Math.hypot(x - px, y - py);\n if (dist > r) continue;\n if (!best || dist < best.dist) {\n best = { drawingId: d.id, pointIndex: i, dist };\n }\n }\n }\n return best ? { drawingId: best.drawingId, pointIndex: best.pointIndex } : null;\n }\n\n private hitTestDrawing(x: number, y: number): string | null {\n const tol = 10 * devicePixelRatio;\n let best: { id: string; dist: number } | null = null;\n\n for (const d of this.drawings) {\n const dist = this.distanceToDrawing(d, x, y);\n if (dist == null || dist > tol) continue;\n if (!best || dist < best.dist) best = { id: d.id, dist };\n }\n return best?.id ?? null;\n }\n\n private distanceToDrawing(d: DrawingRecord, x: number, y: number): number | null {\n if (d.type === 'hline' && d.points[0]) {\n const py = this.opts.priceToY(d.points[0].price);\n return py == null ? null : Math.abs(y - py);\n }\n if (d.type === 'vline' && d.points[0]) {\n const px = this.opts.timeToX(d.points[0].t);\n return px == null ? null : Math.abs(x - px);\n }\n if (d.type === 'trendline' && d.points.length >= 2) {\n return this.distToSegment(d, x, y);\n }\n if ((d.type === 'rectangle' || d.type === 'fibonacci') && d.points.length >= 2) {\n const x1 = this.opts.timeToX(d.points[0]!.t);\n const y1 = this.opts.priceToY(d.points[0]!.price);\n const x2 = this.opts.timeToX(d.points[1]!.t);\n const y2 = this.opts.priceToY(d.points[1]!.price);\n if (x1 == null || y1 == null || x2 == null || y2 == null) return null;\n const left = Math.min(x1, x2);\n const right = Math.max(x1, x2);\n const top = Math.min(y1, y2);\n const bottom = Math.max(y1, y2);\n const inside = x >= left && x <= right && y >= top && y <= bottom;\n const edge = Math.min(\n Math.abs(x - left),\n Math.abs(x - right),\n Math.abs(y - top),\n Math.abs(y - bottom),\n );\n return inside ? 0 : edge;\n }\n if (d.type === 'text' && d.points[0]) {\n const px = this.opts.timeToX(d.points[0].t);\n const py = this.opts.priceToY(d.points[0].price);\n if (px == null || py == null) return null;\n return Math.hypot(x - px, y - py);\n }\n return null;\n }\n\n private distToSegment(d: DrawingRecord, x: number, y: number): number | null {\n const x1 = this.opts.timeToX(d.points[0]!.t);\n const y1 = this.opts.priceToY(d.points[0]!.price);\n const x2 = this.opts.timeToX(d.points[1]!.t);\n const y2 = this.opts.priceToY(d.points[1]!.price);\n if (x1 == null || y1 == null || x2 == null || y2 == null) return null;\n const dx = x2 - x1;\n const dy = y2 - y1;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) return Math.hypot(x - x1, y - y1);\n const t = Math.max(0, Math.min(1, ((x - x1) * dx + (y - y1) * dy) / len2));\n const px = x1 + t * dx;\n const py = y1 + t * dy;\n return Math.hypot(x - px, y - py);\n }\n}"],"mappings":"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","names":["pt"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coderyo/drawings",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -9,12 +9,18 @@
|
|
|
9
9
|
"import": "./dist/index.js"
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsup",
|
|
14
|
+
"test": "vitest run --passWithNoTests",
|
|
15
|
+
"lint": "eslint src",
|
|
16
|
+
"typecheck": "tsc --noEmit"
|
|
17
|
+
},
|
|
12
18
|
"devDependencies": {
|
|
19
|
+
"@coderyo/eslint-config": "workspace:*",
|
|
20
|
+
"@coderyo/tsconfig": "workspace:*",
|
|
13
21
|
"tsup": "^8.5.0",
|
|
14
22
|
"typescript": "^5.8.3",
|
|
15
|
-
"vitest": "^3.2.4"
|
|
16
|
-
"@coderyo/eslint-config": "0.0.0",
|
|
17
|
-
"@coderyo/tsconfig": "0.0.0"
|
|
23
|
+
"vitest": "^3.2.4"
|
|
18
24
|
},
|
|
19
25
|
"files": [
|
|
20
26
|
"dist"
|
|
@@ -23,11 +29,5 @@
|
|
|
23
29
|
"type": "git",
|
|
24
30
|
"url": "git+https://github.com/CodeRyoStudio/tradview.git",
|
|
25
31
|
"directory": "packages/drawings"
|
|
26
|
-
},
|
|
27
|
-
"scripts": {
|
|
28
|
-
"build": "tsup",
|
|
29
|
-
"test": "vitest run --passWithNoTests",
|
|
30
|
-
"lint": "eslint src",
|
|
31
|
-
"typecheck": "tsc --noEmit"
|
|
32
32
|
}
|
|
33
|
-
}
|
|
33
|
+
}
|