import { getRectOfNodes, getBoundsofRects } from '../../utils/graph'; import { Node, Rect } from '../../types'; import MiniMapNode from './MiniMapNode'; import { computed, defineComponent, HTMLAttributes, PropType } from 'vue'; import store from '../../store'; type StringFunc = (node: Node) => string; export interface MiniMapProps extends HTMLAttributes { nodeColor?: string | StringFunc; nodeStrokeColor?: string | StringFunc; nodeClassName?: string | StringFunc; nodeBorderRadius?: number; nodeStrokeWidth?: number; maskColor?: string; } declare const window: any; const defaultWidth = 200; const defaultHeight = 150; const MiniMap = defineComponent({ name: 'MiniMap', props: { nodeStrokeColor: { type: (String || Function) as PropType, required: false, default: '#555' }, nodeColor: { type: (String || Function) as PropType, required: false, default: '#fff' }, nodeClassName: { type: (String || Function) as PropType, required: false, default: '' }, nodeBorderRadius: { type: Number as PropType, required: false, default: 5 }, nodeStrokeWidth: { type: Number as PropType, required: false, default: 2 }, maskColor: { type: String as PropType, required: false, default: 'rgb(240, 242, 243, 0.7)' } }, setup(props, { attrs }: { attrs: Record }) { const pinia = store(); const transform = computed(() => pinia.transform); const mapClasses = ['revue-flow__minimap']; const elementWidth = computed(() => (attrs.style?.width || defaultWidth)! as number); const elementHeight = computed(() => (attrs.style?.height || defaultHeight)! as number); const nodeColorFunc = (props.nodeColor instanceof Function ? props.nodeColor : () => props.nodeColor) as StringFunc; const nodeStrokeColorFunc = ( props.nodeStrokeColor instanceof Function ? props.nodeStrokeColor : () => props.nodeStrokeColor ) as StringFunc; const nodeClassNameFunc = ( props.nodeClassName instanceof Function ? props.nodeClassName : () => props.nodeClassName ) as StringFunc; const hasNodes = computed(() => pinia.nodes && pinia.nodes.length); const bb = computed(() => getRectOfNodes(pinia.nodes)); const viewBB = computed(() => ({ x: -transform.value[0] / transform.value[2], y: -transform.value[1] / transform.value[2], width: pinia.width / transform.value[2], height: pinia.height / transform.value[2] })); const boundingRect = computed(() => (hasNodes.value ? getBoundsofRects(bb.value, viewBB.value) : viewBB.value)); const scaledWidth = computed(() => boundingRect.value.width / elementWidth.value); const scaledHeight = computed(() => boundingRect.value.height / elementHeight.value); const viewScale = computed(() => Math.max(scaledWidth.value, scaledHeight.value)); const viewWidth = computed(() => viewScale.value * elementWidth.value); const viewHeight = computed(() => viewScale.value * elementHeight.value); const offset = computed(() => 5 * viewScale.value); const x = computed(() => boundingRect.value.x - (viewWidth.value - boundingRect.value.width) / 2 - offset.value); const y = computed(() => boundingRect.value.y - (viewHeight.value - boundingRect.value.height) / 2 - offset.value); const width = computed(() => viewWidth.value + offset.value * 2); const height = computed(() => viewHeight.value + offset.value * 2); const shapeRendering = typeof window === 'undefined' || !!window.chrome ? 'crispEdges' : 'geometricPrecision'; return () => ( {pinia.nodes .filter((node) => !node.isHidden) .map((node) => ( ))} ); } }); export default MiniMap;