@@ -9,10 +9,15 @@ import {
99 OnPointerDownHandler ,
1010 OnDragHandler ,
1111} from "../canvas-event-target" ;
12- import { get_hovering_target , centerOf } from "../math" ;
12+ import {
13+ target_of_point ,
14+ centerOf ,
15+ edge_scrolling ,
16+ target_of_area ,
17+ } from "../math" ;
1318import { utils } from "@design-sdk/core" ;
1419import { LazyFrame } from "@code-editor/canvas/lazy-frame" ;
15- import { HudCustomRenderers , HudSurface } from "./hud-surface " ;
20+ import { HudCustomRenderers , HudSurface } from ".. /hud" ;
1621import type { Box , XY , CanvasTransform , XYWH } from "../types" ;
1722import type { FrameOptimizationFactors } from "../frame" ;
1823const designq = utils . query ;
@@ -89,7 +94,7 @@ export function Canvas({
8994 ...props
9095} : {
9196 viewbound : Box ;
92- onSelectNode ?: ( node ? : ReflectSceneNode ) => void ;
97+ onSelectNode ?: ( ... node : ReflectSceneNode [ ] ) => void ;
9398 onClearSelection ?: ( ) => void ;
9499} & CanvasCustomRenderers &
95100 CanvasState & {
@@ -131,6 +136,7 @@ export function Canvas({
131136 ? [ offset [ 0 ] / zoom , offset [ 1 ] / zoom ]
132137 : [ 0 , 0 ] ;
133138 const [ isPanning , setIsPanning ] = useState ( false ) ;
139+ const [ isDraggomg , setIsDragging ] = useState ( false ) ;
134140 const [ marquee , setMarquee ] = useState < XYWH > ( null ) ;
135141
136142 const cvtransform : CanvasTransform = {
@@ -151,17 +157,46 @@ export function Canvas({
151157 setHoveringLayer ( wshighlight ) ;
152158 } , [ highlightedLayer ] ) ;
153159
160+ // area selection hook
161+ useEffect ( ( ) => {
162+ if ( marquee ) {
163+ const area : XYWH = [
164+ marquee [ 0 ] / zoom ,
165+ marquee [ 1 ] / zoom ,
166+ marquee [ 2 ] / zoom ,
167+ marquee [ 3 ] / zoom ,
168+ ] ;
169+
170+ const selections = target_of_area ( {
171+ area,
172+ tree : nodes ,
173+ contain : false ,
174+ } ) ;
175+
176+ // https://stackoverflow.com/a/19746771
177+ const same =
178+ selectedNodes . length === selections ?. length &&
179+ selectedNodes . every ( ( value , index ) => value === selections [ index ] . id ) ;
180+
181+ if ( ! same ) {
182+ onSelectNode ( ...selections ) ;
183+ }
184+ }
185+ //
186+ } , [ marquee ] ) ;
187+
154188 const onPointerMove : OnPointerMoveHandler = ( state ) => {
155- if ( isPanning || isZooming ) {
189+ if ( isPanning || isZooming || isDraggomg ) {
156190 // don't perform hover calculation while transforming.
157191 return ;
158192 }
159- const hovering = get_hovering_target ( {
193+ const hovering = target_of_point ( {
160194 point : state . xy ,
161195 tree : nodes ,
162196 zoom : zoom ,
163197 offset : nonscaled_offset ,
164198 margin : LAYER_HOVER_HIT_MARGIN ,
199+ reverse : true ,
165200 } ) ;
166201
167202 if ( ! hovering ) {
@@ -223,27 +258,48 @@ export function Canvas({
223258 setOffset ( [ newx , newy ] ) ;
224259 } ;
225260
261+ const onDragStart : OnDragHandler = ( s ) => {
262+ onClearSelection ( ) ;
263+ setIsDragging ( true ) ;
264+ setHoveringLayer ( null ) ;
265+
266+ // set the marquee start point
267+ const [ x , y ] = s . initial ;
268+ const [ ox , oy ] = offset ;
269+ const [ x1 , y1 ] = [ x - ox , y - oy ] ;
270+ setMarquee ( [ x1 , y1 , 0 , 0 ] ) ;
271+ } ;
272+
226273 const onDrag : OnDragHandler = ( s ) => {
227- const [ x1 , y1 ] = s . initial ;
228- const [ x2 , y2 ] = [
274+ const [ ox , oy ] = offset ;
275+ const [ x , y ] = [
229276 // @ts -ignore
230277 s . event . clientX ,
231278 // @ts -ignore
232279 s . event . clientY ,
233280 ] ;
234281
235- const [ ox , oy ] = offset ;
236- const [ x , y , w , h ] = [
237- x1 - ox ,
238- y1 - oy ,
239- x2 - x1 , // w
240- y2 - y1 , // h
241- ] ;
242- setMarquee ( [ x , y , w , h ] ) ;
282+ const [ x1 , y1 ] = [ x - ox , y - oy ] ;
283+
284+ if ( marquee ) {
285+ const [ w , h ] = [
286+ x1 - marquee [ 0 ] , // w
287+ y1 - marquee [ 1 ] , // h
288+ ] ;
289+ setMarquee ( [ marquee [ 0 ] , marquee [ 1 ] , w , h ] ) ;
290+ }
291+
292+ // edge scrolling
293+ const [ cx , cy ] = [ x , y ] ;
294+ const [ dx , dy ] = edge_scrolling ( cx , cy , viewbound ) ;
295+ if ( dx || dy ) {
296+ setOffset ( [ ox + dx , oy + dy ] ) ;
297+ }
243298 } ;
244299
245300 const onDragEnd : OnDragHandler = ( s ) => {
246301 setMarquee ( null ) ;
302+ setIsDragging ( false ) ;
247303 } ;
248304
249305 const is_canvas_transforming = isPanning || isZooming ;
@@ -299,8 +355,8 @@ export function Canvas({
299355 onPointerMoveStart = { ( ) => { } }
300356 onPointerMoveEnd = { ( ) => { } }
301357 onPointerDown = { onPointerDown }
358+ onDragStart = { onDragStart }
302359 onDrag = { onDrag }
303- onDragStart = { ( ) => { } } // TODO:
304360 onDragEnd = { onDragEnd }
305361 >
306362 < HudSurface
@@ -363,7 +419,7 @@ function CanvasTransformRoot({
363419 width : 0 ,
364420 height : 0 ,
365421 willChange : "transform" ,
366- transform : `scale(${ scale } ) translateX (${ xy [ 0 ] } px) translateY( ${ xy [ 1 ] } px)` ,
422+ transform : `scale(${ scale } ) translate3d (${ xy [ 0 ] } px, ${ xy [ 1 ] } px, 0 )` ,
367423 isolation : "isolate" ,
368424 } }
369425 >
0 commit comments