From 84f3acb15ab64993275e3085c71de8e47720a6df Mon Sep 17 00:00:00 2001 From: Tyler Shaddix Date: Thu, 16 Nov 2023 13:51:56 -0800 Subject: [PATCH] Fix build --- .github/workflows/build.yaml | 1 + .prettierignore | 1 + dist/index.es.js.map | 2 +- dist/index.umd.js.map | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 .prettierignore diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 20e0c06..1b04ea6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -21,3 +21,4 @@ jobs: - run: npm ci - run: npm run typecheck - run: npm run prettier + - run: npm run build diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..5b29e15 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +**/*.d.ts diff --git a/dist/index.es.js.map b/dist/index.es.js.map index ec6e335..74ac204 100644 --- a/dist/index.es.js.map +++ b/dist/index.es.js.map @@ -1 +1 @@ -{"version":3,"file":"index.es.js","sources":["../src/util.ts","../src/StrokeManager.ts","../src/Manager.ts","../src/tools/PenTool.ts","../src/tools/EraserTool.ts","../node_modules/color-name/index.js","../node_modules/color-parse/index.mjs","../node_modules/color-alpha/index.mjs","../src/tools/HighlighterTool.ts"],"sourcesContent":["import { IPoint } from \"./types\";\r\n\r\n/**\r\n * Get the distance between two points\r\n * @param p1\r\n * @param p2\r\n * @returns number\r\n */\r\nexport function getEuclidean(p1: IPoint, p2: IPoint): number {\r\n return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\r\n}\r\n\r\n/**\r\n * Gets the unit vector representing the vector from start\r\n * point to end point with a length of 1.\r\n * @param startPoint\r\n * @param endPoint\r\n * @returns IPoint\r\n */\r\nexport function getUnitVector(startPoint: IPoint, endPoint: IPoint): IPoint {\r\n const length = getEuclidean(startPoint, endPoint);\r\n\r\n const dirVect = {\r\n x: endPoint.x - startPoint.x,\r\n y: endPoint.y - startPoint.y,\r\n };\r\n\r\n const unitVect: IPoint = {\r\n x: dirVect.x / length,\r\n y: dirVect.y / length,\r\n };\r\n\r\n return unitVect;\r\n}\r\n","import { IPoint, IStrokePart } from \"./types\";\r\nimport { getEuclidean } from \"./util\";\r\n\r\nexport interface IOnStrokePartHandler {\r\n (strokePart: IStrokePart): void;\r\n}\r\n\r\nexport interface ITouch {\r\n id: number;\r\n position: IPoint;\r\n}\r\n\r\nexport class StrokeManager {\r\n // reference to canvas element\r\n private canvas: HTMLCanvasElement;\r\n // holds last touch point in a drag\r\n private lastTouch: ITouch | null;\r\n // value indicates how sensitive the stroke detection is higher is better\r\n private sensitivity: number;\r\n // holds all of the last emitted stroke parts in a drag\r\n private lastStrokeParts: IStrokePart[];\r\n // the handlers listening for new strokes\r\n private onStrokePartHandlers: IOnStrokePartHandler[];\r\n\r\n constructor(canvas: HTMLCanvasElement) {\r\n this.canvas = canvas;\r\n this.lastTouch = null;\r\n this.sensitivity = 20.0;\r\n this.lastStrokeParts = [];\r\n this.onStrokePartHandlers = [];\r\n\r\n this.onTouchStart = this.onTouchStart.bind(this);\r\n this.onTouchEnd = this.onTouchEnd.bind(this);\r\n this.onTouchCancel = this.onTouchCancel.bind(this);\r\n this.onTouchMove = this.onTouchMove.bind(this);\r\n this.destroy = this.destroy.bind(this);\r\n this.getRelativePosition = this.getRelativePosition.bind(this);\r\n\r\n this.canvas.addEventListener(\"touchstart\", this.onTouchStart, {\r\n passive: false\r\n });\r\n this.canvas.addEventListener(\"touchend\", this.onTouchEnd, {\r\n passive: false\r\n });\r\n this.canvas.addEventListener(\"touchcancel\", this.onTouchCancel, {\r\n passive: false\r\n });\r\n this.canvas.addEventListener(\"touchmove\", this.onTouchMove, {\r\n passive: false\r\n });\r\n }\r\n\r\n /**\r\n * Registers a handler to be fired on a new stroke part\r\n * @param handler\r\n */\r\n public onStrokePart(handler: IOnStrokePartHandler): void {\r\n this.onStrokePartHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Removes all active listeners\r\n */\r\n public destroy(): void {\r\n this.onStrokePartHandlers = [];\r\n this.lastStrokeParts = [];\r\n this.canvas.removeEventListener(\"touchstart\", this.onTouchStart);\r\n this.canvas.removeEventListener(\"touchend\", this.onTouchEnd);\r\n this.canvas.removeEventListener(\"touchcancel\", this.onTouchCancel);\r\n this.canvas.removeEventListener(\"touchmove\", this.onTouchMove);\r\n }\r\n\r\n /**\r\n * Get relative position to canvas\r\n * @param clientX\r\n * @param clientY\r\n * @returns IPoint\r\n */\r\n private getRelativePosition(clientX: number, clientY: number): IPoint {\r\n const rect = this.canvas.getBoundingClientRect();\r\n\r\n return {\r\n x: clientX - rect.left,\r\n y: clientY - rect.top\r\n };\r\n }\r\n\r\n /**\r\n * Creates a new touch if one does not\r\n * already exist\r\n * @param e\r\n */\r\n private onTouchStart(e: TouchEvent): void {\r\n e.preventDefault();\r\n\r\n // if there is an ongoing touch, ignore this event\r\n if (this.lastTouch) {\r\n return;\r\n }\r\n\r\n const touches: TouchList = e.changedTouches;\r\n\r\n // only get the first touch\r\n const touch = touches.item(0);\r\n\r\n // save the touch\r\n this.lastTouch = {\r\n id: touch.identifier,\r\n position: this.getRelativePosition(touch.clientX, touch.clientY)\r\n };\r\n }\r\n\r\n /**\r\n * Creates a line from last touch to current touch\r\n * point and emits event. Does no-op if no existing touch\r\n * @param e\r\n */\r\n private onTouchMove(e: TouchEvent): void {\r\n e.preventDefault();\r\n\r\n // if no last touch... something is wrong\r\n if (!this.lastTouch) {\r\n return;\r\n }\r\n\r\n const touches: TouchList = e.changedTouches;\r\n\r\n // find the current touch we are tracking\r\n const touch: Touch = Array.from(touches).find(touch => {\r\n return touch.identifier === this.lastTouch.id;\r\n });\r\n\r\n // if the touch was not one we were tracking,\r\n // ignore and no-op\r\n if (!touch) {\r\n return;\r\n }\r\n\r\n const nextTouch: ITouch = {\r\n id: touch.identifier,\r\n position: this.getRelativePosition(touch.clientX, touch.clientY)\r\n };\r\n\r\n // If sensitivity setting has been set,\r\n // check if this point is far enough from last\r\n // touch to be drawn\r\n if (\r\n this.sensitivity &&\r\n getEuclidean(nextTouch.position, this.lastTouch.position) <\r\n 10.0 / this.sensitivity\r\n ) {\r\n return;\r\n }\r\n\r\n const strokePart: IStrokePart = {\r\n endPoint: nextTouch.position,\r\n startPoint: this.lastTouch.position,\r\n isStart: this.lastStrokeParts.length === 0,\r\n isEnd: false\r\n };\r\n\r\n this.onStrokePartHandlers.forEach(handler => {\r\n handler(strokePart);\r\n });\r\n\r\n // save this touch as last touch\r\n this.lastTouch = nextTouch;\r\n this.lastStrokeParts.push(strokePart);\r\n }\r\n\r\n /**\r\n * Draws a line from last point to final point. Removes\r\n * the reference to last touch point.\r\n * @param e\r\n */\r\n private onTouchEnd(e: TouchEvent): void {\r\n e.preventDefault();\r\n\r\n // if no last touch... something is wrong\r\n if (!this.lastTouch) {\r\n return;\r\n }\r\n\r\n const touches: TouchList = e.changedTouches;\r\n\r\n // find the current touch we are tracking\r\n const touch: Touch = Array.from(touches).find(touch => {\r\n return touch.identifier === this.lastTouch.id;\r\n });\r\n\r\n // if the touch was not one we were tracking,\r\n // ignore and no-op\r\n if (!touch) {\r\n return;\r\n }\r\n\r\n const endPoint = this.getRelativePosition(touch.clientX, touch.clientY);\r\n\r\n const strokePart: IStrokePart = {\r\n startPoint: this.lastTouch.position,\r\n endPoint,\r\n isStart: false,\r\n isEnd: true\r\n };\r\n\r\n this.onStrokePartHandlers.forEach(handler => {\r\n handler(strokePart);\r\n });\r\n\r\n this.lastTouch = null;\r\n this.lastStrokeParts = [];\r\n }\r\n\r\n /**\r\n * Removes the current last touch point\r\n * @param e\r\n */\r\n private onTouchCancel(e: TouchEvent): void {\r\n e.preventDefault();\r\n this.lastTouch = null;\r\n this.lastStrokeParts = [];\r\n }\r\n}\r\n","import { IStrokePart, ITool } from \"./types\";\r\nimport { StrokeManager } from \"./StrokeManager\";\r\n\r\nexport class Manager {\r\n // reference to the canvas\r\n private canvas: HTMLCanvasElement;\r\n // reference to stroke manager\r\n private strokeManager: StrokeManager;\r\n // holds the pixel ratio between canvas backing\r\n // store and device ratio (used for hi fi displays)\r\n private pixelRatio: number;\r\n // the width of the canvas\r\n private canvasWidth: number;\r\n // the height of the canvas\r\n private canvasHeight: number;\r\n // holds a reference to next animation frame\r\n private nextAnimationFrame: number;\r\n // the currently selected tool\r\n private currentTool: ITool | null;\r\n // holds stroke parts for ongoing stroke\r\n private currentStroke: IStrokePart[];\r\n // the state of the canvas (not including ongoing stroke)\r\n private canvasState: ImageData | null;\r\n // indicates whether changes have occured that require redraw\r\n private shouldDraw: boolean;\r\n // indicates whether canvas should commit its next draw state to current state\r\n private shouldCommit: boolean;\r\n\r\n constructor(\r\n canvas: HTMLCanvasElement,\r\n canvasWidth: number,\r\n canvasHeight: number\r\n ) {\r\n this.canvas = canvas;\r\n this.canvasWidth = canvasWidth;\r\n this.canvasHeight = canvasHeight;\r\n this.currentTool = null;\r\n this.currentStroke = [];\r\n this.strokeManager = new StrokeManager(canvas);\r\n this.canvasState = null;\r\n this.shouldDraw = false;\r\n this.shouldCommit = false;\r\n\r\n // find pixel ratio relative to backing store and device ratio\r\n const bsr = (canvas.getContext(\"2d\") as any).backingStorePixelRatio || 1;\r\n const dpr = window.devicePixelRatio || 1;\r\n this.pixelRatio = dpr / bsr;\r\n\r\n this.setCanvasSize = this.setCanvasSize.bind(this);\r\n this.setTool = this.setTool.bind(this);\r\n this.destroy = this.destroy.bind(this);\r\n this.clear = this.clear.bind(this);\r\n this.draw = this.draw.bind(this);\r\n this.onStrokePart = this.onStrokePart.bind(this);\r\n\r\n // schedule animation frame loop\r\n this.nextAnimationFrame = window.requestAnimationFrame(this.draw);\r\n // set up listener for new stroke part\r\n this.strokeManager.onStrokePart(this.onStrokePart);\r\n\r\n this.setCanvasSize(canvasWidth, canvasHeight);\r\n }\r\n\r\n /**\r\n * Sets the canvas desired width and height and sets transform\r\n * for hifi displays\r\n * @param width\r\n * @param height\r\n */\r\n public setCanvasSize(width: number, height: number): void {\r\n this.canvasWidth = width;\r\n this.canvasHeight = height;\r\n\r\n const { canvas, canvasWidth, canvasHeight, pixelRatio } = this;\r\n\r\n const ctx = canvas.getContext(\"2d\");\r\n\r\n // appropriately scale canvas to map to device ratio\r\n canvas.width = canvasWidth * pixelRatio;\r\n canvas.height = canvasHeight * pixelRatio;\r\n canvas.style.width = canvasWidth + \"px\";\r\n canvas.style.height = canvasHeight + \"px\";\r\n ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);\r\n }\r\n\r\n /**\r\n * Sets the current tool for the manager\r\n * @param tool\r\n */\r\n public setTool(tool: ITool): void {\r\n this.currentTool = tool;\r\n }\r\n\r\n /**\r\n * Remove all event listeners\r\n */\r\n public destroy(): void {\r\n // cancel animation loop\r\n window.cancelAnimationFrame(this.nextAnimationFrame);\r\n // remove all listeners on stroke manager\r\n this.strokeManager.destroy();\r\n }\r\n\r\n /**\r\n * Clears the canvas\r\n */\r\n public clear(): void {\r\n this.canvasState = null;\r\n this.currentStroke = [];\r\n this.shouldDraw = true;\r\n this.shouldCommit = true;\r\n }\r\n\r\n /**\r\n * Adds a new stroke part to the nextStrokes\r\n * array\r\n * @param strokePart\r\n */\r\n private onStrokePart(strokePart: IStrokePart): void {\r\n this.currentStroke.push(strokePart);\r\n\r\n this.shouldDraw = true;\r\n\r\n if (strokePart.isEnd) {\r\n this.shouldCommit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Draws a frame\r\n */\r\n private draw(): void {\r\n // schedule next draw\r\n this.nextAnimationFrame = window.requestAnimationFrame(this.draw);\r\n\r\n const ctx = this.canvas.getContext(\"2d\");\r\n\r\n if (!this.shouldDraw) {\r\n return;\r\n }\r\n\r\n // clear canvas\r\n ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);\r\n\r\n // draw current state\r\n if (this.canvasState) {\r\n ctx.putImageData(this.canvasState, 0, 0);\r\n }\r\n\r\n // if a tool has been selected and there are\r\n // pending strokes, draw them\r\n if (this.currentTool && this.currentStroke.length) {\r\n ctx.save();\r\n this.currentTool.draw(ctx, this.currentStroke);\r\n ctx.restore();\r\n }\r\n\r\n // if all changes have been made for current stroke,\r\n // save it as the new canvas state\r\n if (this.shouldCommit) {\r\n this.canvasState = ctx.getImageData(\r\n 0,\r\n 0,\r\n this.canvasWidth * this.pixelRatio,\r\n this.canvasHeight * this.pixelRatio\r\n );\r\n this.currentStroke = [];\r\n this.shouldCommit = false;\r\n }\r\n\r\n this.shouldDraw = false;\r\n }\r\n}\r\n","import { IStrokePart } from \"../types\";\r\n\r\nexport class PenTool {\r\n readonly color: string;\r\n readonly width: number;\r\n\r\n constructor(color: string = \"red\", width: number = 3) {\r\n this.color = color;\r\n this.width = width;\r\n }\r\n\r\n /**\r\n * Draws a \"pen stroke\" for all line segments\r\n * @param ctx\r\n * @param strokeParts\r\n */\r\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\r\n const firstPart = strokeParts[0];\r\n\r\n ctx.beginPath();\r\n\r\n ctx.lineWidth = this.width;\r\n ctx.strokeStyle = this.color;\r\n ctx.lineCap = \"round\";\r\n ctx.lineJoin = \"round\";\r\n\r\n ctx.moveTo(firstPart.startPoint.x, firstPart.startPoint.y);\r\n\r\n strokeParts.forEach((strokePart) => {\r\n const { endPoint } = strokePart;\r\n ctx.lineTo(endPoint.x, endPoint.y);\r\n });\r\n\r\n ctx.stroke();\r\n }\r\n}\r\n","import { IStrokePart, IPoint } from \"../types\";\r\nimport { getUnitVector, getEuclidean } from \"../util\";\r\n\r\nexport interface IHandleOptions {\r\n hide: boolean;\r\n strokeWidth: number;\r\n fillColor: string;\r\n strokeColor: string;\r\n}\r\n\r\nexport class EraserTool {\r\n readonly width: number;\r\n readonly handleOpts: IHandleOptions;\r\n\r\n constructor(width: number = 10, handleOpts?: Partial) {\r\n this.width = width;\r\n\r\n handleOpts = handleOpts || {};\r\n\r\n this.handleOpts = {\r\n hide: handleOpts.hide || false,\r\n strokeWidth: handleOpts.strokeWidth || 2,\r\n fillColor: handleOpts.fillColor || \"white\",\r\n strokeColor: handleOpts.strokeColor || \"black\",\r\n };\r\n }\r\n\r\n /**\r\n * Draws an \"eraser stroke\" for all line segments\r\n * @param ctx\r\n * @param strokeParts\r\n */\r\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\r\n const { handleOpts } = this;\r\n const halfWidth = this.width / 2.0;\r\n\r\n strokeParts.forEach((strokePart) => {\r\n const { startPoint, endPoint, isEnd } = strokePart;\r\n\r\n const length = getEuclidean(startPoint, endPoint);\r\n const unitVect: IPoint = getUnitVector(startPoint, endPoint);\r\n let currentPoint: IPoint = startPoint;\r\n let i = 0;\r\n\r\n // clear all the way along the drag\r\n while (i < length) {\r\n const nextPoint: IPoint = {\r\n x: currentPoint.x + unitVect.x,\r\n y: currentPoint.y + unitVect.y,\r\n };\r\n\r\n ctx.clearRect(\r\n nextPoint.x - halfWidth,\r\n nextPoint.y - halfWidth,\r\n this.width,\r\n this.width\r\n );\r\n\r\n i++;\r\n currentPoint = nextPoint;\r\n }\r\n });\r\n\r\n const lastPart = strokeParts[strokeParts.length - 1];\r\n\r\n // if the end is not the last part, then draw\r\n // the tool indicator at the endpoint\r\n if (!lastPart.isEnd && !handleOpts.hide) {\r\n ctx.strokeStyle = handleOpts.strokeColor;\r\n ctx.fillStyle = handleOpts.fillColor;\r\n\r\n ctx.fillRect(\r\n lastPart.endPoint.x - halfWidth,\r\n lastPart.endPoint.y - halfWidth,\r\n this.width,\r\n this.width\r\n );\r\n\r\n ctx.strokeRect(\r\n lastPart.endPoint.x - halfWidth + 0.5,\r\n lastPart.endPoint.y - halfWidth + 0.5,\r\n this.width - 1,\r\n this.width - 1\r\n );\r\n }\r\n }\r\n}\r\n","'use strict'\r\n\r\nmodule.exports = {\r\n\t\"aliceblue\": [240, 248, 255],\r\n\t\"antiquewhite\": [250, 235, 215],\r\n\t\"aqua\": [0, 255, 255],\r\n\t\"aquamarine\": [127, 255, 212],\r\n\t\"azure\": [240, 255, 255],\r\n\t\"beige\": [245, 245, 220],\r\n\t\"bisque\": [255, 228, 196],\r\n\t\"black\": [0, 0, 0],\r\n\t\"blanchedalmond\": [255, 235, 205],\r\n\t\"blue\": [0, 0, 255],\r\n\t\"blueviolet\": [138, 43, 226],\r\n\t\"brown\": [165, 42, 42],\r\n\t\"burlywood\": [222, 184, 135],\r\n\t\"cadetblue\": [95, 158, 160],\r\n\t\"chartreuse\": [127, 255, 0],\r\n\t\"chocolate\": [210, 105, 30],\r\n\t\"coral\": [255, 127, 80],\r\n\t\"cornflowerblue\": [100, 149, 237],\r\n\t\"cornsilk\": [255, 248, 220],\r\n\t\"crimson\": [220, 20, 60],\r\n\t\"cyan\": [0, 255, 255],\r\n\t\"darkblue\": [0, 0, 139],\r\n\t\"darkcyan\": [0, 139, 139],\r\n\t\"darkgoldenrod\": [184, 134, 11],\r\n\t\"darkgray\": [169, 169, 169],\r\n\t\"darkgreen\": [0, 100, 0],\r\n\t\"darkgrey\": [169, 169, 169],\r\n\t\"darkkhaki\": [189, 183, 107],\r\n\t\"darkmagenta\": [139, 0, 139],\r\n\t\"darkolivegreen\": [85, 107, 47],\r\n\t\"darkorange\": [255, 140, 0],\r\n\t\"darkorchid\": [153, 50, 204],\r\n\t\"darkred\": [139, 0, 0],\r\n\t\"darksalmon\": [233, 150, 122],\r\n\t\"darkseagreen\": [143, 188, 143],\r\n\t\"darkslateblue\": [72, 61, 139],\r\n\t\"darkslategray\": [47, 79, 79],\r\n\t\"darkslategrey\": [47, 79, 79],\r\n\t\"darkturquoise\": [0, 206, 209],\r\n\t\"darkviolet\": [148, 0, 211],\r\n\t\"deeppink\": [255, 20, 147],\r\n\t\"deepskyblue\": [0, 191, 255],\r\n\t\"dimgray\": [105, 105, 105],\r\n\t\"dimgrey\": [105, 105, 105],\r\n\t\"dodgerblue\": [30, 144, 255],\r\n\t\"firebrick\": [178, 34, 34],\r\n\t\"floralwhite\": [255, 250, 240],\r\n\t\"forestgreen\": [34, 139, 34],\r\n\t\"fuchsia\": [255, 0, 255],\r\n\t\"gainsboro\": [220, 220, 220],\r\n\t\"ghostwhite\": [248, 248, 255],\r\n\t\"gold\": [255, 215, 0],\r\n\t\"goldenrod\": [218, 165, 32],\r\n\t\"gray\": [128, 128, 128],\r\n\t\"green\": [0, 128, 0],\r\n\t\"greenyellow\": [173, 255, 47],\r\n\t\"grey\": [128, 128, 128],\r\n\t\"honeydew\": [240, 255, 240],\r\n\t\"hotpink\": [255, 105, 180],\r\n\t\"indianred\": [205, 92, 92],\r\n\t\"indigo\": [75, 0, 130],\r\n\t\"ivory\": [255, 255, 240],\r\n\t\"khaki\": [240, 230, 140],\r\n\t\"lavender\": [230, 230, 250],\r\n\t\"lavenderblush\": [255, 240, 245],\r\n\t\"lawngreen\": [124, 252, 0],\r\n\t\"lemonchiffon\": [255, 250, 205],\r\n\t\"lightblue\": [173, 216, 230],\r\n\t\"lightcoral\": [240, 128, 128],\r\n\t\"lightcyan\": [224, 255, 255],\r\n\t\"lightgoldenrodyellow\": [250, 250, 210],\r\n\t\"lightgray\": [211, 211, 211],\r\n\t\"lightgreen\": [144, 238, 144],\r\n\t\"lightgrey\": [211, 211, 211],\r\n\t\"lightpink\": [255, 182, 193],\r\n\t\"lightsalmon\": [255, 160, 122],\r\n\t\"lightseagreen\": [32, 178, 170],\r\n\t\"lightskyblue\": [135, 206, 250],\r\n\t\"lightslategray\": [119, 136, 153],\r\n\t\"lightslategrey\": [119, 136, 153],\r\n\t\"lightsteelblue\": [176, 196, 222],\r\n\t\"lightyellow\": [255, 255, 224],\r\n\t\"lime\": [0, 255, 0],\r\n\t\"limegreen\": [50, 205, 50],\r\n\t\"linen\": [250, 240, 230],\r\n\t\"magenta\": [255, 0, 255],\r\n\t\"maroon\": [128, 0, 0],\r\n\t\"mediumaquamarine\": [102, 205, 170],\r\n\t\"mediumblue\": [0, 0, 205],\r\n\t\"mediumorchid\": [186, 85, 211],\r\n\t\"mediumpurple\": [147, 112, 219],\r\n\t\"mediumseagreen\": [60, 179, 113],\r\n\t\"mediumslateblue\": [123, 104, 238],\r\n\t\"mediumspringgreen\": [0, 250, 154],\r\n\t\"mediumturquoise\": [72, 209, 204],\r\n\t\"mediumvioletred\": [199, 21, 133],\r\n\t\"midnightblue\": [25, 25, 112],\r\n\t\"mintcream\": [245, 255, 250],\r\n\t\"mistyrose\": [255, 228, 225],\r\n\t\"moccasin\": [255, 228, 181],\r\n\t\"navajowhite\": [255, 222, 173],\r\n\t\"navy\": [0, 0, 128],\r\n\t\"oldlace\": [253, 245, 230],\r\n\t\"olive\": [128, 128, 0],\r\n\t\"olivedrab\": [107, 142, 35],\r\n\t\"orange\": [255, 165, 0],\r\n\t\"orangered\": [255, 69, 0],\r\n\t\"orchid\": [218, 112, 214],\r\n\t\"palegoldenrod\": [238, 232, 170],\r\n\t\"palegreen\": [152, 251, 152],\r\n\t\"paleturquoise\": [175, 238, 238],\r\n\t\"palevioletred\": [219, 112, 147],\r\n\t\"papayawhip\": [255, 239, 213],\r\n\t\"peachpuff\": [255, 218, 185],\r\n\t\"peru\": [205, 133, 63],\r\n\t\"pink\": [255, 192, 203],\r\n\t\"plum\": [221, 160, 221],\r\n\t\"powderblue\": [176, 224, 230],\r\n\t\"purple\": [128, 0, 128],\r\n\t\"rebeccapurple\": [102, 51, 153],\r\n\t\"red\": [255, 0, 0],\r\n\t\"rosybrown\": [188, 143, 143],\r\n\t\"royalblue\": [65, 105, 225],\r\n\t\"saddlebrown\": [139, 69, 19],\r\n\t\"salmon\": [250, 128, 114],\r\n\t\"sandybrown\": [244, 164, 96],\r\n\t\"seagreen\": [46, 139, 87],\r\n\t\"seashell\": [255, 245, 238],\r\n\t\"sienna\": [160, 82, 45],\r\n\t\"silver\": [192, 192, 192],\r\n\t\"skyblue\": [135, 206, 235],\r\n\t\"slateblue\": [106, 90, 205],\r\n\t\"slategray\": [112, 128, 144],\r\n\t\"slategrey\": [112, 128, 144],\r\n\t\"snow\": [255, 250, 250],\r\n\t\"springgreen\": [0, 255, 127],\r\n\t\"steelblue\": [70, 130, 180],\r\n\t\"tan\": [210, 180, 140],\r\n\t\"teal\": [0, 128, 128],\r\n\t\"thistle\": [216, 191, 216],\r\n\t\"tomato\": [255, 99, 71],\r\n\t\"turquoise\": [64, 224, 208],\r\n\t\"violet\": [238, 130, 238],\r\n\t\"wheat\": [245, 222, 179],\r\n\t\"white\": [255, 255, 255],\r\n\t\"whitesmoke\": [245, 245, 245],\r\n\t\"yellow\": [255, 255, 0],\r\n\t\"yellowgreen\": [154, 205, 50]\r\n};\r\n","/**\n * @module color-parse\n */\nimport names from 'color-name'\n\nexport default parse\n\n/**\n * Base hues\n * http://dev.w3.org/csswg/css-color/#typedef-named-hue\n */\n//FIXME: use external hue detector\nvar baseHues = {\n\tred: 0,\n\torange: 60,\n\tyellow: 120,\n\tgreen: 180,\n\tblue: 240,\n\tpurple: 300\n}\n\n/**\n * Parse color from the string passed\n *\n * @return {Object} A space indicator `space`, an array `values` and `alpha`\n */\nfunction parse(cstr) {\n\tvar m, parts = [], alpha = 1, space\n\n\tif (typeof cstr === 'string') {\n\t\tcstr = cstr.toLowerCase();\n\n\t\t//keyword\n\t\tif (names[cstr]) {\n\t\t\tparts = names[cstr].slice()\n\t\t\tspace = 'rgb'\n\t\t}\n\n\t\t//reserved words\n\t\telse if (cstr === 'transparent') {\n\t\t\talpha = 0\n\t\t\tspace = 'rgb'\n\t\t\tparts = [0, 0, 0]\n\t\t}\n\n\t\t//hex\n\t\telse if (/^#[A-Fa-f0-9]+$/.test(cstr)) {\n\t\t\tvar base = cstr.slice(1)\n\t\t\tvar size = base.length\n\t\t\tvar isShort = size <= 4\n\t\t\talpha = 1\n\n\t\t\tif (isShort) {\n\t\t\t\tparts = [\n\t\t\t\t\tparseInt(base[0] + base[0], 16),\n\t\t\t\t\tparseInt(base[1] + base[1], 16),\n\t\t\t\t\tparseInt(base[2] + base[2], 16)\n\t\t\t\t]\n\t\t\t\tif (size === 4) {\n\t\t\t\t\talpha = parseInt(base[3] + base[3], 16) / 255\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tparts = [\n\t\t\t\t\tparseInt(base[0] + base[1], 16),\n\t\t\t\t\tparseInt(base[2] + base[3], 16),\n\t\t\t\t\tparseInt(base[4] + base[5], 16)\n\t\t\t\t]\n\t\t\t\tif (size === 8) {\n\t\t\t\t\talpha = parseInt(base[6] + base[7], 16) / 255\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!parts[0]) parts[0] = 0\n\t\t\tif (!parts[1]) parts[1] = 0\n\t\t\tif (!parts[2]) parts[2] = 0\n\n\t\t\tspace = 'rgb'\n\t\t}\n\n\t\t//color space\n\t\telse if (m = /^((?:rgb|hs[lvb]|hwb|cmyk?|xy[zy]|gray|lab|lchu?v?|[ly]uv|lms)a?)\\s*\\(([^\\)]*)\\)/.exec(cstr)) {\n\t\t\tvar name = m[1]\n\t\t\tvar isRGB = name === 'rgb'\n\t\t\tvar base = name.replace(/a$/, '')\n\t\t\tspace = base\n\t\t\tvar size = base === 'cmyk' ? 4 : base === 'gray' ? 1 : 3\n\t\t\tparts = m[2].trim()\n\t\t\t\t.split(/\\s*[,\\/]\\s*|\\s+/)\n\t\t\t\t.map(function (x, i) {\n\t\t\t\t\t//\n\t\t\t\t\tif (/%$/.test(x)) {\n\t\t\t\t\t\t//alpha\n\t\t\t\t\t\tif (i === size) return parseFloat(x) / 100\n\t\t\t\t\t\t//rgb\n\t\t\t\t\t\tif (base === 'rgb') return parseFloat(x) * 255 / 100\n\t\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t\t}\n\t\t\t\t\t//hue\n\t\t\t\t\telse if (base[i] === 'h') {\n\t\t\t\t\t\t//\n\t\t\t\t\t\tif (/deg$/.test(x)) {\n\t\t\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//\n\t\t\t\t\t\telse if (baseHues[x] !== undefined) {\n\t\t\t\t\t\t\treturn baseHues[x]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t})\n\n\t\t\tif (name === base) parts.push(1)\n\t\t\talpha = (isRGB) ? 1 : (parts[size] === undefined) ? 1 : parts[size]\n\t\t\tparts = parts.slice(0, size)\n\t\t}\n\n\t\t//named channels case\n\t\telse if (cstr.length > 10 && /[0-9](?:\\s|\\/)/.test(cstr)) {\n\t\t\tparts = cstr.match(/([0-9]+)/g).map(function (value) {\n\t\t\t\treturn parseFloat(value)\n\t\t\t})\n\n\t\t\tspace = cstr.match(/([a-z])/ig).join('').toLowerCase()\n\t\t}\n\t}\n\n\t//numeric case\n\telse if (!isNaN(cstr)) {\n\t\tspace = 'rgb'\n\t\tparts = [cstr >>> 16, (cstr & 0x00ff00) >>> 8, cstr & 0x0000ff]\n\t}\n\n\t//array-like\n\telse if (Array.isArray(cstr) || cstr.length) {\n\t\tparts = [cstr[0], cstr[1], cstr[2]]\n\t\tspace = 'rgb'\n\t\talpha = cstr.length === 4 ? cstr[3] : 1\n\t}\n\n\t//object case - detects css cases of rgb and hsl\n\telse if (cstr instanceof Object) {\n\t\tif (cstr.r != null || cstr.red != null || cstr.R != null) {\n\t\t\tspace = 'rgb'\n\t\t\tparts = [\n\t\t\t\tcstr.r || cstr.red || cstr.R || 0,\n\t\t\t\tcstr.g || cstr.green || cstr.G || 0,\n\t\t\t\tcstr.b || cstr.blue || cstr.B || 0\n\t\t\t]\n\t\t}\n\t\telse {\n\t\t\tspace = 'hsl'\n\t\t\tparts = [\n\t\t\t\tcstr.h || cstr.hue || cstr.H || 0,\n\t\t\t\tcstr.s || cstr.saturation || cstr.S || 0,\n\t\t\t\tcstr.l || cstr.lightness || cstr.L || cstr.b || cstr.brightness\n\t\t\t]\n\t\t}\n\n\t\talpha = cstr.a || cstr.alpha || cstr.opacity || 1\n\n\t\tif (cstr.opacity != null) alpha /= 100\n\t}\n\n\treturn {\n\t\tspace: space,\n\t\tvalues: parts,\n\t\talpha: alpha\n\t}\n}\n","/**\r\n * @module color-alpha\r\n */\r\nimport parse from 'color-parse';\r\n\r\nexport default function alpha (color, value) {\r\n\tvar obj = parse(color);\r\n\r\n\tif (value == null) value = obj.alpha;\r\n\r\n\t//catch percent\r\n\tif (obj.space[0] === 'h') {\r\n\t\treturn obj.space + ['a(', obj.values[0], ',', obj.values[1], '%,', obj.values[2], '%,', value, ')'].join('');\r\n\t}\r\n\r\n\treturn obj.space + ['a(', obj.values, ',', value, ')'].join('');\r\n}\r\n","import alpha from \"color-alpha\";\r\n\r\nimport { IStrokePart } from \"../types\";\r\n\r\nexport class HighlighterTool {\r\n readonly color: string;\r\n readonly width: number;\r\n\r\n constructor(\r\n color: string = \"yellow\",\r\n width: number = 8,\r\n opacity: Number = 0.3\r\n ) {\r\n this.width = width;\r\n\r\n // calculate color w/ opacity\r\n this.color = alpha(color, 0.4);\r\n }\r\n\r\n /**\r\n * Draws a \"highlighter stroke\" for all line segments\r\n * @param ctx\r\n * @param strokeParts\r\n */\r\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\r\n const firstPart = strokeParts[0];\r\n\r\n ctx.beginPath();\r\n\r\n ctx.lineWidth = this.width;\r\n ctx.strokeStyle = this.color;\r\n ctx.lineCap = \"butt\";\r\n ctx.miterLimit = 1;\r\n\r\n ctx.moveTo(firstPart.startPoint.x, firstPart.startPoint.y);\r\n\r\n strokeParts.forEach((strokePart) => {\r\n const { endPoint } = strokePart;\r\n ctx.lineTo(endPoint.x, endPoint.y);\r\n });\r\n\r\n ctx.stroke();\r\n }\r\n}\r\n"],"names":["getEuclidean","p1","p2","getUnitVector","startPoint","endPoint","length","dirVect","StrokeManager","canvas","handler","clientX","clientY","rect","e","touch","touches","nextTouch","strokePart","Manager","canvasWidth","canvasHeight","bsr","dpr","width","height","pixelRatio","ctx","tool","PenTool","color","strokeParts","firstPart","EraserTool","handleOpts","halfWidth","isEnd","unitVect","currentPoint","i","nextPoint","lastPart","colorName","baseHues","parse","cstr","m","parts","alpha","space","names","base","size","isShort","name","isRGB","x","value","obj","HighlighterTool","opacity"],"mappings":"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","x_google_ignoreList":[5,6,7]} \ No newline at end of file +{"version":3,"file":"index.es.js","sources":["../src/util.ts","../src/StrokeManager.ts","../src/Manager.ts","../src/tools/PenTool.ts","../src/tools/EraserTool.ts","../node_modules/color-name/index.js","../node_modules/color-parse/index.mjs","../node_modules/color-alpha/index.mjs","../src/tools/HighlighterTool.ts"],"sourcesContent":["import { IPoint } from \"./types\";\n\n/**\n * Get the distance between two points\n * @param p1\n * @param p2\n * @returns number\n */\nexport function getEuclidean(p1: IPoint, p2: IPoint): number {\n return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\n}\n\n/**\n * Gets the unit vector representing the vector from start\n * point to end point with a length of 1.\n * @param startPoint\n * @param endPoint\n * @returns IPoint\n */\nexport function getUnitVector(startPoint: IPoint, endPoint: IPoint): IPoint {\n const length = getEuclidean(startPoint, endPoint);\n\n const dirVect = {\n x: endPoint.x - startPoint.x,\n y: endPoint.y - startPoint.y,\n };\n\n const unitVect: IPoint = {\n x: dirVect.x / length,\n y: dirVect.y / length,\n };\n\n return unitVect;\n}\n","import { IPoint, IStrokePart } from \"./types\";\nimport { getEuclidean } from \"./util\";\n\nexport interface IOnStrokePartHandler {\n (strokePart: IStrokePart): void;\n}\n\nexport interface ITouch {\n id: number;\n position: IPoint;\n}\n\nexport class StrokeManager {\n // reference to canvas element\n private canvas: HTMLCanvasElement;\n // holds last touch point in a drag\n private lastTouch: ITouch | null;\n // value indicates how sensitive the stroke detection is higher is better\n private sensitivity: number;\n // holds all of the last emitted stroke parts in a drag\n private lastStrokeParts: IStrokePart[];\n // the handlers listening for new strokes\n private onStrokePartHandlers: IOnStrokePartHandler[];\n\n constructor(canvas: HTMLCanvasElement) {\n this.canvas = canvas;\n this.lastTouch = null;\n this.sensitivity = 20.0;\n this.lastStrokeParts = [];\n this.onStrokePartHandlers = [];\n\n this.onTouchStart = this.onTouchStart.bind(this);\n this.onTouchEnd = this.onTouchEnd.bind(this);\n this.onTouchCancel = this.onTouchCancel.bind(this);\n this.onTouchMove = this.onTouchMove.bind(this);\n this.destroy = this.destroy.bind(this);\n this.getRelativePosition = this.getRelativePosition.bind(this);\n\n this.canvas.addEventListener(\"touchstart\", this.onTouchStart, {\n passive: false,\n });\n this.canvas.addEventListener(\"touchend\", this.onTouchEnd, {\n passive: false,\n });\n this.canvas.addEventListener(\"touchcancel\", this.onTouchCancel, {\n passive: false,\n });\n this.canvas.addEventListener(\"touchmove\", this.onTouchMove, {\n passive: false,\n });\n }\n\n /**\n * Registers a handler to be fired on a new stroke part\n * @param handler\n */\n public onStrokePart(handler: IOnStrokePartHandler): void {\n this.onStrokePartHandlers.push(handler);\n }\n\n /**\n * Removes all active listeners\n */\n public destroy(): void {\n this.onStrokePartHandlers = [];\n this.lastStrokeParts = [];\n this.canvas.removeEventListener(\"touchstart\", this.onTouchStart);\n this.canvas.removeEventListener(\"touchend\", this.onTouchEnd);\n this.canvas.removeEventListener(\"touchcancel\", this.onTouchCancel);\n this.canvas.removeEventListener(\"touchmove\", this.onTouchMove);\n }\n\n /**\n * Get relative position to canvas\n * @param clientX\n * @param clientY\n * @returns IPoint\n */\n private getRelativePosition(clientX: number, clientY: number): IPoint {\n const rect = this.canvas.getBoundingClientRect();\n\n return {\n x: clientX - rect.left,\n y: clientY - rect.top,\n };\n }\n\n /**\n * Creates a new touch if one does not\n * already exist\n * @param e\n */\n private onTouchStart(e: TouchEvent): void {\n e.preventDefault();\n\n // if there is an ongoing touch, ignore this event\n if (this.lastTouch) {\n return;\n }\n\n const touches: TouchList = e.changedTouches;\n\n // only get the first touch\n const touch = touches.item(0);\n\n // save the touch\n this.lastTouch = {\n id: touch.identifier,\n position: this.getRelativePosition(touch.clientX, touch.clientY),\n };\n }\n\n /**\n * Creates a line from last touch to current touch\n * point and emits event. Does no-op if no existing touch\n * @param e\n */\n private onTouchMove(e: TouchEvent): void {\n e.preventDefault();\n\n // if no last touch... something is wrong\n if (!this.lastTouch) {\n return;\n }\n\n const touches: TouchList = e.changedTouches;\n\n // find the current touch we are tracking\n const touch: Touch = Array.from(touches).find((touch) => {\n return touch.identifier === this.lastTouch.id;\n });\n\n // if the touch was not one we were tracking,\n // ignore and no-op\n if (!touch) {\n return;\n }\n\n const nextTouch: ITouch = {\n id: touch.identifier,\n position: this.getRelativePosition(touch.clientX, touch.clientY),\n };\n\n // If sensitivity setting has been set,\n // check if this point is far enough from last\n // touch to be drawn\n if (\n this.sensitivity &&\n getEuclidean(nextTouch.position, this.lastTouch.position) <\n 10.0 / this.sensitivity\n ) {\n return;\n }\n\n const strokePart: IStrokePart = {\n endPoint: nextTouch.position,\n startPoint: this.lastTouch.position,\n isStart: this.lastStrokeParts.length === 0,\n isEnd: false,\n };\n\n this.onStrokePartHandlers.forEach((handler) => {\n handler(strokePart);\n });\n\n // save this touch as last touch\n this.lastTouch = nextTouch;\n this.lastStrokeParts.push(strokePart);\n }\n\n /**\n * Draws a line from last point to final point. Removes\n * the reference to last touch point.\n * @param e\n */\n private onTouchEnd(e: TouchEvent): void {\n e.preventDefault();\n\n // if no last touch... something is wrong\n if (!this.lastTouch) {\n return;\n }\n\n const touches: TouchList = e.changedTouches;\n\n // find the current touch we are tracking\n const touch: Touch = Array.from(touches).find((touch) => {\n return touch.identifier === this.lastTouch.id;\n });\n\n // if the touch was not one we were tracking,\n // ignore and no-op\n if (!touch) {\n return;\n }\n\n const endPoint = this.getRelativePosition(touch.clientX, touch.clientY);\n\n const strokePart: IStrokePart = {\n startPoint: this.lastTouch.position,\n endPoint,\n isStart: false,\n isEnd: true,\n };\n\n this.onStrokePartHandlers.forEach((handler) => {\n handler(strokePart);\n });\n\n this.lastTouch = null;\n this.lastStrokeParts = [];\n }\n\n /**\n * Removes the current last touch point\n * @param e\n */\n private onTouchCancel(e: TouchEvent): void {\n e.preventDefault();\n this.lastTouch = null;\n this.lastStrokeParts = [];\n }\n}\n","import { IStrokePart, ITool } from \"./types\";\nimport { StrokeManager } from \"./StrokeManager\";\n\nexport class Manager {\n // reference to the canvas\n private canvas: HTMLCanvasElement;\n // reference to stroke manager\n private strokeManager: StrokeManager;\n // holds the pixel ratio between canvas backing\n // store and device ratio (used for hi fi displays)\n private pixelRatio: number;\n // the width of the canvas\n private canvasWidth: number;\n // the height of the canvas\n private canvasHeight: number;\n // holds a reference to next animation frame\n private nextAnimationFrame: number;\n // the currently selected tool\n private currentTool: ITool | null;\n // holds stroke parts for ongoing stroke\n private currentStroke: IStrokePart[];\n // the state of the canvas (not including ongoing stroke)\n private canvasState: ImageData | null;\n // indicates whether changes have occured that require redraw\n private shouldDraw: boolean;\n // indicates whether canvas should commit its next draw state to current state\n private shouldCommit: boolean;\n\n constructor(\n canvas: HTMLCanvasElement,\n canvasWidth: number,\n canvasHeight: number,\n ) {\n this.canvas = canvas;\n this.canvasWidth = canvasWidth;\n this.canvasHeight = canvasHeight;\n this.currentTool = null;\n this.currentStroke = [];\n this.strokeManager = new StrokeManager(canvas);\n this.canvasState = null;\n this.shouldDraw = false;\n this.shouldCommit = false;\n\n // find pixel ratio relative to backing store and device ratio\n const bsr = (canvas.getContext(\"2d\") as any).backingStorePixelRatio || 1;\n const dpr = window.devicePixelRatio || 1;\n this.pixelRatio = dpr / bsr;\n\n this.setCanvasSize = this.setCanvasSize.bind(this);\n this.setTool = this.setTool.bind(this);\n this.destroy = this.destroy.bind(this);\n this.clear = this.clear.bind(this);\n this.draw = this.draw.bind(this);\n this.onStrokePart = this.onStrokePart.bind(this);\n\n // schedule animation frame loop\n this.nextAnimationFrame = window.requestAnimationFrame(this.draw);\n // set up listener for new stroke part\n this.strokeManager.onStrokePart(this.onStrokePart);\n\n this.setCanvasSize(canvasWidth, canvasHeight);\n }\n\n /**\n * Sets the canvas desired width and height and sets transform\n * for hifi displays\n * @param width\n * @param height\n */\n public setCanvasSize(width: number, height: number): void {\n this.canvasWidth = width;\n this.canvasHeight = height;\n\n const { canvas, canvasWidth, canvasHeight, pixelRatio } = this;\n\n const ctx = canvas.getContext(\"2d\");\n\n // appropriately scale canvas to map to device ratio\n canvas.width = canvasWidth * pixelRatio;\n canvas.height = canvasHeight * pixelRatio;\n canvas.style.width = canvasWidth + \"px\";\n canvas.style.height = canvasHeight + \"px\";\n ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);\n }\n\n /**\n * Sets the current tool for the manager\n * @param tool\n */\n public setTool(tool: ITool): void {\n this.currentTool = tool;\n }\n\n /**\n * Remove all event listeners\n */\n public destroy(): void {\n // cancel animation loop\n window.cancelAnimationFrame(this.nextAnimationFrame);\n // remove all listeners on stroke manager\n this.strokeManager.destroy();\n }\n\n /**\n * Clears the canvas\n */\n public clear(): void {\n this.canvasState = null;\n this.currentStroke = [];\n this.shouldDraw = true;\n this.shouldCommit = true;\n }\n\n /**\n * Adds a new stroke part to the nextStrokes\n * array\n * @param strokePart\n */\n private onStrokePart(strokePart: IStrokePart): void {\n this.currentStroke.push(strokePart);\n\n this.shouldDraw = true;\n\n if (strokePart.isEnd) {\n this.shouldCommit = true;\n }\n }\n\n /**\n * Draws a frame\n */\n private draw(): void {\n // schedule next draw\n this.nextAnimationFrame = window.requestAnimationFrame(this.draw);\n\n const ctx = this.canvas.getContext(\"2d\");\n\n if (!this.shouldDraw) {\n return;\n }\n\n // clear canvas\n ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);\n\n // draw current state\n if (this.canvasState) {\n ctx.putImageData(this.canvasState, 0, 0);\n }\n\n // if a tool has been selected and there are\n // pending strokes, draw them\n if (this.currentTool && this.currentStroke.length) {\n ctx.save();\n this.currentTool.draw(ctx, this.currentStroke);\n ctx.restore();\n }\n\n // if all changes have been made for current stroke,\n // save it as the new canvas state\n if (this.shouldCommit) {\n this.canvasState = ctx.getImageData(\n 0,\n 0,\n this.canvasWidth * this.pixelRatio,\n this.canvasHeight * this.pixelRatio,\n );\n this.currentStroke = [];\n this.shouldCommit = false;\n }\n\n this.shouldDraw = false;\n }\n}\n","import { IStrokePart } from \"../types\";\n\nexport class PenTool {\n readonly color: string;\n readonly width: number;\n\n constructor(color: string = \"red\", width: number = 3) {\n this.color = color;\n this.width = width;\n }\n\n /**\n * Draws a \"pen stroke\" for all line segments\n * @param ctx\n * @param strokeParts\n */\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\n const firstPart = strokeParts[0];\n\n ctx.beginPath();\n\n ctx.lineWidth = this.width;\n ctx.strokeStyle = this.color;\n ctx.lineCap = \"round\";\n ctx.lineJoin = \"round\";\n\n ctx.moveTo(firstPart.startPoint.x, firstPart.startPoint.y);\n\n strokeParts.forEach((strokePart) => {\n const { endPoint } = strokePart;\n ctx.lineTo(endPoint.x, endPoint.y);\n });\n\n ctx.stroke();\n }\n}\n","import { IStrokePart, IPoint } from \"../types\";\nimport { getUnitVector, getEuclidean } from \"../util\";\n\nexport interface IHandleOptions {\n hide: boolean;\n strokeWidth: number;\n fillColor: string;\n strokeColor: string;\n}\n\nexport class EraserTool {\n readonly width: number;\n readonly handleOpts: IHandleOptions;\n\n constructor(width: number = 10, handleOpts?: Partial) {\n this.width = width;\n\n handleOpts = handleOpts || {};\n\n this.handleOpts = {\n hide: handleOpts.hide || false,\n strokeWidth: handleOpts.strokeWidth || 2,\n fillColor: handleOpts.fillColor || \"white\",\n strokeColor: handleOpts.strokeColor || \"black\",\n };\n }\n\n /**\n * Draws an \"eraser stroke\" for all line segments\n * @param ctx\n * @param strokeParts\n */\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\n const { handleOpts } = this;\n const halfWidth = this.width / 2.0;\n\n strokeParts.forEach((strokePart) => {\n const { startPoint, endPoint, isEnd } = strokePart;\n\n const length = getEuclidean(startPoint, endPoint);\n const unitVect: IPoint = getUnitVector(startPoint, endPoint);\n let currentPoint: IPoint = startPoint;\n let i = 0;\n\n // clear all the way along the drag\n while (i < length) {\n const nextPoint: IPoint = {\n x: currentPoint.x + unitVect.x,\n y: currentPoint.y + unitVect.y,\n };\n\n ctx.clearRect(\n nextPoint.x - halfWidth,\n nextPoint.y - halfWidth,\n this.width,\n this.width,\n );\n\n i++;\n currentPoint = nextPoint;\n }\n });\n\n const lastPart = strokeParts[strokeParts.length - 1];\n\n // if the end is not the last part, then draw\n // the tool indicator at the endpoint\n if (!lastPart.isEnd && !handleOpts.hide) {\n ctx.strokeStyle = handleOpts.strokeColor;\n ctx.fillStyle = handleOpts.fillColor;\n\n ctx.fillRect(\n lastPart.endPoint.x - halfWidth,\n lastPart.endPoint.y - halfWidth,\n this.width,\n this.width,\n );\n\n ctx.strokeRect(\n lastPart.endPoint.x - halfWidth + 0.5,\n lastPart.endPoint.y - halfWidth + 0.5,\n this.width - 1,\n this.width - 1,\n );\n }\n }\n}\n","'use strict'\r\n\r\nmodule.exports = {\r\n\t\"aliceblue\": [240, 248, 255],\r\n\t\"antiquewhite\": [250, 235, 215],\r\n\t\"aqua\": [0, 255, 255],\r\n\t\"aquamarine\": [127, 255, 212],\r\n\t\"azure\": [240, 255, 255],\r\n\t\"beige\": [245, 245, 220],\r\n\t\"bisque\": [255, 228, 196],\r\n\t\"black\": [0, 0, 0],\r\n\t\"blanchedalmond\": [255, 235, 205],\r\n\t\"blue\": [0, 0, 255],\r\n\t\"blueviolet\": [138, 43, 226],\r\n\t\"brown\": [165, 42, 42],\r\n\t\"burlywood\": [222, 184, 135],\r\n\t\"cadetblue\": [95, 158, 160],\r\n\t\"chartreuse\": [127, 255, 0],\r\n\t\"chocolate\": [210, 105, 30],\r\n\t\"coral\": [255, 127, 80],\r\n\t\"cornflowerblue\": [100, 149, 237],\r\n\t\"cornsilk\": [255, 248, 220],\r\n\t\"crimson\": [220, 20, 60],\r\n\t\"cyan\": [0, 255, 255],\r\n\t\"darkblue\": [0, 0, 139],\r\n\t\"darkcyan\": [0, 139, 139],\r\n\t\"darkgoldenrod\": [184, 134, 11],\r\n\t\"darkgray\": [169, 169, 169],\r\n\t\"darkgreen\": [0, 100, 0],\r\n\t\"darkgrey\": [169, 169, 169],\r\n\t\"darkkhaki\": [189, 183, 107],\r\n\t\"darkmagenta\": [139, 0, 139],\r\n\t\"darkolivegreen\": [85, 107, 47],\r\n\t\"darkorange\": [255, 140, 0],\r\n\t\"darkorchid\": [153, 50, 204],\r\n\t\"darkred\": [139, 0, 0],\r\n\t\"darksalmon\": [233, 150, 122],\r\n\t\"darkseagreen\": [143, 188, 143],\r\n\t\"darkslateblue\": [72, 61, 139],\r\n\t\"darkslategray\": [47, 79, 79],\r\n\t\"darkslategrey\": [47, 79, 79],\r\n\t\"darkturquoise\": [0, 206, 209],\r\n\t\"darkviolet\": [148, 0, 211],\r\n\t\"deeppink\": [255, 20, 147],\r\n\t\"deepskyblue\": [0, 191, 255],\r\n\t\"dimgray\": [105, 105, 105],\r\n\t\"dimgrey\": [105, 105, 105],\r\n\t\"dodgerblue\": [30, 144, 255],\r\n\t\"firebrick\": [178, 34, 34],\r\n\t\"floralwhite\": [255, 250, 240],\r\n\t\"forestgreen\": [34, 139, 34],\r\n\t\"fuchsia\": [255, 0, 255],\r\n\t\"gainsboro\": [220, 220, 220],\r\n\t\"ghostwhite\": [248, 248, 255],\r\n\t\"gold\": [255, 215, 0],\r\n\t\"goldenrod\": [218, 165, 32],\r\n\t\"gray\": [128, 128, 128],\r\n\t\"green\": [0, 128, 0],\r\n\t\"greenyellow\": [173, 255, 47],\r\n\t\"grey\": [128, 128, 128],\r\n\t\"honeydew\": [240, 255, 240],\r\n\t\"hotpink\": [255, 105, 180],\r\n\t\"indianred\": [205, 92, 92],\r\n\t\"indigo\": [75, 0, 130],\r\n\t\"ivory\": [255, 255, 240],\r\n\t\"khaki\": [240, 230, 140],\r\n\t\"lavender\": [230, 230, 250],\r\n\t\"lavenderblush\": [255, 240, 245],\r\n\t\"lawngreen\": [124, 252, 0],\r\n\t\"lemonchiffon\": [255, 250, 205],\r\n\t\"lightblue\": [173, 216, 230],\r\n\t\"lightcoral\": [240, 128, 128],\r\n\t\"lightcyan\": [224, 255, 255],\r\n\t\"lightgoldenrodyellow\": [250, 250, 210],\r\n\t\"lightgray\": [211, 211, 211],\r\n\t\"lightgreen\": [144, 238, 144],\r\n\t\"lightgrey\": [211, 211, 211],\r\n\t\"lightpink\": [255, 182, 193],\r\n\t\"lightsalmon\": [255, 160, 122],\r\n\t\"lightseagreen\": [32, 178, 170],\r\n\t\"lightskyblue\": [135, 206, 250],\r\n\t\"lightslategray\": [119, 136, 153],\r\n\t\"lightslategrey\": [119, 136, 153],\r\n\t\"lightsteelblue\": [176, 196, 222],\r\n\t\"lightyellow\": [255, 255, 224],\r\n\t\"lime\": [0, 255, 0],\r\n\t\"limegreen\": [50, 205, 50],\r\n\t\"linen\": [250, 240, 230],\r\n\t\"magenta\": [255, 0, 255],\r\n\t\"maroon\": [128, 0, 0],\r\n\t\"mediumaquamarine\": [102, 205, 170],\r\n\t\"mediumblue\": [0, 0, 205],\r\n\t\"mediumorchid\": [186, 85, 211],\r\n\t\"mediumpurple\": [147, 112, 219],\r\n\t\"mediumseagreen\": [60, 179, 113],\r\n\t\"mediumslateblue\": [123, 104, 238],\r\n\t\"mediumspringgreen\": [0, 250, 154],\r\n\t\"mediumturquoise\": [72, 209, 204],\r\n\t\"mediumvioletred\": [199, 21, 133],\r\n\t\"midnightblue\": [25, 25, 112],\r\n\t\"mintcream\": [245, 255, 250],\r\n\t\"mistyrose\": [255, 228, 225],\r\n\t\"moccasin\": [255, 228, 181],\r\n\t\"navajowhite\": [255, 222, 173],\r\n\t\"navy\": [0, 0, 128],\r\n\t\"oldlace\": [253, 245, 230],\r\n\t\"olive\": [128, 128, 0],\r\n\t\"olivedrab\": [107, 142, 35],\r\n\t\"orange\": [255, 165, 0],\r\n\t\"orangered\": [255, 69, 0],\r\n\t\"orchid\": [218, 112, 214],\r\n\t\"palegoldenrod\": [238, 232, 170],\r\n\t\"palegreen\": [152, 251, 152],\r\n\t\"paleturquoise\": [175, 238, 238],\r\n\t\"palevioletred\": [219, 112, 147],\r\n\t\"papayawhip\": [255, 239, 213],\r\n\t\"peachpuff\": [255, 218, 185],\r\n\t\"peru\": [205, 133, 63],\r\n\t\"pink\": [255, 192, 203],\r\n\t\"plum\": [221, 160, 221],\r\n\t\"powderblue\": [176, 224, 230],\r\n\t\"purple\": [128, 0, 128],\r\n\t\"rebeccapurple\": [102, 51, 153],\r\n\t\"red\": [255, 0, 0],\r\n\t\"rosybrown\": [188, 143, 143],\r\n\t\"royalblue\": [65, 105, 225],\r\n\t\"saddlebrown\": [139, 69, 19],\r\n\t\"salmon\": [250, 128, 114],\r\n\t\"sandybrown\": [244, 164, 96],\r\n\t\"seagreen\": [46, 139, 87],\r\n\t\"seashell\": [255, 245, 238],\r\n\t\"sienna\": [160, 82, 45],\r\n\t\"silver\": [192, 192, 192],\r\n\t\"skyblue\": [135, 206, 235],\r\n\t\"slateblue\": [106, 90, 205],\r\n\t\"slategray\": [112, 128, 144],\r\n\t\"slategrey\": [112, 128, 144],\r\n\t\"snow\": [255, 250, 250],\r\n\t\"springgreen\": [0, 255, 127],\r\n\t\"steelblue\": [70, 130, 180],\r\n\t\"tan\": [210, 180, 140],\r\n\t\"teal\": [0, 128, 128],\r\n\t\"thistle\": [216, 191, 216],\r\n\t\"tomato\": [255, 99, 71],\r\n\t\"turquoise\": [64, 224, 208],\r\n\t\"violet\": [238, 130, 238],\r\n\t\"wheat\": [245, 222, 179],\r\n\t\"white\": [255, 255, 255],\r\n\t\"whitesmoke\": [245, 245, 245],\r\n\t\"yellow\": [255, 255, 0],\r\n\t\"yellowgreen\": [154, 205, 50]\r\n};\r\n","/**\n * @module color-parse\n */\nimport names from 'color-name'\n\nexport default parse\n\n/**\n * Base hues\n * http://dev.w3.org/csswg/css-color/#typedef-named-hue\n */\n//FIXME: use external hue detector\nvar baseHues = {\n\tred: 0,\n\torange: 60,\n\tyellow: 120,\n\tgreen: 180,\n\tblue: 240,\n\tpurple: 300\n}\n\n/**\n * Parse color from the string passed\n *\n * @return {Object} A space indicator `space`, an array `values` and `alpha`\n */\nfunction parse(cstr) {\n\tvar m, parts = [], alpha = 1, space\n\n\tif (typeof cstr === 'string') {\n\t\tcstr = cstr.toLowerCase();\n\n\t\t//keyword\n\t\tif (names[cstr]) {\n\t\t\tparts = names[cstr].slice()\n\t\t\tspace = 'rgb'\n\t\t}\n\n\t\t//reserved words\n\t\telse if (cstr === 'transparent') {\n\t\t\talpha = 0\n\t\t\tspace = 'rgb'\n\t\t\tparts = [0, 0, 0]\n\t\t}\n\n\t\t//hex\n\t\telse if (/^#[A-Fa-f0-9]+$/.test(cstr)) {\n\t\t\tvar base = cstr.slice(1)\n\t\t\tvar size = base.length\n\t\t\tvar isShort = size <= 4\n\t\t\talpha = 1\n\n\t\t\tif (isShort) {\n\t\t\t\tparts = [\n\t\t\t\t\tparseInt(base[0] + base[0], 16),\n\t\t\t\t\tparseInt(base[1] + base[1], 16),\n\t\t\t\t\tparseInt(base[2] + base[2], 16)\n\t\t\t\t]\n\t\t\t\tif (size === 4) {\n\t\t\t\t\talpha = parseInt(base[3] + base[3], 16) / 255\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tparts = [\n\t\t\t\t\tparseInt(base[0] + base[1], 16),\n\t\t\t\t\tparseInt(base[2] + base[3], 16),\n\t\t\t\t\tparseInt(base[4] + base[5], 16)\n\t\t\t\t]\n\t\t\t\tif (size === 8) {\n\t\t\t\t\talpha = parseInt(base[6] + base[7], 16) / 255\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!parts[0]) parts[0] = 0\n\t\t\tif (!parts[1]) parts[1] = 0\n\t\t\tif (!parts[2]) parts[2] = 0\n\n\t\t\tspace = 'rgb'\n\t\t}\n\n\t\t//color space\n\t\telse if (m = /^((?:rgb|hs[lvb]|hwb|cmyk?|xy[zy]|gray|lab|lchu?v?|[ly]uv|lms)a?)\\s*\\(([^\\)]*)\\)/.exec(cstr)) {\n\t\t\tvar name = m[1]\n\t\t\tvar isRGB = name === 'rgb'\n\t\t\tvar base = name.replace(/a$/, '')\n\t\t\tspace = base\n\t\t\tvar size = base === 'cmyk' ? 4 : base === 'gray' ? 1 : 3\n\t\t\tparts = m[2].trim()\n\t\t\t\t.split(/\\s*[,\\/]\\s*|\\s+/)\n\t\t\t\t.map(function (x, i) {\n\t\t\t\t\t//\n\t\t\t\t\tif (/%$/.test(x)) {\n\t\t\t\t\t\t//alpha\n\t\t\t\t\t\tif (i === size) return parseFloat(x) / 100\n\t\t\t\t\t\t//rgb\n\t\t\t\t\t\tif (base === 'rgb') return parseFloat(x) * 255 / 100\n\t\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t\t}\n\t\t\t\t\t//hue\n\t\t\t\t\telse if (base[i] === 'h') {\n\t\t\t\t\t\t//\n\t\t\t\t\t\tif (/deg$/.test(x)) {\n\t\t\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//\n\t\t\t\t\t\telse if (baseHues[x] !== undefined) {\n\t\t\t\t\t\t\treturn baseHues[x]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t})\n\n\t\t\tif (name === base) parts.push(1)\n\t\t\talpha = (isRGB) ? 1 : (parts[size] === undefined) ? 1 : parts[size]\n\t\t\tparts = parts.slice(0, size)\n\t\t}\n\n\t\t//named channels case\n\t\telse if (cstr.length > 10 && /[0-9](?:\\s|\\/)/.test(cstr)) {\n\t\t\tparts = cstr.match(/([0-9]+)/g).map(function (value) {\n\t\t\t\treturn parseFloat(value)\n\t\t\t})\n\n\t\t\tspace = cstr.match(/([a-z])/ig).join('').toLowerCase()\n\t\t}\n\t}\n\n\t//numeric case\n\telse if (!isNaN(cstr)) {\n\t\tspace = 'rgb'\n\t\tparts = [cstr >>> 16, (cstr & 0x00ff00) >>> 8, cstr & 0x0000ff]\n\t}\n\n\t//array-like\n\telse if (Array.isArray(cstr) || cstr.length) {\n\t\tparts = [cstr[0], cstr[1], cstr[2]]\n\t\tspace = 'rgb'\n\t\talpha = cstr.length === 4 ? cstr[3] : 1\n\t}\n\n\t//object case - detects css cases of rgb and hsl\n\telse if (cstr instanceof Object) {\n\t\tif (cstr.r != null || cstr.red != null || cstr.R != null) {\n\t\t\tspace = 'rgb'\n\t\t\tparts = [\n\t\t\t\tcstr.r || cstr.red || cstr.R || 0,\n\t\t\t\tcstr.g || cstr.green || cstr.G || 0,\n\t\t\t\tcstr.b || cstr.blue || cstr.B || 0\n\t\t\t]\n\t\t}\n\t\telse {\n\t\t\tspace = 'hsl'\n\t\t\tparts = [\n\t\t\t\tcstr.h || cstr.hue || cstr.H || 0,\n\t\t\t\tcstr.s || cstr.saturation || cstr.S || 0,\n\t\t\t\tcstr.l || cstr.lightness || cstr.L || cstr.b || cstr.brightness\n\t\t\t]\n\t\t}\n\n\t\talpha = cstr.a || cstr.alpha || cstr.opacity || 1\n\n\t\tif (cstr.opacity != null) alpha /= 100\n\t}\n\n\treturn {\n\t\tspace: space,\n\t\tvalues: parts,\n\t\talpha: alpha\n\t}\n}\n","/**\r\n * @module color-alpha\r\n */\r\nimport parse from 'color-parse';\r\n\r\nexport default function alpha (color, value) {\r\n\tvar obj = parse(color);\r\n\r\n\tif (value == null) value = obj.alpha;\r\n\r\n\t//catch percent\r\n\tif (obj.space[0] === 'h') {\r\n\t\treturn obj.space + ['a(', obj.values[0], ',', obj.values[1], '%,', obj.values[2], '%,', value, ')'].join('');\r\n\t}\r\n\r\n\treturn obj.space + ['a(', obj.values, ',', value, ')'].join('');\r\n}\r\n","import alpha from \"color-alpha\";\n\nimport { IStrokePart } from \"../types\";\n\nexport class HighlighterTool {\n readonly color: string;\n readonly width: number;\n\n constructor(\n color: string = \"yellow\",\n width: number = 8,\n opacity: Number = 0.3,\n ) {\n this.width = width;\n\n // calculate color w/ opacity\n this.color = alpha(color, 0.4);\n }\n\n /**\n * Draws a \"highlighter stroke\" for all line segments\n * @param ctx\n * @param strokeParts\n */\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\n const firstPart = strokeParts[0];\n\n ctx.beginPath();\n\n ctx.lineWidth = this.width;\n ctx.strokeStyle = this.color;\n ctx.lineCap = \"butt\";\n ctx.miterLimit = 1;\n\n ctx.moveTo(firstPart.startPoint.x, firstPart.startPoint.y);\n\n strokeParts.forEach((strokePart) => {\n const { endPoint } = strokePart;\n ctx.lineTo(endPoint.x, endPoint.y);\n });\n\n ctx.stroke();\n }\n}\n"],"names":["getEuclidean","p1","p2","getUnitVector","startPoint","endPoint","length","dirVect","StrokeManager","canvas","handler","clientX","clientY","rect","e","touch","touches","nextTouch","strokePart","Manager","canvasWidth","canvasHeight","bsr","dpr","width","height","pixelRatio","ctx","tool","PenTool","color","strokeParts","firstPart","EraserTool","handleOpts","halfWidth","isEnd","unitVect","currentPoint","i","nextPoint","lastPart","colorName","baseHues","parse","cstr","m","parts","alpha","space","names","base","size","isShort","name","isRGB","x","value","obj","HighlighterTool","opacity"],"mappings":"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","x_google_ignoreList":[5,6,7]} \ No newline at end of file diff --git a/dist/index.umd.js.map b/dist/index.umd.js.map index 29ab3d8..3cfe016 100644 --- a/dist/index.umd.js.map +++ b/dist/index.umd.js.map @@ -1 +1 @@ -{"version":3,"file":"index.umd.js","sources":["../src/util.ts","../src/StrokeManager.ts","../src/Manager.ts","../src/tools/PenTool.ts","../src/tools/EraserTool.ts","../node_modules/color-name/index.js","../node_modules/color-parse/index.mjs","../node_modules/color-alpha/index.mjs","../src/tools/HighlighterTool.ts"],"sourcesContent":["import { IPoint } from \"./types\";\r\n\r\n/**\r\n * Get the distance between two points\r\n * @param p1\r\n * @param p2\r\n * @returns number\r\n */\r\nexport function getEuclidean(p1: IPoint, p2: IPoint): number {\r\n return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\r\n}\r\n\r\n/**\r\n * Gets the unit vector representing the vector from start\r\n * point to end point with a length of 1.\r\n * @param startPoint\r\n * @param endPoint\r\n * @returns IPoint\r\n */\r\nexport function getUnitVector(startPoint: IPoint, endPoint: IPoint): IPoint {\r\n const length = getEuclidean(startPoint, endPoint);\r\n\r\n const dirVect = {\r\n x: endPoint.x - startPoint.x,\r\n y: endPoint.y - startPoint.y,\r\n };\r\n\r\n const unitVect: IPoint = {\r\n x: dirVect.x / length,\r\n y: dirVect.y / length,\r\n };\r\n\r\n return unitVect;\r\n}\r\n","import { IPoint, IStrokePart } from \"./types\";\r\nimport { getEuclidean } from \"./util\";\r\n\r\nexport interface IOnStrokePartHandler {\r\n (strokePart: IStrokePart): void;\r\n}\r\n\r\nexport interface ITouch {\r\n id: number;\r\n position: IPoint;\r\n}\r\n\r\nexport class StrokeManager {\r\n // reference to canvas element\r\n private canvas: HTMLCanvasElement;\r\n // holds last touch point in a drag\r\n private lastTouch: ITouch | null;\r\n // value indicates how sensitive the stroke detection is higher is better\r\n private sensitivity: number;\r\n // holds all of the last emitted stroke parts in a drag\r\n private lastStrokeParts: IStrokePart[];\r\n // the handlers listening for new strokes\r\n private onStrokePartHandlers: IOnStrokePartHandler[];\r\n\r\n constructor(canvas: HTMLCanvasElement) {\r\n this.canvas = canvas;\r\n this.lastTouch = null;\r\n this.sensitivity = 20.0;\r\n this.lastStrokeParts = [];\r\n this.onStrokePartHandlers = [];\r\n\r\n this.onTouchStart = this.onTouchStart.bind(this);\r\n this.onTouchEnd = this.onTouchEnd.bind(this);\r\n this.onTouchCancel = this.onTouchCancel.bind(this);\r\n this.onTouchMove = this.onTouchMove.bind(this);\r\n this.destroy = this.destroy.bind(this);\r\n this.getRelativePosition = this.getRelativePosition.bind(this);\r\n\r\n this.canvas.addEventListener(\"touchstart\", this.onTouchStart, {\r\n passive: false\r\n });\r\n this.canvas.addEventListener(\"touchend\", this.onTouchEnd, {\r\n passive: false\r\n });\r\n this.canvas.addEventListener(\"touchcancel\", this.onTouchCancel, {\r\n passive: false\r\n });\r\n this.canvas.addEventListener(\"touchmove\", this.onTouchMove, {\r\n passive: false\r\n });\r\n }\r\n\r\n /**\r\n * Registers a handler to be fired on a new stroke part\r\n * @param handler\r\n */\r\n public onStrokePart(handler: IOnStrokePartHandler): void {\r\n this.onStrokePartHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Removes all active listeners\r\n */\r\n public destroy(): void {\r\n this.onStrokePartHandlers = [];\r\n this.lastStrokeParts = [];\r\n this.canvas.removeEventListener(\"touchstart\", this.onTouchStart);\r\n this.canvas.removeEventListener(\"touchend\", this.onTouchEnd);\r\n this.canvas.removeEventListener(\"touchcancel\", this.onTouchCancel);\r\n this.canvas.removeEventListener(\"touchmove\", this.onTouchMove);\r\n }\r\n\r\n /**\r\n * Get relative position to canvas\r\n * @param clientX\r\n * @param clientY\r\n * @returns IPoint\r\n */\r\n private getRelativePosition(clientX: number, clientY: number): IPoint {\r\n const rect = this.canvas.getBoundingClientRect();\r\n\r\n return {\r\n x: clientX - rect.left,\r\n y: clientY - rect.top\r\n };\r\n }\r\n\r\n /**\r\n * Creates a new touch if one does not\r\n * already exist\r\n * @param e\r\n */\r\n private onTouchStart(e: TouchEvent): void {\r\n e.preventDefault();\r\n\r\n // if there is an ongoing touch, ignore this event\r\n if (this.lastTouch) {\r\n return;\r\n }\r\n\r\n const touches: TouchList = e.changedTouches;\r\n\r\n // only get the first touch\r\n const touch = touches.item(0);\r\n\r\n // save the touch\r\n this.lastTouch = {\r\n id: touch.identifier,\r\n position: this.getRelativePosition(touch.clientX, touch.clientY)\r\n };\r\n }\r\n\r\n /**\r\n * Creates a line from last touch to current touch\r\n * point and emits event. Does no-op if no existing touch\r\n * @param e\r\n */\r\n private onTouchMove(e: TouchEvent): void {\r\n e.preventDefault();\r\n\r\n // if no last touch... something is wrong\r\n if (!this.lastTouch) {\r\n return;\r\n }\r\n\r\n const touches: TouchList = e.changedTouches;\r\n\r\n // find the current touch we are tracking\r\n const touch: Touch = Array.from(touches).find(touch => {\r\n return touch.identifier === this.lastTouch.id;\r\n });\r\n\r\n // if the touch was not one we were tracking,\r\n // ignore and no-op\r\n if (!touch) {\r\n return;\r\n }\r\n\r\n const nextTouch: ITouch = {\r\n id: touch.identifier,\r\n position: this.getRelativePosition(touch.clientX, touch.clientY)\r\n };\r\n\r\n // If sensitivity setting has been set,\r\n // check if this point is far enough from last\r\n // touch to be drawn\r\n if (\r\n this.sensitivity &&\r\n getEuclidean(nextTouch.position, this.lastTouch.position) <\r\n 10.0 / this.sensitivity\r\n ) {\r\n return;\r\n }\r\n\r\n const strokePart: IStrokePart = {\r\n endPoint: nextTouch.position,\r\n startPoint: this.lastTouch.position,\r\n isStart: this.lastStrokeParts.length === 0,\r\n isEnd: false\r\n };\r\n\r\n this.onStrokePartHandlers.forEach(handler => {\r\n handler(strokePart);\r\n });\r\n\r\n // save this touch as last touch\r\n this.lastTouch = nextTouch;\r\n this.lastStrokeParts.push(strokePart);\r\n }\r\n\r\n /**\r\n * Draws a line from last point to final point. Removes\r\n * the reference to last touch point.\r\n * @param e\r\n */\r\n private onTouchEnd(e: TouchEvent): void {\r\n e.preventDefault();\r\n\r\n // if no last touch... something is wrong\r\n if (!this.lastTouch) {\r\n return;\r\n }\r\n\r\n const touches: TouchList = e.changedTouches;\r\n\r\n // find the current touch we are tracking\r\n const touch: Touch = Array.from(touches).find(touch => {\r\n return touch.identifier === this.lastTouch.id;\r\n });\r\n\r\n // if the touch was not one we were tracking,\r\n // ignore and no-op\r\n if (!touch) {\r\n return;\r\n }\r\n\r\n const endPoint = this.getRelativePosition(touch.clientX, touch.clientY);\r\n\r\n const strokePart: IStrokePart = {\r\n startPoint: this.lastTouch.position,\r\n endPoint,\r\n isStart: false,\r\n isEnd: true\r\n };\r\n\r\n this.onStrokePartHandlers.forEach(handler => {\r\n handler(strokePart);\r\n });\r\n\r\n this.lastTouch = null;\r\n this.lastStrokeParts = [];\r\n }\r\n\r\n /**\r\n * Removes the current last touch point\r\n * @param e\r\n */\r\n private onTouchCancel(e: TouchEvent): void {\r\n e.preventDefault();\r\n this.lastTouch = null;\r\n this.lastStrokeParts = [];\r\n }\r\n}\r\n","import { IStrokePart, ITool } from \"./types\";\r\nimport { StrokeManager } from \"./StrokeManager\";\r\n\r\nexport class Manager {\r\n // reference to the canvas\r\n private canvas: HTMLCanvasElement;\r\n // reference to stroke manager\r\n private strokeManager: StrokeManager;\r\n // holds the pixel ratio between canvas backing\r\n // store and device ratio (used for hi fi displays)\r\n private pixelRatio: number;\r\n // the width of the canvas\r\n private canvasWidth: number;\r\n // the height of the canvas\r\n private canvasHeight: number;\r\n // holds a reference to next animation frame\r\n private nextAnimationFrame: number;\r\n // the currently selected tool\r\n private currentTool: ITool | null;\r\n // holds stroke parts for ongoing stroke\r\n private currentStroke: IStrokePart[];\r\n // the state of the canvas (not including ongoing stroke)\r\n private canvasState: ImageData | null;\r\n // indicates whether changes have occured that require redraw\r\n private shouldDraw: boolean;\r\n // indicates whether canvas should commit its next draw state to current state\r\n private shouldCommit: boolean;\r\n\r\n constructor(\r\n canvas: HTMLCanvasElement,\r\n canvasWidth: number,\r\n canvasHeight: number\r\n ) {\r\n this.canvas = canvas;\r\n this.canvasWidth = canvasWidth;\r\n this.canvasHeight = canvasHeight;\r\n this.currentTool = null;\r\n this.currentStroke = [];\r\n this.strokeManager = new StrokeManager(canvas);\r\n this.canvasState = null;\r\n this.shouldDraw = false;\r\n this.shouldCommit = false;\r\n\r\n // find pixel ratio relative to backing store and device ratio\r\n const bsr = (canvas.getContext(\"2d\") as any).backingStorePixelRatio || 1;\r\n const dpr = window.devicePixelRatio || 1;\r\n this.pixelRatio = dpr / bsr;\r\n\r\n this.setCanvasSize = this.setCanvasSize.bind(this);\r\n this.setTool = this.setTool.bind(this);\r\n this.destroy = this.destroy.bind(this);\r\n this.clear = this.clear.bind(this);\r\n this.draw = this.draw.bind(this);\r\n this.onStrokePart = this.onStrokePart.bind(this);\r\n\r\n // schedule animation frame loop\r\n this.nextAnimationFrame = window.requestAnimationFrame(this.draw);\r\n // set up listener for new stroke part\r\n this.strokeManager.onStrokePart(this.onStrokePart);\r\n\r\n this.setCanvasSize(canvasWidth, canvasHeight);\r\n }\r\n\r\n /**\r\n * Sets the canvas desired width and height and sets transform\r\n * for hifi displays\r\n * @param width\r\n * @param height\r\n */\r\n public setCanvasSize(width: number, height: number): void {\r\n this.canvasWidth = width;\r\n this.canvasHeight = height;\r\n\r\n const { canvas, canvasWidth, canvasHeight, pixelRatio } = this;\r\n\r\n const ctx = canvas.getContext(\"2d\");\r\n\r\n // appropriately scale canvas to map to device ratio\r\n canvas.width = canvasWidth * pixelRatio;\r\n canvas.height = canvasHeight * pixelRatio;\r\n canvas.style.width = canvasWidth + \"px\";\r\n canvas.style.height = canvasHeight + \"px\";\r\n ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);\r\n }\r\n\r\n /**\r\n * Sets the current tool for the manager\r\n * @param tool\r\n */\r\n public setTool(tool: ITool): void {\r\n this.currentTool = tool;\r\n }\r\n\r\n /**\r\n * Remove all event listeners\r\n */\r\n public destroy(): void {\r\n // cancel animation loop\r\n window.cancelAnimationFrame(this.nextAnimationFrame);\r\n // remove all listeners on stroke manager\r\n this.strokeManager.destroy();\r\n }\r\n\r\n /**\r\n * Clears the canvas\r\n */\r\n public clear(): void {\r\n this.canvasState = null;\r\n this.currentStroke = [];\r\n this.shouldDraw = true;\r\n this.shouldCommit = true;\r\n }\r\n\r\n /**\r\n * Adds a new stroke part to the nextStrokes\r\n * array\r\n * @param strokePart\r\n */\r\n private onStrokePart(strokePart: IStrokePart): void {\r\n this.currentStroke.push(strokePart);\r\n\r\n this.shouldDraw = true;\r\n\r\n if (strokePart.isEnd) {\r\n this.shouldCommit = true;\r\n }\r\n }\r\n\r\n /**\r\n * Draws a frame\r\n */\r\n private draw(): void {\r\n // schedule next draw\r\n this.nextAnimationFrame = window.requestAnimationFrame(this.draw);\r\n\r\n const ctx = this.canvas.getContext(\"2d\");\r\n\r\n if (!this.shouldDraw) {\r\n return;\r\n }\r\n\r\n // clear canvas\r\n ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);\r\n\r\n // draw current state\r\n if (this.canvasState) {\r\n ctx.putImageData(this.canvasState, 0, 0);\r\n }\r\n\r\n // if a tool has been selected and there are\r\n // pending strokes, draw them\r\n if (this.currentTool && this.currentStroke.length) {\r\n ctx.save();\r\n this.currentTool.draw(ctx, this.currentStroke);\r\n ctx.restore();\r\n }\r\n\r\n // if all changes have been made for current stroke,\r\n // save it as the new canvas state\r\n if (this.shouldCommit) {\r\n this.canvasState = ctx.getImageData(\r\n 0,\r\n 0,\r\n this.canvasWidth * this.pixelRatio,\r\n this.canvasHeight * this.pixelRatio\r\n );\r\n this.currentStroke = [];\r\n this.shouldCommit = false;\r\n }\r\n\r\n this.shouldDraw = false;\r\n }\r\n}\r\n","import { IStrokePart } from \"../types\";\r\n\r\nexport class PenTool {\r\n readonly color: string;\r\n readonly width: number;\r\n\r\n constructor(color: string = \"red\", width: number = 3) {\r\n this.color = color;\r\n this.width = width;\r\n }\r\n\r\n /**\r\n * Draws a \"pen stroke\" for all line segments\r\n * @param ctx\r\n * @param strokeParts\r\n */\r\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\r\n const firstPart = strokeParts[0];\r\n\r\n ctx.beginPath();\r\n\r\n ctx.lineWidth = this.width;\r\n ctx.strokeStyle = this.color;\r\n ctx.lineCap = \"round\";\r\n ctx.lineJoin = \"round\";\r\n\r\n ctx.moveTo(firstPart.startPoint.x, firstPart.startPoint.y);\r\n\r\n strokeParts.forEach((strokePart) => {\r\n const { endPoint } = strokePart;\r\n ctx.lineTo(endPoint.x, endPoint.y);\r\n });\r\n\r\n ctx.stroke();\r\n }\r\n}\r\n","import { IStrokePart, IPoint } from \"../types\";\r\nimport { getUnitVector, getEuclidean } from \"../util\";\r\n\r\nexport interface IHandleOptions {\r\n hide: boolean;\r\n strokeWidth: number;\r\n fillColor: string;\r\n strokeColor: string;\r\n}\r\n\r\nexport class EraserTool {\r\n readonly width: number;\r\n readonly handleOpts: IHandleOptions;\r\n\r\n constructor(width: number = 10, handleOpts?: Partial) {\r\n this.width = width;\r\n\r\n handleOpts = handleOpts || {};\r\n\r\n this.handleOpts = {\r\n hide: handleOpts.hide || false,\r\n strokeWidth: handleOpts.strokeWidth || 2,\r\n fillColor: handleOpts.fillColor || \"white\",\r\n strokeColor: handleOpts.strokeColor || \"black\",\r\n };\r\n }\r\n\r\n /**\r\n * Draws an \"eraser stroke\" for all line segments\r\n * @param ctx\r\n * @param strokeParts\r\n */\r\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\r\n const { handleOpts } = this;\r\n const halfWidth = this.width / 2.0;\r\n\r\n strokeParts.forEach((strokePart) => {\r\n const { startPoint, endPoint, isEnd } = strokePart;\r\n\r\n const length = getEuclidean(startPoint, endPoint);\r\n const unitVect: IPoint = getUnitVector(startPoint, endPoint);\r\n let currentPoint: IPoint = startPoint;\r\n let i = 0;\r\n\r\n // clear all the way along the drag\r\n while (i < length) {\r\n const nextPoint: IPoint = {\r\n x: currentPoint.x + unitVect.x,\r\n y: currentPoint.y + unitVect.y,\r\n };\r\n\r\n ctx.clearRect(\r\n nextPoint.x - halfWidth,\r\n nextPoint.y - halfWidth,\r\n this.width,\r\n this.width\r\n );\r\n\r\n i++;\r\n currentPoint = nextPoint;\r\n }\r\n });\r\n\r\n const lastPart = strokeParts[strokeParts.length - 1];\r\n\r\n // if the end is not the last part, then draw\r\n // the tool indicator at the endpoint\r\n if (!lastPart.isEnd && !handleOpts.hide) {\r\n ctx.strokeStyle = handleOpts.strokeColor;\r\n ctx.fillStyle = handleOpts.fillColor;\r\n\r\n ctx.fillRect(\r\n lastPart.endPoint.x - halfWidth,\r\n lastPart.endPoint.y - halfWidth,\r\n this.width,\r\n this.width\r\n );\r\n\r\n ctx.strokeRect(\r\n lastPart.endPoint.x - halfWidth + 0.5,\r\n lastPart.endPoint.y - halfWidth + 0.5,\r\n this.width - 1,\r\n this.width - 1\r\n );\r\n }\r\n }\r\n}\r\n","'use strict'\r\n\r\nmodule.exports = {\r\n\t\"aliceblue\": [240, 248, 255],\r\n\t\"antiquewhite\": [250, 235, 215],\r\n\t\"aqua\": [0, 255, 255],\r\n\t\"aquamarine\": [127, 255, 212],\r\n\t\"azure\": [240, 255, 255],\r\n\t\"beige\": [245, 245, 220],\r\n\t\"bisque\": [255, 228, 196],\r\n\t\"black\": [0, 0, 0],\r\n\t\"blanchedalmond\": [255, 235, 205],\r\n\t\"blue\": [0, 0, 255],\r\n\t\"blueviolet\": [138, 43, 226],\r\n\t\"brown\": [165, 42, 42],\r\n\t\"burlywood\": [222, 184, 135],\r\n\t\"cadetblue\": [95, 158, 160],\r\n\t\"chartreuse\": [127, 255, 0],\r\n\t\"chocolate\": [210, 105, 30],\r\n\t\"coral\": [255, 127, 80],\r\n\t\"cornflowerblue\": [100, 149, 237],\r\n\t\"cornsilk\": [255, 248, 220],\r\n\t\"crimson\": [220, 20, 60],\r\n\t\"cyan\": [0, 255, 255],\r\n\t\"darkblue\": [0, 0, 139],\r\n\t\"darkcyan\": [0, 139, 139],\r\n\t\"darkgoldenrod\": [184, 134, 11],\r\n\t\"darkgray\": [169, 169, 169],\r\n\t\"darkgreen\": [0, 100, 0],\r\n\t\"darkgrey\": [169, 169, 169],\r\n\t\"darkkhaki\": [189, 183, 107],\r\n\t\"darkmagenta\": [139, 0, 139],\r\n\t\"darkolivegreen\": [85, 107, 47],\r\n\t\"darkorange\": [255, 140, 0],\r\n\t\"darkorchid\": [153, 50, 204],\r\n\t\"darkred\": [139, 0, 0],\r\n\t\"darksalmon\": [233, 150, 122],\r\n\t\"darkseagreen\": [143, 188, 143],\r\n\t\"darkslateblue\": [72, 61, 139],\r\n\t\"darkslategray\": [47, 79, 79],\r\n\t\"darkslategrey\": [47, 79, 79],\r\n\t\"darkturquoise\": [0, 206, 209],\r\n\t\"darkviolet\": [148, 0, 211],\r\n\t\"deeppink\": [255, 20, 147],\r\n\t\"deepskyblue\": [0, 191, 255],\r\n\t\"dimgray\": [105, 105, 105],\r\n\t\"dimgrey\": [105, 105, 105],\r\n\t\"dodgerblue\": [30, 144, 255],\r\n\t\"firebrick\": [178, 34, 34],\r\n\t\"floralwhite\": [255, 250, 240],\r\n\t\"forestgreen\": [34, 139, 34],\r\n\t\"fuchsia\": [255, 0, 255],\r\n\t\"gainsboro\": [220, 220, 220],\r\n\t\"ghostwhite\": [248, 248, 255],\r\n\t\"gold\": [255, 215, 0],\r\n\t\"goldenrod\": [218, 165, 32],\r\n\t\"gray\": [128, 128, 128],\r\n\t\"green\": [0, 128, 0],\r\n\t\"greenyellow\": [173, 255, 47],\r\n\t\"grey\": [128, 128, 128],\r\n\t\"honeydew\": [240, 255, 240],\r\n\t\"hotpink\": [255, 105, 180],\r\n\t\"indianred\": [205, 92, 92],\r\n\t\"indigo\": [75, 0, 130],\r\n\t\"ivory\": [255, 255, 240],\r\n\t\"khaki\": [240, 230, 140],\r\n\t\"lavender\": [230, 230, 250],\r\n\t\"lavenderblush\": [255, 240, 245],\r\n\t\"lawngreen\": [124, 252, 0],\r\n\t\"lemonchiffon\": [255, 250, 205],\r\n\t\"lightblue\": [173, 216, 230],\r\n\t\"lightcoral\": [240, 128, 128],\r\n\t\"lightcyan\": [224, 255, 255],\r\n\t\"lightgoldenrodyellow\": [250, 250, 210],\r\n\t\"lightgray\": [211, 211, 211],\r\n\t\"lightgreen\": [144, 238, 144],\r\n\t\"lightgrey\": [211, 211, 211],\r\n\t\"lightpink\": [255, 182, 193],\r\n\t\"lightsalmon\": [255, 160, 122],\r\n\t\"lightseagreen\": [32, 178, 170],\r\n\t\"lightskyblue\": [135, 206, 250],\r\n\t\"lightslategray\": [119, 136, 153],\r\n\t\"lightslategrey\": [119, 136, 153],\r\n\t\"lightsteelblue\": [176, 196, 222],\r\n\t\"lightyellow\": [255, 255, 224],\r\n\t\"lime\": [0, 255, 0],\r\n\t\"limegreen\": [50, 205, 50],\r\n\t\"linen\": [250, 240, 230],\r\n\t\"magenta\": [255, 0, 255],\r\n\t\"maroon\": [128, 0, 0],\r\n\t\"mediumaquamarine\": [102, 205, 170],\r\n\t\"mediumblue\": [0, 0, 205],\r\n\t\"mediumorchid\": [186, 85, 211],\r\n\t\"mediumpurple\": [147, 112, 219],\r\n\t\"mediumseagreen\": [60, 179, 113],\r\n\t\"mediumslateblue\": [123, 104, 238],\r\n\t\"mediumspringgreen\": [0, 250, 154],\r\n\t\"mediumturquoise\": [72, 209, 204],\r\n\t\"mediumvioletred\": [199, 21, 133],\r\n\t\"midnightblue\": [25, 25, 112],\r\n\t\"mintcream\": [245, 255, 250],\r\n\t\"mistyrose\": [255, 228, 225],\r\n\t\"moccasin\": [255, 228, 181],\r\n\t\"navajowhite\": [255, 222, 173],\r\n\t\"navy\": [0, 0, 128],\r\n\t\"oldlace\": [253, 245, 230],\r\n\t\"olive\": [128, 128, 0],\r\n\t\"olivedrab\": [107, 142, 35],\r\n\t\"orange\": [255, 165, 0],\r\n\t\"orangered\": [255, 69, 0],\r\n\t\"orchid\": [218, 112, 214],\r\n\t\"palegoldenrod\": [238, 232, 170],\r\n\t\"palegreen\": [152, 251, 152],\r\n\t\"paleturquoise\": [175, 238, 238],\r\n\t\"palevioletred\": [219, 112, 147],\r\n\t\"papayawhip\": [255, 239, 213],\r\n\t\"peachpuff\": [255, 218, 185],\r\n\t\"peru\": [205, 133, 63],\r\n\t\"pink\": [255, 192, 203],\r\n\t\"plum\": [221, 160, 221],\r\n\t\"powderblue\": [176, 224, 230],\r\n\t\"purple\": [128, 0, 128],\r\n\t\"rebeccapurple\": [102, 51, 153],\r\n\t\"red\": [255, 0, 0],\r\n\t\"rosybrown\": [188, 143, 143],\r\n\t\"royalblue\": [65, 105, 225],\r\n\t\"saddlebrown\": [139, 69, 19],\r\n\t\"salmon\": [250, 128, 114],\r\n\t\"sandybrown\": [244, 164, 96],\r\n\t\"seagreen\": [46, 139, 87],\r\n\t\"seashell\": [255, 245, 238],\r\n\t\"sienna\": [160, 82, 45],\r\n\t\"silver\": [192, 192, 192],\r\n\t\"skyblue\": [135, 206, 235],\r\n\t\"slateblue\": [106, 90, 205],\r\n\t\"slategray\": [112, 128, 144],\r\n\t\"slategrey\": [112, 128, 144],\r\n\t\"snow\": [255, 250, 250],\r\n\t\"springgreen\": [0, 255, 127],\r\n\t\"steelblue\": [70, 130, 180],\r\n\t\"tan\": [210, 180, 140],\r\n\t\"teal\": [0, 128, 128],\r\n\t\"thistle\": [216, 191, 216],\r\n\t\"tomato\": [255, 99, 71],\r\n\t\"turquoise\": [64, 224, 208],\r\n\t\"violet\": [238, 130, 238],\r\n\t\"wheat\": [245, 222, 179],\r\n\t\"white\": [255, 255, 255],\r\n\t\"whitesmoke\": [245, 245, 245],\r\n\t\"yellow\": [255, 255, 0],\r\n\t\"yellowgreen\": [154, 205, 50]\r\n};\r\n","/**\n * @module color-parse\n */\nimport names from 'color-name'\n\nexport default parse\n\n/**\n * Base hues\n * http://dev.w3.org/csswg/css-color/#typedef-named-hue\n */\n//FIXME: use external hue detector\nvar baseHues = {\n\tred: 0,\n\torange: 60,\n\tyellow: 120,\n\tgreen: 180,\n\tblue: 240,\n\tpurple: 300\n}\n\n/**\n * Parse color from the string passed\n *\n * @return {Object} A space indicator `space`, an array `values` and `alpha`\n */\nfunction parse(cstr) {\n\tvar m, parts = [], alpha = 1, space\n\n\tif (typeof cstr === 'string') {\n\t\tcstr = cstr.toLowerCase();\n\n\t\t//keyword\n\t\tif (names[cstr]) {\n\t\t\tparts = names[cstr].slice()\n\t\t\tspace = 'rgb'\n\t\t}\n\n\t\t//reserved words\n\t\telse if (cstr === 'transparent') {\n\t\t\talpha = 0\n\t\t\tspace = 'rgb'\n\t\t\tparts = [0, 0, 0]\n\t\t}\n\n\t\t//hex\n\t\telse if (/^#[A-Fa-f0-9]+$/.test(cstr)) {\n\t\t\tvar base = cstr.slice(1)\n\t\t\tvar size = base.length\n\t\t\tvar isShort = size <= 4\n\t\t\talpha = 1\n\n\t\t\tif (isShort) {\n\t\t\t\tparts = [\n\t\t\t\t\tparseInt(base[0] + base[0], 16),\n\t\t\t\t\tparseInt(base[1] + base[1], 16),\n\t\t\t\t\tparseInt(base[2] + base[2], 16)\n\t\t\t\t]\n\t\t\t\tif (size === 4) {\n\t\t\t\t\talpha = parseInt(base[3] + base[3], 16) / 255\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tparts = [\n\t\t\t\t\tparseInt(base[0] + base[1], 16),\n\t\t\t\t\tparseInt(base[2] + base[3], 16),\n\t\t\t\t\tparseInt(base[4] + base[5], 16)\n\t\t\t\t]\n\t\t\t\tif (size === 8) {\n\t\t\t\t\talpha = parseInt(base[6] + base[7], 16) / 255\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!parts[0]) parts[0] = 0\n\t\t\tif (!parts[1]) parts[1] = 0\n\t\t\tif (!parts[2]) parts[2] = 0\n\n\t\t\tspace = 'rgb'\n\t\t}\n\n\t\t//color space\n\t\telse if (m = /^((?:rgb|hs[lvb]|hwb|cmyk?|xy[zy]|gray|lab|lchu?v?|[ly]uv|lms)a?)\\s*\\(([^\\)]*)\\)/.exec(cstr)) {\n\t\t\tvar name = m[1]\n\t\t\tvar isRGB = name === 'rgb'\n\t\t\tvar base = name.replace(/a$/, '')\n\t\t\tspace = base\n\t\t\tvar size = base === 'cmyk' ? 4 : base === 'gray' ? 1 : 3\n\t\t\tparts = m[2].trim()\n\t\t\t\t.split(/\\s*[,\\/]\\s*|\\s+/)\n\t\t\t\t.map(function (x, i) {\n\t\t\t\t\t//\n\t\t\t\t\tif (/%$/.test(x)) {\n\t\t\t\t\t\t//alpha\n\t\t\t\t\t\tif (i === size) return parseFloat(x) / 100\n\t\t\t\t\t\t//rgb\n\t\t\t\t\t\tif (base === 'rgb') return parseFloat(x) * 255 / 100\n\t\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t\t}\n\t\t\t\t\t//hue\n\t\t\t\t\telse if (base[i] === 'h') {\n\t\t\t\t\t\t//\n\t\t\t\t\t\tif (/deg$/.test(x)) {\n\t\t\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//\n\t\t\t\t\t\telse if (baseHues[x] !== undefined) {\n\t\t\t\t\t\t\treturn baseHues[x]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t})\n\n\t\t\tif (name === base) parts.push(1)\n\t\t\talpha = (isRGB) ? 1 : (parts[size] === undefined) ? 1 : parts[size]\n\t\t\tparts = parts.slice(0, size)\n\t\t}\n\n\t\t//named channels case\n\t\telse if (cstr.length > 10 && /[0-9](?:\\s|\\/)/.test(cstr)) {\n\t\t\tparts = cstr.match(/([0-9]+)/g).map(function (value) {\n\t\t\t\treturn parseFloat(value)\n\t\t\t})\n\n\t\t\tspace = cstr.match(/([a-z])/ig).join('').toLowerCase()\n\t\t}\n\t}\n\n\t//numeric case\n\telse if (!isNaN(cstr)) {\n\t\tspace = 'rgb'\n\t\tparts = [cstr >>> 16, (cstr & 0x00ff00) >>> 8, cstr & 0x0000ff]\n\t}\n\n\t//array-like\n\telse if (Array.isArray(cstr) || cstr.length) {\n\t\tparts = [cstr[0], cstr[1], cstr[2]]\n\t\tspace = 'rgb'\n\t\talpha = cstr.length === 4 ? cstr[3] : 1\n\t}\n\n\t//object case - detects css cases of rgb and hsl\n\telse if (cstr instanceof Object) {\n\t\tif (cstr.r != null || cstr.red != null || cstr.R != null) {\n\t\t\tspace = 'rgb'\n\t\t\tparts = [\n\t\t\t\tcstr.r || cstr.red || cstr.R || 0,\n\t\t\t\tcstr.g || cstr.green || cstr.G || 0,\n\t\t\t\tcstr.b || cstr.blue || cstr.B || 0\n\t\t\t]\n\t\t}\n\t\telse {\n\t\t\tspace = 'hsl'\n\t\t\tparts = [\n\t\t\t\tcstr.h || cstr.hue || cstr.H || 0,\n\t\t\t\tcstr.s || cstr.saturation || cstr.S || 0,\n\t\t\t\tcstr.l || cstr.lightness || cstr.L || cstr.b || cstr.brightness\n\t\t\t]\n\t\t}\n\n\t\talpha = cstr.a || cstr.alpha || cstr.opacity || 1\n\n\t\tif (cstr.opacity != null) alpha /= 100\n\t}\n\n\treturn {\n\t\tspace: space,\n\t\tvalues: parts,\n\t\talpha: alpha\n\t}\n}\n","/**\r\n * @module color-alpha\r\n */\r\nimport parse from 'color-parse';\r\n\r\nexport default function alpha (color, value) {\r\n\tvar obj = parse(color);\r\n\r\n\tif (value == null) value = obj.alpha;\r\n\r\n\t//catch percent\r\n\tif (obj.space[0] === 'h') {\r\n\t\treturn obj.space + ['a(', obj.values[0], ',', obj.values[1], '%,', obj.values[2], '%,', value, ')'].join('');\r\n\t}\r\n\r\n\treturn obj.space + ['a(', obj.values, ',', value, ')'].join('');\r\n}\r\n","import alpha from \"color-alpha\";\r\n\r\nimport { IStrokePart } from \"../types\";\r\n\r\nexport class HighlighterTool {\r\n readonly color: string;\r\n readonly width: number;\r\n\r\n constructor(\r\n color: string = \"yellow\",\r\n width: number = 8,\r\n opacity: Number = 0.3\r\n ) {\r\n this.width = width;\r\n\r\n // calculate color w/ opacity\r\n this.color = alpha(color, 0.4);\r\n }\r\n\r\n /**\r\n * Draws a \"highlighter stroke\" for all line segments\r\n * @param ctx\r\n * @param strokeParts\r\n */\r\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\r\n const firstPart = strokeParts[0];\r\n\r\n ctx.beginPath();\r\n\r\n ctx.lineWidth = this.width;\r\n ctx.strokeStyle = this.color;\r\n ctx.lineCap = \"butt\";\r\n ctx.miterLimit = 1;\r\n\r\n ctx.moveTo(firstPart.startPoint.x, firstPart.startPoint.y);\r\n\r\n strokeParts.forEach((strokePart) => {\r\n const { endPoint } = strokePart;\r\n ctx.lineTo(endPoint.x, endPoint.y);\r\n });\r\n\r\n ctx.stroke();\r\n }\r\n}\r\n"],"names":["getEuclidean","p1","p2","getUnitVector","startPoint","endPoint","length","dirVect","StrokeManager","canvas","handler","clientX","clientY","rect","e","touch","touches","nextTouch","strokePart","Manager","canvasWidth","canvasHeight","bsr","dpr","width","height","pixelRatio","ctx","tool","PenTool","color","strokeParts","firstPart","EraserTool","handleOpts","halfWidth","isEnd","unitVect","currentPoint","i","nextPoint","lastPart","colorName","baseHues","parse","cstr","m","parts","alpha","space","names","base","size","isShort","name","isRGB","x","value","obj","HighlighterTool","opacity"],"mappings":"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","x_google_ignoreList":[5,6,7]} \ No newline at end of file +{"version":3,"file":"index.umd.js","sources":["../src/util.ts","../src/StrokeManager.ts","../src/Manager.ts","../src/tools/PenTool.ts","../src/tools/EraserTool.ts","../node_modules/color-name/index.js","../node_modules/color-parse/index.mjs","../node_modules/color-alpha/index.mjs","../src/tools/HighlighterTool.ts"],"sourcesContent":["import { IPoint } from \"./types\";\n\n/**\n * Get the distance between two points\n * @param p1\n * @param p2\n * @returns number\n */\nexport function getEuclidean(p1: IPoint, p2: IPoint): number {\n return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\n}\n\n/**\n * Gets the unit vector representing the vector from start\n * point to end point with a length of 1.\n * @param startPoint\n * @param endPoint\n * @returns IPoint\n */\nexport function getUnitVector(startPoint: IPoint, endPoint: IPoint): IPoint {\n const length = getEuclidean(startPoint, endPoint);\n\n const dirVect = {\n x: endPoint.x - startPoint.x,\n y: endPoint.y - startPoint.y,\n };\n\n const unitVect: IPoint = {\n x: dirVect.x / length,\n y: dirVect.y / length,\n };\n\n return unitVect;\n}\n","import { IPoint, IStrokePart } from \"./types\";\nimport { getEuclidean } from \"./util\";\n\nexport interface IOnStrokePartHandler {\n (strokePart: IStrokePart): void;\n}\n\nexport interface ITouch {\n id: number;\n position: IPoint;\n}\n\nexport class StrokeManager {\n // reference to canvas element\n private canvas: HTMLCanvasElement;\n // holds last touch point in a drag\n private lastTouch: ITouch | null;\n // value indicates how sensitive the stroke detection is higher is better\n private sensitivity: number;\n // holds all of the last emitted stroke parts in a drag\n private lastStrokeParts: IStrokePart[];\n // the handlers listening for new strokes\n private onStrokePartHandlers: IOnStrokePartHandler[];\n\n constructor(canvas: HTMLCanvasElement) {\n this.canvas = canvas;\n this.lastTouch = null;\n this.sensitivity = 20.0;\n this.lastStrokeParts = [];\n this.onStrokePartHandlers = [];\n\n this.onTouchStart = this.onTouchStart.bind(this);\n this.onTouchEnd = this.onTouchEnd.bind(this);\n this.onTouchCancel = this.onTouchCancel.bind(this);\n this.onTouchMove = this.onTouchMove.bind(this);\n this.destroy = this.destroy.bind(this);\n this.getRelativePosition = this.getRelativePosition.bind(this);\n\n this.canvas.addEventListener(\"touchstart\", this.onTouchStart, {\n passive: false,\n });\n this.canvas.addEventListener(\"touchend\", this.onTouchEnd, {\n passive: false,\n });\n this.canvas.addEventListener(\"touchcancel\", this.onTouchCancel, {\n passive: false,\n });\n this.canvas.addEventListener(\"touchmove\", this.onTouchMove, {\n passive: false,\n });\n }\n\n /**\n * Registers a handler to be fired on a new stroke part\n * @param handler\n */\n public onStrokePart(handler: IOnStrokePartHandler): void {\n this.onStrokePartHandlers.push(handler);\n }\n\n /**\n * Removes all active listeners\n */\n public destroy(): void {\n this.onStrokePartHandlers = [];\n this.lastStrokeParts = [];\n this.canvas.removeEventListener(\"touchstart\", this.onTouchStart);\n this.canvas.removeEventListener(\"touchend\", this.onTouchEnd);\n this.canvas.removeEventListener(\"touchcancel\", this.onTouchCancel);\n this.canvas.removeEventListener(\"touchmove\", this.onTouchMove);\n }\n\n /**\n * Get relative position to canvas\n * @param clientX\n * @param clientY\n * @returns IPoint\n */\n private getRelativePosition(clientX: number, clientY: number): IPoint {\n const rect = this.canvas.getBoundingClientRect();\n\n return {\n x: clientX - rect.left,\n y: clientY - rect.top,\n };\n }\n\n /**\n * Creates a new touch if one does not\n * already exist\n * @param e\n */\n private onTouchStart(e: TouchEvent): void {\n e.preventDefault();\n\n // if there is an ongoing touch, ignore this event\n if (this.lastTouch) {\n return;\n }\n\n const touches: TouchList = e.changedTouches;\n\n // only get the first touch\n const touch = touches.item(0);\n\n // save the touch\n this.lastTouch = {\n id: touch.identifier,\n position: this.getRelativePosition(touch.clientX, touch.clientY),\n };\n }\n\n /**\n * Creates a line from last touch to current touch\n * point and emits event. Does no-op if no existing touch\n * @param e\n */\n private onTouchMove(e: TouchEvent): void {\n e.preventDefault();\n\n // if no last touch... something is wrong\n if (!this.lastTouch) {\n return;\n }\n\n const touches: TouchList = e.changedTouches;\n\n // find the current touch we are tracking\n const touch: Touch = Array.from(touches).find((touch) => {\n return touch.identifier === this.lastTouch.id;\n });\n\n // if the touch was not one we were tracking,\n // ignore and no-op\n if (!touch) {\n return;\n }\n\n const nextTouch: ITouch = {\n id: touch.identifier,\n position: this.getRelativePosition(touch.clientX, touch.clientY),\n };\n\n // If sensitivity setting has been set,\n // check if this point is far enough from last\n // touch to be drawn\n if (\n this.sensitivity &&\n getEuclidean(nextTouch.position, this.lastTouch.position) <\n 10.0 / this.sensitivity\n ) {\n return;\n }\n\n const strokePart: IStrokePart = {\n endPoint: nextTouch.position,\n startPoint: this.lastTouch.position,\n isStart: this.lastStrokeParts.length === 0,\n isEnd: false,\n };\n\n this.onStrokePartHandlers.forEach((handler) => {\n handler(strokePart);\n });\n\n // save this touch as last touch\n this.lastTouch = nextTouch;\n this.lastStrokeParts.push(strokePart);\n }\n\n /**\n * Draws a line from last point to final point. Removes\n * the reference to last touch point.\n * @param e\n */\n private onTouchEnd(e: TouchEvent): void {\n e.preventDefault();\n\n // if no last touch... something is wrong\n if (!this.lastTouch) {\n return;\n }\n\n const touches: TouchList = e.changedTouches;\n\n // find the current touch we are tracking\n const touch: Touch = Array.from(touches).find((touch) => {\n return touch.identifier === this.lastTouch.id;\n });\n\n // if the touch was not one we were tracking,\n // ignore and no-op\n if (!touch) {\n return;\n }\n\n const endPoint = this.getRelativePosition(touch.clientX, touch.clientY);\n\n const strokePart: IStrokePart = {\n startPoint: this.lastTouch.position,\n endPoint,\n isStart: false,\n isEnd: true,\n };\n\n this.onStrokePartHandlers.forEach((handler) => {\n handler(strokePart);\n });\n\n this.lastTouch = null;\n this.lastStrokeParts = [];\n }\n\n /**\n * Removes the current last touch point\n * @param e\n */\n private onTouchCancel(e: TouchEvent): void {\n e.preventDefault();\n this.lastTouch = null;\n this.lastStrokeParts = [];\n }\n}\n","import { IStrokePart, ITool } from \"./types\";\nimport { StrokeManager } from \"./StrokeManager\";\n\nexport class Manager {\n // reference to the canvas\n private canvas: HTMLCanvasElement;\n // reference to stroke manager\n private strokeManager: StrokeManager;\n // holds the pixel ratio between canvas backing\n // store and device ratio (used for hi fi displays)\n private pixelRatio: number;\n // the width of the canvas\n private canvasWidth: number;\n // the height of the canvas\n private canvasHeight: number;\n // holds a reference to next animation frame\n private nextAnimationFrame: number;\n // the currently selected tool\n private currentTool: ITool | null;\n // holds stroke parts for ongoing stroke\n private currentStroke: IStrokePart[];\n // the state of the canvas (not including ongoing stroke)\n private canvasState: ImageData | null;\n // indicates whether changes have occured that require redraw\n private shouldDraw: boolean;\n // indicates whether canvas should commit its next draw state to current state\n private shouldCommit: boolean;\n\n constructor(\n canvas: HTMLCanvasElement,\n canvasWidth: number,\n canvasHeight: number,\n ) {\n this.canvas = canvas;\n this.canvasWidth = canvasWidth;\n this.canvasHeight = canvasHeight;\n this.currentTool = null;\n this.currentStroke = [];\n this.strokeManager = new StrokeManager(canvas);\n this.canvasState = null;\n this.shouldDraw = false;\n this.shouldCommit = false;\n\n // find pixel ratio relative to backing store and device ratio\n const bsr = (canvas.getContext(\"2d\") as any).backingStorePixelRatio || 1;\n const dpr = window.devicePixelRatio || 1;\n this.pixelRatio = dpr / bsr;\n\n this.setCanvasSize = this.setCanvasSize.bind(this);\n this.setTool = this.setTool.bind(this);\n this.destroy = this.destroy.bind(this);\n this.clear = this.clear.bind(this);\n this.draw = this.draw.bind(this);\n this.onStrokePart = this.onStrokePart.bind(this);\n\n // schedule animation frame loop\n this.nextAnimationFrame = window.requestAnimationFrame(this.draw);\n // set up listener for new stroke part\n this.strokeManager.onStrokePart(this.onStrokePart);\n\n this.setCanvasSize(canvasWidth, canvasHeight);\n }\n\n /**\n * Sets the canvas desired width and height and sets transform\n * for hifi displays\n * @param width\n * @param height\n */\n public setCanvasSize(width: number, height: number): void {\n this.canvasWidth = width;\n this.canvasHeight = height;\n\n const { canvas, canvasWidth, canvasHeight, pixelRatio } = this;\n\n const ctx = canvas.getContext(\"2d\");\n\n // appropriately scale canvas to map to device ratio\n canvas.width = canvasWidth * pixelRatio;\n canvas.height = canvasHeight * pixelRatio;\n canvas.style.width = canvasWidth + \"px\";\n canvas.style.height = canvasHeight + \"px\";\n ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);\n }\n\n /**\n * Sets the current tool for the manager\n * @param tool\n */\n public setTool(tool: ITool): void {\n this.currentTool = tool;\n }\n\n /**\n * Remove all event listeners\n */\n public destroy(): void {\n // cancel animation loop\n window.cancelAnimationFrame(this.nextAnimationFrame);\n // remove all listeners on stroke manager\n this.strokeManager.destroy();\n }\n\n /**\n * Clears the canvas\n */\n public clear(): void {\n this.canvasState = null;\n this.currentStroke = [];\n this.shouldDraw = true;\n this.shouldCommit = true;\n }\n\n /**\n * Adds a new stroke part to the nextStrokes\n * array\n * @param strokePart\n */\n private onStrokePart(strokePart: IStrokePart): void {\n this.currentStroke.push(strokePart);\n\n this.shouldDraw = true;\n\n if (strokePart.isEnd) {\n this.shouldCommit = true;\n }\n }\n\n /**\n * Draws a frame\n */\n private draw(): void {\n // schedule next draw\n this.nextAnimationFrame = window.requestAnimationFrame(this.draw);\n\n const ctx = this.canvas.getContext(\"2d\");\n\n if (!this.shouldDraw) {\n return;\n }\n\n // clear canvas\n ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);\n\n // draw current state\n if (this.canvasState) {\n ctx.putImageData(this.canvasState, 0, 0);\n }\n\n // if a tool has been selected and there are\n // pending strokes, draw them\n if (this.currentTool && this.currentStroke.length) {\n ctx.save();\n this.currentTool.draw(ctx, this.currentStroke);\n ctx.restore();\n }\n\n // if all changes have been made for current stroke,\n // save it as the new canvas state\n if (this.shouldCommit) {\n this.canvasState = ctx.getImageData(\n 0,\n 0,\n this.canvasWidth * this.pixelRatio,\n this.canvasHeight * this.pixelRatio,\n );\n this.currentStroke = [];\n this.shouldCommit = false;\n }\n\n this.shouldDraw = false;\n }\n}\n","import { IStrokePart } from \"../types\";\n\nexport class PenTool {\n readonly color: string;\n readonly width: number;\n\n constructor(color: string = \"red\", width: number = 3) {\n this.color = color;\n this.width = width;\n }\n\n /**\n * Draws a \"pen stroke\" for all line segments\n * @param ctx\n * @param strokeParts\n */\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\n const firstPart = strokeParts[0];\n\n ctx.beginPath();\n\n ctx.lineWidth = this.width;\n ctx.strokeStyle = this.color;\n ctx.lineCap = \"round\";\n ctx.lineJoin = \"round\";\n\n ctx.moveTo(firstPart.startPoint.x, firstPart.startPoint.y);\n\n strokeParts.forEach((strokePart) => {\n const { endPoint } = strokePart;\n ctx.lineTo(endPoint.x, endPoint.y);\n });\n\n ctx.stroke();\n }\n}\n","import { IStrokePart, IPoint } from \"../types\";\nimport { getUnitVector, getEuclidean } from \"../util\";\n\nexport interface IHandleOptions {\n hide: boolean;\n strokeWidth: number;\n fillColor: string;\n strokeColor: string;\n}\n\nexport class EraserTool {\n readonly width: number;\n readonly handleOpts: IHandleOptions;\n\n constructor(width: number = 10, handleOpts?: Partial) {\n this.width = width;\n\n handleOpts = handleOpts || {};\n\n this.handleOpts = {\n hide: handleOpts.hide || false,\n strokeWidth: handleOpts.strokeWidth || 2,\n fillColor: handleOpts.fillColor || \"white\",\n strokeColor: handleOpts.strokeColor || \"black\",\n };\n }\n\n /**\n * Draws an \"eraser stroke\" for all line segments\n * @param ctx\n * @param strokeParts\n */\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\n const { handleOpts } = this;\n const halfWidth = this.width / 2.0;\n\n strokeParts.forEach((strokePart) => {\n const { startPoint, endPoint, isEnd } = strokePart;\n\n const length = getEuclidean(startPoint, endPoint);\n const unitVect: IPoint = getUnitVector(startPoint, endPoint);\n let currentPoint: IPoint = startPoint;\n let i = 0;\n\n // clear all the way along the drag\n while (i < length) {\n const nextPoint: IPoint = {\n x: currentPoint.x + unitVect.x,\n y: currentPoint.y + unitVect.y,\n };\n\n ctx.clearRect(\n nextPoint.x - halfWidth,\n nextPoint.y - halfWidth,\n this.width,\n this.width,\n );\n\n i++;\n currentPoint = nextPoint;\n }\n });\n\n const lastPart = strokeParts[strokeParts.length - 1];\n\n // if the end is not the last part, then draw\n // the tool indicator at the endpoint\n if (!lastPart.isEnd && !handleOpts.hide) {\n ctx.strokeStyle = handleOpts.strokeColor;\n ctx.fillStyle = handleOpts.fillColor;\n\n ctx.fillRect(\n lastPart.endPoint.x - halfWidth,\n lastPart.endPoint.y - halfWidth,\n this.width,\n this.width,\n );\n\n ctx.strokeRect(\n lastPart.endPoint.x - halfWidth + 0.5,\n lastPart.endPoint.y - halfWidth + 0.5,\n this.width - 1,\n this.width - 1,\n );\n }\n }\n}\n","'use strict'\r\n\r\nmodule.exports = {\r\n\t\"aliceblue\": [240, 248, 255],\r\n\t\"antiquewhite\": [250, 235, 215],\r\n\t\"aqua\": [0, 255, 255],\r\n\t\"aquamarine\": [127, 255, 212],\r\n\t\"azure\": [240, 255, 255],\r\n\t\"beige\": [245, 245, 220],\r\n\t\"bisque\": [255, 228, 196],\r\n\t\"black\": [0, 0, 0],\r\n\t\"blanchedalmond\": [255, 235, 205],\r\n\t\"blue\": [0, 0, 255],\r\n\t\"blueviolet\": [138, 43, 226],\r\n\t\"brown\": [165, 42, 42],\r\n\t\"burlywood\": [222, 184, 135],\r\n\t\"cadetblue\": [95, 158, 160],\r\n\t\"chartreuse\": [127, 255, 0],\r\n\t\"chocolate\": [210, 105, 30],\r\n\t\"coral\": [255, 127, 80],\r\n\t\"cornflowerblue\": [100, 149, 237],\r\n\t\"cornsilk\": [255, 248, 220],\r\n\t\"crimson\": [220, 20, 60],\r\n\t\"cyan\": [0, 255, 255],\r\n\t\"darkblue\": [0, 0, 139],\r\n\t\"darkcyan\": [0, 139, 139],\r\n\t\"darkgoldenrod\": [184, 134, 11],\r\n\t\"darkgray\": [169, 169, 169],\r\n\t\"darkgreen\": [0, 100, 0],\r\n\t\"darkgrey\": [169, 169, 169],\r\n\t\"darkkhaki\": [189, 183, 107],\r\n\t\"darkmagenta\": [139, 0, 139],\r\n\t\"darkolivegreen\": [85, 107, 47],\r\n\t\"darkorange\": [255, 140, 0],\r\n\t\"darkorchid\": [153, 50, 204],\r\n\t\"darkred\": [139, 0, 0],\r\n\t\"darksalmon\": [233, 150, 122],\r\n\t\"darkseagreen\": [143, 188, 143],\r\n\t\"darkslateblue\": [72, 61, 139],\r\n\t\"darkslategray\": [47, 79, 79],\r\n\t\"darkslategrey\": [47, 79, 79],\r\n\t\"darkturquoise\": [0, 206, 209],\r\n\t\"darkviolet\": [148, 0, 211],\r\n\t\"deeppink\": [255, 20, 147],\r\n\t\"deepskyblue\": [0, 191, 255],\r\n\t\"dimgray\": [105, 105, 105],\r\n\t\"dimgrey\": [105, 105, 105],\r\n\t\"dodgerblue\": [30, 144, 255],\r\n\t\"firebrick\": [178, 34, 34],\r\n\t\"floralwhite\": [255, 250, 240],\r\n\t\"forestgreen\": [34, 139, 34],\r\n\t\"fuchsia\": [255, 0, 255],\r\n\t\"gainsboro\": [220, 220, 220],\r\n\t\"ghostwhite\": [248, 248, 255],\r\n\t\"gold\": [255, 215, 0],\r\n\t\"goldenrod\": [218, 165, 32],\r\n\t\"gray\": [128, 128, 128],\r\n\t\"green\": [0, 128, 0],\r\n\t\"greenyellow\": [173, 255, 47],\r\n\t\"grey\": [128, 128, 128],\r\n\t\"honeydew\": [240, 255, 240],\r\n\t\"hotpink\": [255, 105, 180],\r\n\t\"indianred\": [205, 92, 92],\r\n\t\"indigo\": [75, 0, 130],\r\n\t\"ivory\": [255, 255, 240],\r\n\t\"khaki\": [240, 230, 140],\r\n\t\"lavender\": [230, 230, 250],\r\n\t\"lavenderblush\": [255, 240, 245],\r\n\t\"lawngreen\": [124, 252, 0],\r\n\t\"lemonchiffon\": [255, 250, 205],\r\n\t\"lightblue\": [173, 216, 230],\r\n\t\"lightcoral\": [240, 128, 128],\r\n\t\"lightcyan\": [224, 255, 255],\r\n\t\"lightgoldenrodyellow\": [250, 250, 210],\r\n\t\"lightgray\": [211, 211, 211],\r\n\t\"lightgreen\": [144, 238, 144],\r\n\t\"lightgrey\": [211, 211, 211],\r\n\t\"lightpink\": [255, 182, 193],\r\n\t\"lightsalmon\": [255, 160, 122],\r\n\t\"lightseagreen\": [32, 178, 170],\r\n\t\"lightskyblue\": [135, 206, 250],\r\n\t\"lightslategray\": [119, 136, 153],\r\n\t\"lightslategrey\": [119, 136, 153],\r\n\t\"lightsteelblue\": [176, 196, 222],\r\n\t\"lightyellow\": [255, 255, 224],\r\n\t\"lime\": [0, 255, 0],\r\n\t\"limegreen\": [50, 205, 50],\r\n\t\"linen\": [250, 240, 230],\r\n\t\"magenta\": [255, 0, 255],\r\n\t\"maroon\": [128, 0, 0],\r\n\t\"mediumaquamarine\": [102, 205, 170],\r\n\t\"mediumblue\": [0, 0, 205],\r\n\t\"mediumorchid\": [186, 85, 211],\r\n\t\"mediumpurple\": [147, 112, 219],\r\n\t\"mediumseagreen\": [60, 179, 113],\r\n\t\"mediumslateblue\": [123, 104, 238],\r\n\t\"mediumspringgreen\": [0, 250, 154],\r\n\t\"mediumturquoise\": [72, 209, 204],\r\n\t\"mediumvioletred\": [199, 21, 133],\r\n\t\"midnightblue\": [25, 25, 112],\r\n\t\"mintcream\": [245, 255, 250],\r\n\t\"mistyrose\": [255, 228, 225],\r\n\t\"moccasin\": [255, 228, 181],\r\n\t\"navajowhite\": [255, 222, 173],\r\n\t\"navy\": [0, 0, 128],\r\n\t\"oldlace\": [253, 245, 230],\r\n\t\"olive\": [128, 128, 0],\r\n\t\"olivedrab\": [107, 142, 35],\r\n\t\"orange\": [255, 165, 0],\r\n\t\"orangered\": [255, 69, 0],\r\n\t\"orchid\": [218, 112, 214],\r\n\t\"palegoldenrod\": [238, 232, 170],\r\n\t\"palegreen\": [152, 251, 152],\r\n\t\"paleturquoise\": [175, 238, 238],\r\n\t\"palevioletred\": [219, 112, 147],\r\n\t\"papayawhip\": [255, 239, 213],\r\n\t\"peachpuff\": [255, 218, 185],\r\n\t\"peru\": [205, 133, 63],\r\n\t\"pink\": [255, 192, 203],\r\n\t\"plum\": [221, 160, 221],\r\n\t\"powderblue\": [176, 224, 230],\r\n\t\"purple\": [128, 0, 128],\r\n\t\"rebeccapurple\": [102, 51, 153],\r\n\t\"red\": [255, 0, 0],\r\n\t\"rosybrown\": [188, 143, 143],\r\n\t\"royalblue\": [65, 105, 225],\r\n\t\"saddlebrown\": [139, 69, 19],\r\n\t\"salmon\": [250, 128, 114],\r\n\t\"sandybrown\": [244, 164, 96],\r\n\t\"seagreen\": [46, 139, 87],\r\n\t\"seashell\": [255, 245, 238],\r\n\t\"sienna\": [160, 82, 45],\r\n\t\"silver\": [192, 192, 192],\r\n\t\"skyblue\": [135, 206, 235],\r\n\t\"slateblue\": [106, 90, 205],\r\n\t\"slategray\": [112, 128, 144],\r\n\t\"slategrey\": [112, 128, 144],\r\n\t\"snow\": [255, 250, 250],\r\n\t\"springgreen\": [0, 255, 127],\r\n\t\"steelblue\": [70, 130, 180],\r\n\t\"tan\": [210, 180, 140],\r\n\t\"teal\": [0, 128, 128],\r\n\t\"thistle\": [216, 191, 216],\r\n\t\"tomato\": [255, 99, 71],\r\n\t\"turquoise\": [64, 224, 208],\r\n\t\"violet\": [238, 130, 238],\r\n\t\"wheat\": [245, 222, 179],\r\n\t\"white\": [255, 255, 255],\r\n\t\"whitesmoke\": [245, 245, 245],\r\n\t\"yellow\": [255, 255, 0],\r\n\t\"yellowgreen\": [154, 205, 50]\r\n};\r\n","/**\n * @module color-parse\n */\nimport names from 'color-name'\n\nexport default parse\n\n/**\n * Base hues\n * http://dev.w3.org/csswg/css-color/#typedef-named-hue\n */\n//FIXME: use external hue detector\nvar baseHues = {\n\tred: 0,\n\torange: 60,\n\tyellow: 120,\n\tgreen: 180,\n\tblue: 240,\n\tpurple: 300\n}\n\n/**\n * Parse color from the string passed\n *\n * @return {Object} A space indicator `space`, an array `values` and `alpha`\n */\nfunction parse(cstr) {\n\tvar m, parts = [], alpha = 1, space\n\n\tif (typeof cstr === 'string') {\n\t\tcstr = cstr.toLowerCase();\n\n\t\t//keyword\n\t\tif (names[cstr]) {\n\t\t\tparts = names[cstr].slice()\n\t\t\tspace = 'rgb'\n\t\t}\n\n\t\t//reserved words\n\t\telse if (cstr === 'transparent') {\n\t\t\talpha = 0\n\t\t\tspace = 'rgb'\n\t\t\tparts = [0, 0, 0]\n\t\t}\n\n\t\t//hex\n\t\telse if (/^#[A-Fa-f0-9]+$/.test(cstr)) {\n\t\t\tvar base = cstr.slice(1)\n\t\t\tvar size = base.length\n\t\t\tvar isShort = size <= 4\n\t\t\talpha = 1\n\n\t\t\tif (isShort) {\n\t\t\t\tparts = [\n\t\t\t\t\tparseInt(base[0] + base[0], 16),\n\t\t\t\t\tparseInt(base[1] + base[1], 16),\n\t\t\t\t\tparseInt(base[2] + base[2], 16)\n\t\t\t\t]\n\t\t\t\tif (size === 4) {\n\t\t\t\t\talpha = parseInt(base[3] + base[3], 16) / 255\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tparts = [\n\t\t\t\t\tparseInt(base[0] + base[1], 16),\n\t\t\t\t\tparseInt(base[2] + base[3], 16),\n\t\t\t\t\tparseInt(base[4] + base[5], 16)\n\t\t\t\t]\n\t\t\t\tif (size === 8) {\n\t\t\t\t\talpha = parseInt(base[6] + base[7], 16) / 255\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!parts[0]) parts[0] = 0\n\t\t\tif (!parts[1]) parts[1] = 0\n\t\t\tif (!parts[2]) parts[2] = 0\n\n\t\t\tspace = 'rgb'\n\t\t}\n\n\t\t//color space\n\t\telse if (m = /^((?:rgb|hs[lvb]|hwb|cmyk?|xy[zy]|gray|lab|lchu?v?|[ly]uv|lms)a?)\\s*\\(([^\\)]*)\\)/.exec(cstr)) {\n\t\t\tvar name = m[1]\n\t\t\tvar isRGB = name === 'rgb'\n\t\t\tvar base = name.replace(/a$/, '')\n\t\t\tspace = base\n\t\t\tvar size = base === 'cmyk' ? 4 : base === 'gray' ? 1 : 3\n\t\t\tparts = m[2].trim()\n\t\t\t\t.split(/\\s*[,\\/]\\s*|\\s+/)\n\t\t\t\t.map(function (x, i) {\n\t\t\t\t\t//\n\t\t\t\t\tif (/%$/.test(x)) {\n\t\t\t\t\t\t//alpha\n\t\t\t\t\t\tif (i === size) return parseFloat(x) / 100\n\t\t\t\t\t\t//rgb\n\t\t\t\t\t\tif (base === 'rgb') return parseFloat(x) * 255 / 100\n\t\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t\t}\n\t\t\t\t\t//hue\n\t\t\t\t\telse if (base[i] === 'h') {\n\t\t\t\t\t\t//\n\t\t\t\t\t\tif (/deg$/.test(x)) {\n\t\t\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//\n\t\t\t\t\t\telse if (baseHues[x] !== undefined) {\n\t\t\t\t\t\t\treturn baseHues[x]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn parseFloat(x)\n\t\t\t\t})\n\n\t\t\tif (name === base) parts.push(1)\n\t\t\talpha = (isRGB) ? 1 : (parts[size] === undefined) ? 1 : parts[size]\n\t\t\tparts = parts.slice(0, size)\n\t\t}\n\n\t\t//named channels case\n\t\telse if (cstr.length > 10 && /[0-9](?:\\s|\\/)/.test(cstr)) {\n\t\t\tparts = cstr.match(/([0-9]+)/g).map(function (value) {\n\t\t\t\treturn parseFloat(value)\n\t\t\t})\n\n\t\t\tspace = cstr.match(/([a-z])/ig).join('').toLowerCase()\n\t\t}\n\t}\n\n\t//numeric case\n\telse if (!isNaN(cstr)) {\n\t\tspace = 'rgb'\n\t\tparts = [cstr >>> 16, (cstr & 0x00ff00) >>> 8, cstr & 0x0000ff]\n\t}\n\n\t//array-like\n\telse if (Array.isArray(cstr) || cstr.length) {\n\t\tparts = [cstr[0], cstr[1], cstr[2]]\n\t\tspace = 'rgb'\n\t\talpha = cstr.length === 4 ? cstr[3] : 1\n\t}\n\n\t//object case - detects css cases of rgb and hsl\n\telse if (cstr instanceof Object) {\n\t\tif (cstr.r != null || cstr.red != null || cstr.R != null) {\n\t\t\tspace = 'rgb'\n\t\t\tparts = [\n\t\t\t\tcstr.r || cstr.red || cstr.R || 0,\n\t\t\t\tcstr.g || cstr.green || cstr.G || 0,\n\t\t\t\tcstr.b || cstr.blue || cstr.B || 0\n\t\t\t]\n\t\t}\n\t\telse {\n\t\t\tspace = 'hsl'\n\t\t\tparts = [\n\t\t\t\tcstr.h || cstr.hue || cstr.H || 0,\n\t\t\t\tcstr.s || cstr.saturation || cstr.S || 0,\n\t\t\t\tcstr.l || cstr.lightness || cstr.L || cstr.b || cstr.brightness\n\t\t\t]\n\t\t}\n\n\t\talpha = cstr.a || cstr.alpha || cstr.opacity || 1\n\n\t\tif (cstr.opacity != null) alpha /= 100\n\t}\n\n\treturn {\n\t\tspace: space,\n\t\tvalues: parts,\n\t\talpha: alpha\n\t}\n}\n","/**\r\n * @module color-alpha\r\n */\r\nimport parse from 'color-parse';\r\n\r\nexport default function alpha (color, value) {\r\n\tvar obj = parse(color);\r\n\r\n\tif (value == null) value = obj.alpha;\r\n\r\n\t//catch percent\r\n\tif (obj.space[0] === 'h') {\r\n\t\treturn obj.space + ['a(', obj.values[0], ',', obj.values[1], '%,', obj.values[2], '%,', value, ')'].join('');\r\n\t}\r\n\r\n\treturn obj.space + ['a(', obj.values, ',', value, ')'].join('');\r\n}\r\n","import alpha from \"color-alpha\";\n\nimport { IStrokePart } from \"../types\";\n\nexport class HighlighterTool {\n readonly color: string;\n readonly width: number;\n\n constructor(\n color: string = \"yellow\",\n width: number = 8,\n opacity: Number = 0.3,\n ) {\n this.width = width;\n\n // calculate color w/ opacity\n this.color = alpha(color, 0.4);\n }\n\n /**\n * Draws a \"highlighter stroke\" for all line segments\n * @param ctx\n * @param strokeParts\n */\n public draw(ctx: CanvasRenderingContext2D, strokeParts: IStrokePart[]): void {\n const firstPart = strokeParts[0];\n\n ctx.beginPath();\n\n ctx.lineWidth = this.width;\n ctx.strokeStyle = this.color;\n ctx.lineCap = \"butt\";\n ctx.miterLimit = 1;\n\n ctx.moveTo(firstPart.startPoint.x, firstPart.startPoint.y);\n\n strokeParts.forEach((strokePart) => {\n const { endPoint } = strokePart;\n ctx.lineTo(endPoint.x, endPoint.y);\n });\n\n ctx.stroke();\n }\n}\n"],"names":["getEuclidean","p1","p2","getUnitVector","startPoint","endPoint","length","dirVect","StrokeManager","canvas","handler","clientX","clientY","rect","e","touch","touches","nextTouch","strokePart","Manager","canvasWidth","canvasHeight","bsr","dpr","width","height","pixelRatio","ctx","tool","PenTool","color","strokeParts","firstPart","EraserTool","handleOpts","halfWidth","isEnd","unitVect","currentPoint","i","nextPoint","lastPart","colorName","baseHues","parse","cstr","m","parts","alpha","space","names","base","size","isShort","name","isRGB","x","value","obj","HighlighterTool","opacity"],"mappings":"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","x_google_ignoreList":[5,6,7]} \ No newline at end of file