@@ -48,6 +48,29 @@ export function MaskOverlay(props: MaskOverlayProps) {
4848 ) ;
4949 } ;
5050
51+ const currentMaskState = maskState ( ) ;
52+ const selected = selectedMask ( ) ;
53+
54+ return (
55+ < Show when = { selected && currentMaskState } >
56+ < MaskOverlayContent
57+ size = { props . size }
58+ maskState = { currentMaskState as ReturnType < typeof evaluateMask > }
59+ updateSegment = { updateSegment }
60+ projectHistory = { projectHistory }
61+ />
62+ </ Show >
63+ ) ;
64+ }
65+
66+ function MaskOverlayContent ( props : {
67+ size : { width : number ; height : number } ;
68+ maskState : ReturnType < typeof evaluateMask > ;
69+ updateSegment : ( fn : ( segment : MaskSegment ) => void ) => void ;
70+ projectHistory : ReturnType < typeof useEditorContext > [ "projectHistory" ] ;
71+ } ) {
72+ const { projectHistory, updateSegment } = props ;
73+
5174 function createMouseDownDrag < T > (
5275 setup : ( ) => T ,
5376 update : (
@@ -85,116 +108,106 @@ export function MaskOverlay(props: MaskOverlayProps) {
85108 } ;
86109 }
87110
111+ const state = ( ) => props . maskState ;
112+ const rect = ( ) => {
113+ const width = state ( ) . size . x * props . size . width ;
114+ const height = state ( ) . size . y * props . size . height ;
115+ const left = state ( ) . position . x * props . size . width - width / 2 ;
116+ const top = state ( ) . position . y * props . size . height - height / 2 ;
117+ return { width, height, left, top } ;
118+ } ;
119+
120+ const onMove = createMouseDownDrag (
121+ ( ) => ( {
122+ startPos : { ...state ( ) . position } ,
123+ } ) ,
124+ ( e , { startPos } , initialMouse ) => {
125+ const dx = ( e . clientX - initialMouse . x ) / props . size . width ;
126+ const dy = ( e . clientY - initialMouse . y ) / props . size . height ;
127+
128+ updateSegment ( ( s ) => {
129+ s . center . x = Math . max ( 0 , Math . min ( 1 , startPos . x + dx ) ) ;
130+ s . center . y = Math . max ( 0 , Math . min ( 1 , startPos . y + dy ) ) ;
131+ } ) ;
132+ } ,
133+ ) ;
134+
135+ const createResizeHandler = ( dirX : - 1 | 0 | 1 , dirY : - 1 | 0 | 1 ) => {
136+ return createMouseDownDrag (
137+ ( ) => ( {
138+ startPos : { ...state ( ) . position } ,
139+ startSize : { ...state ( ) . size } ,
140+ } ) ,
141+ ( e , { startPos, startSize } , initialMouse ) => {
142+ const dx = ( e . clientX - initialMouse . x ) / props . size . width ;
143+ const dy = ( e . clientY - initialMouse . y ) / props . size . height ;
144+
145+ updateSegment ( ( s ) => {
146+ if ( dirX !== 0 ) {
147+ const newWidth = Math . max ( 0.01 , startSize . x + dx * dirX ) ;
148+ s . size . x = newWidth ;
149+ s . center . x = startPos . x + dx / 2 ;
150+ }
151+
152+ if ( dirY !== 0 ) {
153+ const newHeight = Math . max ( 0.01 , startSize . y + dy * dirY ) ;
154+ s . size . y = newHeight ;
155+ s . center . y = startPos . y + dy / 2 ;
156+ }
157+ } ) ;
158+ } ,
159+ ) ;
160+ } ;
161+
88162 return (
89- < Show when = { selectedMask ( ) && maskState ( ) } >
90- { ( ) => {
91- const state = ( ) => maskState ( ) ! ;
92- const rect = ( ) => {
93- const width = state ( ) . size . x * props . size . width ;
94- const height = state ( ) . size . y * props . size . height ;
95- const left = state ( ) . position . x * props . size . width - width / 2 ;
96- const top = state ( ) . position . y * props . size . height - height / 2 ;
97- return { width, height, left, top } ;
98- } ;
99-
100- const onMove = createMouseDownDrag (
101- ( ) => ( {
102- startPos : { ...state ( ) . position } ,
103- } ) ,
104- ( e , { startPos } , initialMouse ) => {
105- const dx = ( e . clientX - initialMouse . x ) / props . size . width ;
106- const dy = ( e . clientY - initialMouse . y ) / props . size . height ;
107-
108- updateSegment ( ( s ) => {
109- s . center . x = Math . max ( 0 , Math . min ( 1 , startPos . x + dx ) ) ;
110- s . center . y = Math . max ( 0 , Math . min ( 1 , startPos . y + dy ) ) ;
111- } ) ;
112- } ,
113- ) ;
114-
115- const createResizeHandler = ( dirX : - 1 | 0 | 1 , dirY : - 1 | 0 | 1 ) => {
116- return createMouseDownDrag (
117- ( ) => ( {
118- startPos : { ...state ( ) . position } ,
119- startSize : { ...state ( ) . size } ,
120- } ) ,
121- ( e , { startPos, startSize } , initialMouse ) => {
122- const dx = ( e . clientX - initialMouse . x ) / props . size . width ;
123- const dy = ( e . clientY - initialMouse . y ) / props . size . height ;
124-
125- updateSegment ( ( s ) => {
126- if ( dirX !== 0 ) {
127- const newWidth = Math . max ( 0.01 , startSize . x + dx * dirX ) ;
128- s . size . x = newWidth ;
129- s . center . x = startPos . x + dx / 2 ;
130- }
131-
132- if ( dirY !== 0 ) {
133- const newHeight = Math . max ( 0.01 , startSize . y + dy * dirY ) ;
134- s . size . y = newHeight ;
135- s . center . y = startPos . y + dy / 2 ;
136- }
137- } ) ;
138- } ,
139- ) ;
140- } ;
141-
142- return (
143- < div class = "absolute inset-0 pointer-events-none" >
144- < div
145- class = "absolute pointer-events-auto group"
146- style = { {
147- left : `${ rect ( ) . left } px` ,
148- top : `${ rect ( ) . top } px` ,
149- width : `${ rect ( ) . width } px` ,
150- height : `${ rect ( ) . height } px` ,
151- } }
152- onMouseDown = { onMove }
153- >
154- { /* Border/Highlight */ }
155- < div class = "absolute inset-0 rounded-md border-2 border-blue-9 bg-blue-9/10 cursor-move" />
156-
157- { /* Handles */ }
158- { /* Corners */ }
159- < ResizeHandle
160- class = "top-0 left-0 -translate-x-1/2 -translate-y-1/2 cursor-nw-resize"
161- onMouseDown = { createResizeHandler ( - 1 , - 1 ) }
162- />
163- < ResizeHandle
164- class = "top-0 right-0 translate-x-1/2 -translate-y-1/2 cursor-ne-resize"
165- onMouseDown = { createResizeHandler ( 1 , - 1 ) }
166- />
167- < ResizeHandle
168- class = "bottom-0 left-0 -translate-x-1/2 translate-y-1/2 cursor-sw-resize"
169- onMouseDown = { createResizeHandler ( - 1 , 1 ) }
170- />
171- < ResizeHandle
172- class = "bottom-0 right-0 translate-x-1/2 translate-y-1/2 cursor-se-resize"
173- onMouseDown = { createResizeHandler ( 1 , 1 ) }
174- />
175-
176- { /* Sides */ }
177- < ResizeHandle
178- class = "top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 cursor-n-resize"
179- onMouseDown = { createResizeHandler ( 0 , - 1 ) }
180- />
181- < ResizeHandle
182- class = "bottom-0 left-1/2 -translate-x-1/2 translate-y-1/2 cursor-s-resize"
183- onMouseDown = { createResizeHandler ( 0 , 1 ) }
184- />
185- < ResizeHandle
186- class = "left-0 top-1/2 -translate-x-1/2 -translate-y-1/2 cursor-w-resize"
187- onMouseDown = { createResizeHandler ( - 1 , 0 ) }
188- />
189- < ResizeHandle
190- class = "right-0 top-1/2 translate-x-1/2 -translate-y-1/2 cursor-e-resize"
191- onMouseDown = { createResizeHandler ( 1 , 0 ) }
192- />
193- </ div >
194- </ div >
195- ) ;
196- } }
197- </ Show >
163+ < div class = "absolute inset-0 pointer-events-none" >
164+ < div
165+ class = "absolute pointer-events-auto group"
166+ style = { {
167+ left : `${ rect ( ) . left } px` ,
168+ top : `${ rect ( ) . top } px` ,
169+ width : `${ rect ( ) . width } px` ,
170+ height : `${ rect ( ) . height } px` ,
171+ } }
172+ onMouseDown = { onMove }
173+ >
174+ < div class = "absolute inset-0 rounded-md border-2 border-blue-9 bg-blue-9/10 cursor-move" />
175+
176+ < ResizeHandle
177+ class = "top-0 left-0 -translate-x-1/2 -translate-y-1/2 cursor-nw-resize"
178+ onMouseDown = { createResizeHandler ( - 1 , - 1 ) }
179+ />
180+ < ResizeHandle
181+ class = "top-0 right-0 translate-x-1/2 -translate-y-1/2 cursor-ne-resize"
182+ onMouseDown = { createResizeHandler ( 1 , - 1 ) }
183+ />
184+ < ResizeHandle
185+ class = "bottom-0 left-0 -translate-x-1/2 translate-y-1/2 cursor-sw-resize"
186+ onMouseDown = { createResizeHandler ( - 1 , 1 ) }
187+ />
188+ < ResizeHandle
189+ class = "bottom-0 right-0 translate-x-1/2 translate-y-1/2 cursor-se-resize"
190+ onMouseDown = { createResizeHandler ( 1 , 1 ) }
191+ />
192+
193+ < ResizeHandle
194+ class = "top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 cursor-n-resize"
195+ onMouseDown = { createResizeHandler ( 0 , - 1 ) }
196+ />
197+ < ResizeHandle
198+ class = "bottom-0 left-1/2 -translate-x-1/2 translate-y-1/2 cursor-s-resize"
199+ onMouseDown = { createResizeHandler ( 0 , 1 ) }
200+ />
201+ < ResizeHandle
202+ class = "left-0 top-1/2 -translate-x-1/2 -translate-y-1/2 cursor-w-resize"
203+ onMouseDown = { createResizeHandler ( - 1 , 0 ) }
204+ />
205+ < ResizeHandle
206+ class = "right-0 top-1/2 translate-x-1/2 -translate-y-1/2 cursor-e-resize"
207+ onMouseDown = { createResizeHandler ( 1 , 0 ) }
208+ />
209+ </ div >
210+ </ div >
198211 ) ;
199212}
200213
0 commit comments