@@ -6,6 +6,8 @@ import { GeometryRenderer } from '../renderers/GeometryRenderer';
66import { SourceRenderer } from '../renderers/SourceRenderer' ;
77import { BoundaryRenderer } from '../renderers/BoundaryRenderer' ;
88import { LatticeRenderer } from '../renderers/LatticeRenderer' ;
9+ import { RegionRenderer } from '../renderers/RegionRenderer' ;
10+ import { RegionBoxRenderer } from '../renderers/RegionBoxRenderer' ;
911import { ResizeHandles } from '../utils/resizeHandles' ;
1012import { useCanvasStore } from '../../stores/canvas' ;
1113
@@ -47,7 +49,7 @@ export const ElementLayer: React.FC<ElementLayerProps> = ({
4749
4850 // Sort elements by type for proper layering
4951 const sortedElements = React . useMemo ( ( ) => {
50- const order = [ 'lattice' , 'cylinder' , 'rectangle' , 'triangle' , 'source' , 'boundary' ] ;
52+ const order = [ 'lattice' , 'cylinder' , 'rectangle' , 'triangle' , 'source' , 'region' , ' boundary'] ;
5153 return [ ...elements ] . sort ( ( a , b ) => {
5254 const aIndex = order . indexOf ( getElementCategory ( a ) ) ;
5355 const bIndex = order . indexOf ( getElementCategory ( b ) ) ;
@@ -57,7 +59,9 @@ export const ElementLayer: React.FC<ElementLayerProps> = ({
5759
5860 return (
5961 < Layer >
60- { sortedElements . map ( ( element ) => {
62+ { sortedElements
63+ . filter ( element => ! element . invisible ) // Don't render invisible elements
64+ . map ( ( element ) => {
6165 const isSelected = selectedIds . includes ( element . id ) ;
6266
6367 // Boundaries don't need CanvasElementComponent wrapper since they don't have position/drag behavior
@@ -135,6 +139,8 @@ export const ElementLayer: React.FC<ElementLayerProps> = ({
135139function getElementCategory ( element : CanvasElement ) : string {
136140 if ( element . type === 'lattice' ) return 'lattice' ;
137141 if ( element . type === 'pmlBoundary' ) return 'boundary' ;
142+ if ( element . type === 'fluxRegion' ) return 'region' ;
143+ if ( element . type === 'regionBox' ) return 'region' ;
138144 if ( 'component' in element ) return 'source' ;
139145 return element . type ;
140146}
@@ -246,6 +252,83 @@ function renderElement(
246252 ) ;
247253 }
248254
255+ if ( element . type === 'fluxRegion' ) {
256+ return (
257+ < RegionRenderer
258+ region = { element as any }
259+ isSelected = { isSelected }
260+ scale = { scale }
261+ GRID_PX = { GRID_PX }
262+ />
263+ ) ;
264+ }
265+
266+ if ( element . type === 'regionBox' ) {
267+ return (
268+ < RegionBoxRenderer
269+ regionBox = { element as any }
270+ isSelected = { isSelected }
271+ scale = { scale }
272+ GRID_PX = { GRID_PX }
273+ />
274+ ) ;
275+ }
276+
277+ if ( element . type === 'regionBox' ) {
278+ // For region boxes with resize handles, we return a special structure when selected
279+ if ( isSelected && ! element . locked && selectedIds ?. length === 1 ) {
280+ return (
281+ < >
282+ < RegionBoxRenderer
283+ regionBox = { element as any }
284+ isSelected = { isSelected }
285+ scale = { scale }
286+ GRID_PX = { GRID_PX }
287+ />
288+ < ResizeHandles
289+ rectangle = { element as any }
290+ GRID_PX = { GRID_PX }
291+ scale = { scale }
292+ onResize = { ( updates : Partial < CanvasElement > ) => onUpdate ( element . id , updates ) }
293+ onResizeEnd = { ( updates : Partial < CanvasElement > ) => onCommit ( element . id , updates ) }
294+ snapToGrid = { ( value : number , forceGrid ?: boolean , forceResolution ?: boolean ) => {
295+ const res = resolution ;
296+ if ( forceResolution && res && res > 1 ) {
297+ const cellSize = 1 / res ;
298+ return Math . round ( value / cellSize ) * cellSize ;
299+ } else if ( forceGrid ) {
300+ return Math . round ( value ) ;
301+ } else if ( resolutionSnapping && res && res > 1 ) {
302+ const cellSize = 1 / res ;
303+ return Math . round ( value / cellSize ) * cellSize ;
304+ } else if ( gridSnapping ) {
305+ return Math . round ( value ) ;
306+ }
307+ return value ;
308+ } }
309+ gridSnapping = { gridSnapping || false }
310+ resolutionSnapping = { resolutionSnapping || false }
311+ showGrid = { showGrid || false }
312+ showResolutionOverlay = { showResolutionOverlay || false }
313+ toggleShowGrid = { toggleShowGrid || ( ( ) => { } ) }
314+ toggleShowResolutionOverlay = { toggleShowResolutionOverlay || ( ( ) => { } ) }
315+ handleUpdateGeometry = { ( id : string , updates : Partial < CanvasElement > ) => onCommit ( id , updates ) }
316+ setActiveInstructionSet = { ( key : string ) => onSetActiveInstructionSet ?.( key ) }
317+ />
318+ </ >
319+ ) ;
320+ }
321+
322+ return (
323+ < RegionBoxRenderer
324+ regionBox = { element as any }
325+ isSelected = { isSelected }
326+ scale = { scale }
327+ GRID_PX = { GRID_PX }
328+ />
329+ ) ;
330+ }
331+
249332 if ( element . type === 'lattice' ) {
250333 return (
251334 < LatticeRenderer
0 commit comments