import * as React from "react"; import { noop } from "lodash"; import { startDOMDrag, Point } from "tandem-common"; import { compose, pure, withHandlers, withState, lifecycle } from "recompose"; import { BasePickerProps } from "./picker.pc"; export enum GrabberAxis { X = 1, Y = X << 1 } export type Props = { grabberAxis: any; draw: any; onChange: any; onChangeComplete: any; getGraggerPoint: any; value: any; }; type InnerProps = { canvas: HTMLCanvasElement; setCanvas: any; grabberPoint: Point; setGrabberPoint: any; } & Props; export default compose( pure, withState(`canvas`, `setCanvas`, null), withState(`grabberPoint`, `setGrabberPoint`, null), withHandlers(() => { let _canvas: HTMLCanvasElement; return { onCanvas: ({ setCanvas, draw = noop }: InnerProps) => ( canvas: HTMLCanvasElement ) => { setCanvas((_canvas = canvas)); if (canvas) { // need to set immediate to ensure that canvas is actually mounted setImmediate(() => { const { width, height } = canvas.parentElement.getBoundingClientRect(); draw(canvas, width || 100, height || 100); }); } }, onMouseDown: ({ grabberAxis, setGrabberPoint, onChange, onChangeComplete }: InnerProps) => event => { const rect = _canvas.getBoundingClientRect(); const handleChange = callback => event => { const point = { left: grabberAxis & GrabberAxis.X ? Math.max( 0, Math.min(rect.width - 1, event.clientX - rect.left) ) : 0, top: grabberAxis & GrabberAxis.Y ? Math.max( 0, Math.min(rect.height - 1, event.clientY - rect.top) ) : 0 }; if (callback) { const imageData = _canvas .getContext("2d") .getImageData(point.left, point.top, 1, 1).data; callback(imageData); } setGrabberPoint(point); }; startDOMDrag( event, noop, handleChange(onChange), handleChange(onChangeComplete) ); } }; }), lifecycle({ componentDidUpdate({ setGrabberPoint, getGraggerPoint, draw, canvas, value }: InnerProps) { if (canvas && this.props.draw !== draw && this.props.draw) { setImmediate(() => { const { width, height } = canvas.parentElement.getBoundingClientRect(); this.props.draw(canvas, width, height); }); } if (canvas && this.props.value !== value) { setImmediate(() => { const { width, height } = canvas.parentElement.getBoundingClientRect(); setGrabberPoint(getGraggerPoint(this.props.value, width, height)); }); } } }), (Base: React.ComponentClass) => ({ onMouseDown, onCanvas, grabberAxis, draw, onChange, onChangeComplete, canvas, grabberPoint, ...rest }) => { return ( ); } );