diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldContextMenu.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldContextMenu.tsx deleted file mode 100644 index ec1500db9d..0000000000 --- a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldContextMenu.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import type { ContextMenuProps } from '@invoke-ai/ui-library'; -import { ContextMenu, MenuGroup, MenuItem, MenuList } from '@invoke-ai/ui-library'; -import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { useFieldInputKind } from 'features/nodes/hooks/useFieldInputKind'; -import { useFieldLabel } from 'features/nodes/hooks/useFieldLabel'; -import { useFieldTemplateTitle } from 'features/nodes/hooks/useFieldTemplateTitle'; -import { - selectWorkflowSlice, - workflowExposedFieldAdded, - workflowExposedFieldRemoved, -} from 'features/nodes/store/workflowSlice'; -import type { ReactNode } from 'react'; -import { memo, useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; -import { PiMinusBold, PiPlusBold } from 'react-icons/pi'; - -type Props = { - nodeId: string; - fieldName: string; - kind: 'input' | 'output'; - children: ContextMenuProps['children']; -}; - -const FieldContextMenu = ({ nodeId, fieldName, kind, children }: Props) => { - const dispatch = useAppDispatch(); - const label = useFieldLabel(nodeId, fieldName); - const fieldTemplateTitle = useFieldTemplateTitle(nodeId, fieldName, kind); - const input = useFieldInputKind(nodeId, fieldName); - const { t } = useTranslation(); - - const selectIsExposed = useMemo( - () => - createSelector(selectWorkflowSlice, (workflow) => { - return Boolean(workflow.exposedFields.find((f) => f.nodeId === nodeId && f.fieldName === fieldName)); - }), - [fieldName, nodeId] - ); - - const mayExpose = useMemo(() => input && ['any', 'direct'].includes(input), [input]); - - const isExposed = useAppSelector(selectIsExposed); - - const handleExposeField = useCallback(() => { - dispatch(workflowExposedFieldAdded({ nodeId, fieldName })); - }, [dispatch, fieldName, nodeId]); - - const handleUnexposeField = useCallback(() => { - dispatch(workflowExposedFieldRemoved({ nodeId, fieldName })); - }, [dispatch, fieldName, nodeId]); - - const menuItems = useMemo(() => { - const menuItems: ReactNode[] = []; - if (mayExpose && !isExposed) { - menuItems.push( - } onClick={handleExposeField}> - {t('nodes.addLinearView')} - - ); - } - if (mayExpose && isExposed) { - menuItems.push( - } onClick={handleUnexposeField}> - {t('nodes.removeLinearView')} - - ); - } - return menuItems; - }, [fieldName, handleExposeField, handleUnexposeField, isExposed, mayExpose, nodeId, t]); - - const renderMenuFunc = useCallback( - () => - !menuItems.length ? null : ( - - {menuItems} - - ), - [fieldTemplateTitle, label, menuItems, t] - ); - - return {children}; -}; - -export default memo(FieldContextMenu); diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldLinearViewToggle.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldLinearViewToggle.tsx index 0dac7996eb..cb1bcba1fe 100644 --- a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldLinearViewToggle.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldLinearViewToggle.tsx @@ -13,10 +13,9 @@ import { PiMinusBold, PiPlusBold } from 'react-icons/pi'; type Props = { nodeId: string; fieldName: string; - isHovered: boolean; }; -const FieldLinearViewToggle = ({ nodeId, fieldName, isHovered }: Props) => { +const FieldLinearViewToggle = ({ nodeId, fieldName }: Props) => { const dispatch = useAppDispatch(); const { t } = useTranslation(); @@ -38,37 +37,31 @@ const FieldLinearViewToggle = ({ nodeId, fieldName, isHovered }: Props) => { dispatch(workflowExposedFieldRemoved({ nodeId, fieldName })); }, [dispatch, fieldName, nodeId]); - const ToggleButton = useMemo(() => { - if (!isHovered) { - return null; - } else if (!isExposed) { - return ( - } - onClick={handleExposeField} - pointerEvents="auto" - size="xs" - /> - ); - } else if (isExposed) { - return ( - } - onClick={handleUnexposeField} - pointerEvents="auto" - size="xs" - /> - ); - } - }, [isHovered, handleExposeField, handleUnexposeField, isExposed, t]); - - return ToggleButton; + if (!isExposed) { + return ( + } + onClick={handleExposeField} + pointerEvents="auto" + size="xs" + /> + ); + } else { + return ( + } + onClick={handleUnexposeField} + pointerEvents="auto" + size="xs" + /> + ); + } }; export default memo(FieldLinearViewToggle); diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/InputField.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/InputField.tsx index bb45f4e3e3..2b9f7960e4 100644 --- a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/InputField.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/InputField.tsx @@ -8,7 +8,6 @@ import { memo, useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import EditableFieldTitle from './EditableFieldTitle'; -import FieldContextMenu from './FieldContextMenu'; import FieldHandle from './FieldHandle'; import FieldLinearViewToggle from './FieldLinearViewToggle'; import InputFieldRenderer from './InputFieldRenderer'; @@ -48,11 +47,11 @@ const InputField = ({ nodeId, fieldName }: Props) => { return false; }, [fieldTemplate, isConnected, doesFieldHaveValue]); - const handleMouseOver = useCallback(() => { + const onMouseEnter = useCallback(() => { setIsHovered(true); }, []); - const handleMouseOut = useCallback(() => { + const onMouseLeave = useCallback(() => { setIsHovered(false); }, []); @@ -97,22 +96,17 @@ const InputField = ({ nodeId, fieldName }: Props) => { return ( - - - {(ref) => ( - - - - - )} - + + + + {isHovered && } +