@@ -19,6 +19,7 @@ import type {
19
19
StrategyApplicationResult ,
20
20
InteractionLifecycle ,
21
21
CustomStrategyState ,
22
+ WhenToShowControl ,
22
23
} from './canvas-strategy-types'
23
24
import {
24
25
ControlDelay ,
@@ -83,6 +84,11 @@ import { getReparentTargetUnified } from './strategies/reparent-helpers/reparent
83
84
import { gridRearrangeResizeKeyboardStrategy } from './strategies/grid-rearrange-keyboard-strategy'
84
85
import createCachedSelector from 're-reselect'
85
86
import { getActivePlugin } from '../plugins/style-plugins'
87
+ import {
88
+ controlsForGridPlaceholders ,
89
+ GridControls ,
90
+ isGridControlsProps ,
91
+ } from '../controls/grid-controls-for-strategies'
86
92
87
93
export type CanvasStrategyFactory = (
88
94
canvasState : InteractionCanvasState ,
@@ -648,6 +654,42 @@ function controlPriorityToNumber(prio: ControlWithProps<any>['priority']): numbe
648
654
}
649
655
}
650
656
657
+ export function combineApplicableControls (
658
+ strategyControls : Array < ControlWithProps < unknown > > ,
659
+ ) : Array < ControlWithProps < unknown > > {
660
+ // Separate out the instances of `GridControls`.
661
+ let result : Array < ControlWithProps < unknown > > = [ ]
662
+ let gridControlsInstances : Array < ControlWithProps < unknown > > = [ ]
663
+ for ( const control of strategyControls ) {
664
+ if ( control . control === GridControls ) {
665
+ gridControlsInstances . push ( control )
666
+ } else {
667
+ result . push ( control )
668
+ }
669
+ }
670
+
671
+ // Sift the instances of `GridControls`, storing their targets by when they should be shown.
672
+ let gridControlsTargets : Map < WhenToShowControl , Array < ElementPath > > = new Map ( )
673
+ for ( const control of gridControlsInstances ) {
674
+ if ( isGridControlsProps ( control . props ) ) {
675
+ const possibleTargets = gridControlsTargets . get ( control . show )
676
+ if ( possibleTargets == null ) {
677
+ gridControlsTargets . set ( control . show , control . props . targets )
678
+ } else {
679
+ possibleTargets . push ( ...control . props . targets )
680
+ }
681
+ }
682
+ }
683
+
684
+ // Create new instances of `GridControls` with the combined targets.
685
+ for ( const [ show , targets ] of gridControlsTargets ) {
686
+ result . push ( controlsForGridPlaceholders ( targets , show , `-${ show } ` ) )
687
+ }
688
+
689
+ // Return the newly created controls with the combined entries.
690
+ return result
691
+ }
692
+
651
693
const controlEquals = ( l : ControlWithProps < any > , r : ControlWithProps < any > ) => {
652
694
return l . control === r . control && l . key === r . key
653
695
}
@@ -667,34 +709,37 @@ export function useGetApplicableStrategyControls(localSelectedViews: Array<Eleme
667
709
'useGetApplicableStrategyControls currentlyInProgress' ,
668
710
)
669
711
return React . useMemo ( ( ) => {
712
+ let strategyControls : Array < ControlWithProps < unknown > > = [ ]
670
713
let isResizable : boolean = false
671
- const bottomStrategyControls : Array < ControlWithProps < unknown > > = [ ]
672
- const middleStrategyControls : Array < ControlWithProps < unknown > > = [ ]
673
- const topStrategyControls : Array < ControlWithProps < unknown > > = [ ]
674
714
// Add the controls for currently applicable strategies.
675
715
for ( const strategy of applicableStrategies ) {
676
716
if ( isResizableStrategy ( strategy ) ) {
677
717
isResizable = true
678
718
}
679
- const strategyControls = getApplicableControls ( currentStrategy , strategy )
680
-
681
- // uniquely add the strategyControls to the bottom, middle, and top arrays
682
- for ( const control of strategyControls ) {
683
- switch ( control . priority ) {
684
- case 'bottom' :
685
- pushUniquelyBy ( bottomStrategyControls , control , controlEquals )
686
- break
687
- case undefined :
688
- pushUniquelyBy ( middleStrategyControls , control , controlEquals )
689
- break
690
- case 'top' :
691
- pushUniquelyBy ( topStrategyControls , control , controlEquals )
692
- break
693
- default :
694
- assertNever ( control . priority )
695
- }
719
+ strategyControls . push ( ...getApplicableControls ( currentStrategy , strategy ) )
720
+ }
721
+ const combinedControls = combineApplicableControls ( strategyControls )
722
+ const bottomStrategyControls : Array < ControlWithProps < unknown > > = [ ]
723
+ const middleStrategyControls : Array < ControlWithProps < unknown > > = [ ]
724
+ const topStrategyControls : Array < ControlWithProps < unknown > > = [ ]
725
+
726
+ // uniquely add the strategyControls to the bottom, middle, and top arrays
727
+ for ( const control of combinedControls ) {
728
+ switch ( control . priority ) {
729
+ case 'bottom' :
730
+ pushUniquelyBy ( bottomStrategyControls , control , controlEquals )
731
+ break
732
+ case undefined :
733
+ pushUniquelyBy ( middleStrategyControls , control , controlEquals )
734
+ break
735
+ case 'top' :
736
+ pushUniquelyBy ( topStrategyControls , control , controlEquals )
737
+ break
738
+ default :
739
+ assertNever ( control . priority )
696
740
}
697
741
}
742
+
698
743
// Special case controls.
699
744
if ( ! isResizable && ! currentlyInProgress ) {
700
745
middleStrategyControls . push ( notResizableControls )
0 commit comments