-
-
Notifications
You must be signed in to change notification settings - Fork 46
Expand file tree
/
Copy pathMinimap.tsx
More file actions
83 lines (77 loc) · 2.18 KB
/
Minimap.tsx
File metadata and controls
83 lines (77 loc) · 2.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import * as React from 'react'
import { useCallback, useRef } from 'react'
import styled from 'styled-components'
import { useResizeObserver } from 'usehooks-ts'
import { Rect, Transform, Translate } from '../types'
import { px } from '../utils'
import { MiniNode } from './MiniNode'
import { MiniViewport } from './MiniViewport'
const Styles = styled.div<{ size: number }>`
position: absolute;
right: 24px;
bottom: 24px;
background: rgba(229, 234, 239, 0.65);
padding: 20px;
overflow: hidden;
border: 1px solid #b1b7ff;
border-radius: 8px;
box-sizing: border-box;
`
type Props = {
size: number
ratio: number
nodes: Rect[]
viewport: Rect
start(): Transform
translate: Translate
point(x: number, y: number): void
}
export function Minimap(props: Props) {
const ref = useRef<HTMLDivElement>(null)
const { width = 0 } = useResizeObserver({
// https://github.com/juliencrn/usehooks-ts/issues/663
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
ref: ref
})
const containerWidth = ref.current?.clientWidth || width
const scale = useCallback((v: number) => v * containerWidth, [containerWidth])
return <Styles
size={props.size}
style={{
width: px(props.size * props.ratio),
height: px(props.size)
}}
onPointerDown={(e: React.PointerEvent) => {
e.stopPropagation()
e.preventDefault()
}}
onDoubleClick={(e: React.MouseEvent) => {
e.stopPropagation()
e.preventDefault()
if (!ref.current) return
const box = ref.current.getBoundingClientRect()
const x = (e.clientX - box.left) / (props.size * props.ratio)
const y = (e.clientY - box.top) / (props.size * props.ratio)
props.point(x, y)
}}
ref={ref}
data-testid="minimap"
>
{containerWidth
? props.nodes.map((node, i) => <MiniNode
key={i}
left={scale(node.left)}
top={scale(node.top)}
width={scale(node.width)}
height={scale(node.height)}
/>)
: null}
<MiniViewport
{...props.viewport}
start={props.start}
containerWidth={containerWidth}
translate={props.translate}
/>
</Styles>
}