Files
labelmain-demo/components/label/components/MetaOperationTool.tsx
2026-02-03 18:05:47 +08:00

205 lines
6.9 KiB
TypeScript

import { Box, Flex, HoverCard } from "@mantine/core"
import { ArrowBigRightDashIcon, MinusCircleIcon } from "lucide-react"
import { useCallback } from "react"
import { useBottomToolsStore } from "../useBottomToolsStore"
import { useDescToolsStore } from "../useDescToolsStore"
import { useTopToolsStore } from "../useTopToolsStore"
const MetaOperationTool = () => {
const { metaOperation, metaData } = useDescToolsStore()
const { activeImage } = useBottomToolsStore()
const currentImageData = metaData.get(activeImage) || []
const HoverContent = useCallback(
(index?: number) => {
if (!metaOperation) return <></>
const { sub_attributes_describe } = metaOperation
return (
<Box w={256}>
<Box
fw={600}
pb={4}
mb={4}
style={{
borderBottom:
"1px solid light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-4))",
}}>
</Box>
{sub_attributes_describe.length ? (
<Box w="100%">
{sub_attributes_describe.map((subDesc) => (
<Flex
key={subDesc.chinese_name}
w="100%"
gap="xs"
mb={4}
align="flex-start">
<Box style={{ minWidth: "fit-content" }} p={4} fw={600}>
{subDesc.chinese_name}
</Box>
<Flex flex={1} wrap="wrap" gap="xs">
{subDesc.optional_item.map((option) => (
<Box
key={option}
c="blue"
p={4}
style={{
cursor: "pointer",
borderRadius: "4px",
}}
onMouseEnter={(e) => {
e.currentTarget.style.backgroundColor =
"var(--mantine-color-gray-1)"
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = "transparent"
}}
onClick={() => {
const map = useDescToolsStore.getState().metaData
if (map.has(activeImage)) {
let arr = map.get(activeImage) || []
if (index || index === 0) arr[index] = option
else arr.push(option)
map.set(activeImage, arr)
} else {
map.set(activeImage, [option])
}
useDescToolsStore.getState().setMetaData(map)
}}>
{option}
</Box>
))}
</Flex>
</Flex>
))}
</Box>
) : (
<Flex w="100%" h={40} justify="center" align="center" bg="gray.1">
</Flex>
)}
</Box>
)
},
[activeImage, metaOperation]
)
const handleDelete = (index: number) => {
const map = useDescToolsStore.getState().metaData
let arr = (map.get(activeImage) || []).filter((_v, i) => i !== index)
map.set(activeImage, arr)
useDescToolsStore.getState().setMetaData(map)
}
return (
<Flex w="100%" h="100%">
{currentImageData.map((text, index) =>
!useTopToolsStore.getState().isView ? (
<Flex
key={`${index}${text}`}
style={{ minWidth: "fit-content" }}
align="center">
{/* Replaced Popover with HoverCard for better hover interaction */}
<HoverCard
shadow="md"
openDelay={100}
closeDelay={100}
withinPortal>
<HoverCard.Target>
<Flex
style={{
minWidth: "fit-content",
border:
"1px solid light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-4))",
borderRadius: "9999px",
cursor: "default",
}}
px={8}
justify="center"
align="center"
gap={4}>
{text}
<Box
style={{ cursor: "pointer", display: "flex" }}
onClick={(e) => {
e.stopPropagation()
handleDelete(index)
}}>
<MinusCircleIcon
style={{ width: 16, color: "var(--mantine-color-red-6)" }}
/>
</Box>
</Flex>
</HoverCard.Target>
<HoverCard.Dropdown>{HoverContent(index)}</HoverCard.Dropdown>
</HoverCard>
{index < currentImageData.length - 1 ? (
<Box w={24}>
<ArrowBigRightDashIcon
style={{ color: "var(--mantine-color-gray-4)" }}
/>
</Box>
) : null}
</Flex>
) : (
<Flex
key={`${index}${text}`}
style={{ minWidth: "fit-content" }}
align="center">
<Flex
style={{
minWidth: "fit-content",
border:
"1px solid light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-4))",
borderRadius: "9999px",
}}
px={8}
justify="center"
align="center"
gap={4}>
{text}
</Flex>
{index < currentImageData.length - 1 ? (
<Box w={24}>
<ArrowBigRightDashIcon
style={{ color: "var(--mantine-color-gray-4)" }}
/>
</Box>
) : null}
</Flex>
)
)}
{!useTopToolsStore.getState().isView ? (
<Flex
style={{ minWidth: "fit-content" }}
justify="center"
align="center"
ml={8}>
{/* Replaced Popover with HoverCard */}
<HoverCard shadow="md" openDelay={100} closeDelay={100} withinPortal>
<HoverCard.Target>
<Box
style={{
minWidth: "fit-content",
border: "1px solid var(--mantine-color-blue-6)",
borderRadius: "9999px",
cursor: "pointer",
}}
px={8}
c="white"
bg="blue">
</Box>
</HoverCard.Target>
<HoverCard.Dropdown>{HoverContent()}</HoverCard.Dropdown>
</HoverCard>
</Flex>
) : null}
</Flex>
)
}
export default MetaOperationTool