diff --git a/invokeai/frontend/web/src/features/regionalPrompts/components/ControlAdapterLayerListItem.tsx b/invokeai/frontend/web/src/features/regionalPrompts/components/ControlAdapterLayerListItem.tsx
index 5f78843aab..ef94b4c75a 100644
--- a/invokeai/frontend/web/src/features/regionalPrompts/components/ControlAdapterLayerListItem.tsx
+++ b/invokeai/frontend/web/src/features/regionalPrompts/components/ControlAdapterLayerListItem.tsx
@@ -4,6 +4,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import ControlAdapterLayerConfig from 'features/regionalPrompts/components/controlAdapterOverrides/ControlAdapterLayerConfig';
import { LayerTitle } from 'features/regionalPrompts/components/LayerTitle';
import { RPLayerDeleteButton } from 'features/regionalPrompts/components/RPLayerDeleteButton';
+import { RPLayerMenu } from 'features/regionalPrompts/components/RPLayerMenu';
import { RPLayerVisibilityToggle } from 'features/regionalPrompts/components/RPLayerVisibilityToggle';
import {
isControlAdapterLayer,
@@ -51,6 +52,7 @@ export const ControlAdapterLayerListItem = memo(({ layerId }: Props) => {
+
diff --git a/invokeai/frontend/web/src/features/regionalPrompts/components/IPAdapterLayerListItem.tsx b/invokeai/frontend/web/src/features/regionalPrompts/components/IPAdapterLayerListItem.tsx
index bf4245f26b..f94865c305 100644
--- a/invokeai/frontend/web/src/features/regionalPrompts/components/IPAdapterLayerListItem.tsx
+++ b/invokeai/frontend/web/src/features/regionalPrompts/components/IPAdapterLayerListItem.tsx
@@ -4,6 +4,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import ControlAdapterLayerConfig from 'features/regionalPrompts/components/controlAdapterOverrides/ControlAdapterLayerConfig';
import { LayerTitle } from 'features/regionalPrompts/components/LayerTitle';
import { RPLayerDeleteButton } from 'features/regionalPrompts/components/RPLayerDeleteButton';
+import { RPLayerMenu } from 'features/regionalPrompts/components/RPLayerMenu';
import { RPLayerVisibilityToggle } from 'features/regionalPrompts/components/RPLayerVisibilityToggle';
import {
isIPAdapterLayer,
@@ -51,6 +52,7 @@ export const IPAdapterLayerListItem = memo(({ layerId }: Props) => {
+
diff --git a/invokeai/frontend/web/src/features/regionalPrompts/components/RPLayerMenu.tsx b/invokeai/frontend/web/src/features/regionalPrompts/components/RPLayerMenu.tsx
index ebfa399227..16619e924e 100644
--- a/invokeai/frontend/web/src/features/regionalPrompts/components/RPLayerMenu.tsx
+++ b/invokeai/frontend/web/src/features/regionalPrompts/components/RPLayerMenu.tsx
@@ -1,78 +1,19 @@
import { IconButton, Menu, MenuButton, MenuDivider, MenuItem, MenuList } from '@invoke-ai/ui-library';
-import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
-import { guidanceLayerIPAdapterAdded } from 'app/store/middleware/listenerMiddleware/listeners/regionalControlToControlAdapterBridge';
-import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
-import {
- isMaskedGuidanceLayer,
- layerDeleted,
- layerMovedBackward,
- layerMovedForward,
- layerMovedToBack,
- layerMovedToFront,
- layerReset,
- maskLayerNegativePromptChanged,
- maskLayerPositivePromptChanged,
- selectRegionalPromptsSlice,
-} from 'features/regionalPrompts/store/regionalPromptsSlice';
-import { memo, useCallback, useMemo } from 'react';
+import { useAppDispatch } from 'app/store/storeHooks';
+import { RPLayerMenuArrangeActions } from 'features/regionalPrompts/components/RPLayerMenuArrangeActions';
+import { RPLayerMenuMaskedGuidanceActions } from 'features/regionalPrompts/components/RPLayerMenuMaskedGuidanceActions';
+import { useLayerType } from 'features/regionalPrompts/hooks/layerStateHooks';
+import { layerDeleted, layerReset } from 'features/regionalPrompts/store/regionalPromptsSlice';
+import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
-import {
- PiArrowCounterClockwiseBold,
- PiArrowDownBold,
- PiArrowLineDownBold,
- PiArrowLineUpBold,
- PiArrowUpBold,
- PiDotsThreeVerticalBold,
- PiPlusBold,
- PiTrashSimpleBold,
-} from 'react-icons/pi';
-import { assert } from 'tsafe';
+import { PiArrowCounterClockwiseBold, PiDotsThreeVerticalBold, PiTrashSimpleBold } from 'react-icons/pi';
type Props = { layerId: string };
export const RPLayerMenu = memo(({ layerId }: Props) => {
const dispatch = useAppDispatch();
const { t } = useTranslation();
- const selectValidActions = useMemo(
- () =>
- createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => {
- const layer = regionalPrompts.present.layers.find((l) => l.id === layerId);
- assert(isMaskedGuidanceLayer(layer), `Layer ${layerId} not found or not an RP layer`);
- const layerIndex = regionalPrompts.present.layers.findIndex((l) => l.id === layerId);
- const layerCount = regionalPrompts.present.layers.length;
- return {
- canAddPositivePrompt: layer.positivePrompt === null,
- canAddNegativePrompt: layer.negativePrompt === null,
- canMoveForward: layerIndex < layerCount - 1,
- canMoveBackward: layerIndex > 0,
- canMoveToFront: layerIndex < layerCount - 1,
- canMoveToBack: layerIndex > 0,
- };
- }),
- [layerId]
- );
- const validActions = useAppSelector(selectValidActions);
- const addPositivePrompt = useCallback(() => {
- dispatch(maskLayerPositivePromptChanged({ layerId, prompt: '' }));
- }, [dispatch, layerId]);
- const addNegativePrompt = useCallback(() => {
- dispatch(maskLayerNegativePromptChanged({ layerId, prompt: '' }));
- }, [dispatch, layerId]);
- const addIPAdapter = useCallback(() => {
- dispatch(guidanceLayerIPAdapterAdded(layerId));
- }, [dispatch, layerId]);
- const moveForward = useCallback(() => {
- dispatch(layerMovedForward(layerId));
- }, [dispatch, layerId]);
- const moveToFront = useCallback(() => {
- dispatch(layerMovedToFront(layerId));
- }, [dispatch, layerId]);
- const moveBackward = useCallback(() => {
- dispatch(layerMovedBackward(layerId));
- }, [dispatch, layerId]);
- const moveToBack = useCallback(() => {
- dispatch(layerMovedToBack(layerId));
- }, [dispatch, layerId]);
+ const layerType = useLayerType(layerId);
const resetLayer = useCallback(() => {
dispatch(layerReset(layerId));
}, [dispatch, layerId]);
@@ -83,32 +24,23 @@ export const RPLayerMenu = memo(({ layerId }: Props) => {