import { prefix, getControlTransform, getLineStyle, getProps, sign } from "./utils"; import { Renderer, MoveableManagerInterface, RenderDirections, } from "./types"; import { DIRECTION_INDEXES, DIRECTION_ROTATIONS, DIRECTIONS, DIRECTIONS4 } from "./consts"; import { IObject, throttle, getRad, getKeys } from "@daybrush/utils"; import { absDegree } from "./ables/Snappable"; export interface DirectionControlInfo { data: Record; classNames: string[]; dir: string; } export function renderDirectionControlsByInfos( moveable: MoveableManagerInterface>, ableName: string, renderDirections: DirectionControlInfo[], React: Renderer, ): any[] { const { renderPoses, rotation: rotationRad, direction, } = moveable.getState(); const { zoom, } = getProps(moveable.props, ableName as any); const degRotation = absDegree(rotationRad / Math.PI * 180); const directionMap: IObject = {}; const renderState = moveable.renderState; if (!renderState.renderDirectionMap) { renderState.renderDirectionMap = {}; } const renderDirectionMap = renderState.renderDirectionMap; renderDirections.forEach(({ dir }) => { directionMap[dir] = true; }); const directionSign = sign(direction); return renderDirections.map(({ data, classNames, dir }) => { const indexes = DIRECTION_INDEXES[dir]; if (!indexes || !directionMap[dir]) { return null; } renderDirectionMap[dir] = true; const directionRotation = (throttle(degRotation, 15) + directionSign * DIRECTION_ROTATIONS[dir] + 720) % 180; const dataAttrs: Record = {}; getKeys(data).forEach(name => { dataAttrs[`data-${name}`] = data[name]; }); return (
renderPoses[index]))}>
); }); } export function renderDirectionControls( moveable: MoveableManagerInterface>, defaultDirections: string[], ableName: string, React: Renderer, ): any[] { const { renderDirections: directions = defaultDirections, displayAroundControls, } = getProps(moveable.props, ableName as any); if (!directions) { return []; } const renderDirections = directions === true ? DIRECTIONS : directions; return [ ...(displayAroundControls ? renderAroundControls(moveable, React, ableName, renderDirections) : []), ...renderDirectionControlsByInfos( moveable, ableName, renderDirections.map(dir => { return { data: {}, classNames: [], dir, }; }), React, ), ]; } export function renderLine( React: Renderer, direction: string, pos1: number[], pos2: number[], zoom: number, key: number | string, ...classNames: string[] ): any { const rad = getRad(pos1, pos2); const rotation = direction ? (throttle(rad / Math.PI * 180, 15)) % 180 : -1; return
; } export function renderEdgeLines( React: Renderer, ableName: string, edge: true | string[], poses: number[][], zoom: number, ): any[] { const directions = edge === true ? DIRECTIONS4 : edge; return directions.map((direction, i) => { const [index1, index2] = DIRECTION_INDEXES[direction]; if (index2 == null) { return; } return renderLine(React, direction, poses[index1], poses[index2], zoom, `${ableName}Edge${i}`, ableName); }).filter(Boolean); } export function getRenderDirections(ableName: string) { return ( moveable: MoveableManagerInterface>, React: Renderer, ) => { const edge = getProps(moveable.props, ableName as any).edge; if (edge && (edge === true || edge.length)) { return [ ...renderEdgeLines( React, ableName, edge, moveable.getState().renderPoses, moveable.props.zoom!, ), ...renderDiagonalDirections(moveable, ableName, React), ]; } return renderAllDirections(moveable, ableName, React); }; } export function renderAllDirections( moveable: MoveableManagerInterface>, ableName: string, React: Renderer, ) { return renderDirectionControls(moveable, DIRECTIONS, ableName, React); } export function renderDiagonalDirections( moveable: MoveableManagerInterface>, ableName: string, React: Renderer, ): any[] { return renderDirectionControls(moveable, ["nw", "ne", "sw", "se"], ableName, React); } export function renderAroundControls( moveable: MoveableManagerInterface>, React: Renderer, ableName?: string, renderDirections?: string[], ): any[] { const renderState = moveable.renderState; if (!renderState.renderDirectionMap) { renderState.renderDirectionMap = {}; } const { renderPoses, rotation: rotationRad, direction, } = moveable.getState(); const renderDirectionMap = renderState.renderDirectionMap; const { zoom, } = moveable.props; const directionSign = sign(direction); const degRotation = rotationRad / Math.PI * 180; return (renderDirections || getKeys(renderDirectionMap)).map(dir => { const indexes = DIRECTION_INDEXES[dir]; if (!indexes) { return null; } const directionRotation = (throttle(degRotation, 15) + directionSign * DIRECTION_ROTATIONS[dir] + 720) % 180; const classNames: string[] = ["around-control"]; if (ableName) { classNames.push("direction", ableName); } return (
renderPoses[index]))}>
); }); }