wwf
2 天以前 a430284aa21e3ae1f0d5654e55b2ad2852519cc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import type { FC } from 'react'
import { useState } from 'react'
import {
  RiArrowDownSLine,
  RiCheckLine,
} from '@remixicon/react'
import classNames from 'classnames'
import { useTranslation } from 'react-i18next'
import type { WriteMode } from '../types'
import { getOperationItems } from '../utils'
import {
  PortalToFollowElem,
  PortalToFollowElemContent,
  PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import type { VarType } from '@/app/components/workflow/types'
import Divider from '@/app/components/base/divider'
 
type Item = {
  value: string | number
  name: string
}
 
type OperationSelectorProps = {
  value: string | number
  onSelect: (value: Item) => void
  placeholder?: string
  disabled?: boolean
  className?: string
  popupClassName?: string
  assignedVarType?: VarType
  writeModeTypes?: WriteMode[]
  writeModeTypesArr?: WriteMode[]
  writeModeTypesNum?: WriteMode[]
}
 
const i18nPrefix = 'workflow.nodes.assigner'
 
const OperationSelector: FC<OperationSelectorProps> = ({
  value,
  onSelect,
  disabled = false,
  className,
  popupClassName,
  assignedVarType,
  writeModeTypes,
  writeModeTypesArr,
  writeModeTypesNum,
}) => {
  const { t } = useTranslation()
  const [open, setOpen] = useState(false)
 
  const items = getOperationItems(assignedVarType, writeModeTypes, writeModeTypesArr, writeModeTypesNum)
 
  const selectedItem = items.find(item => item.value === value)
 
  return (
    <PortalToFollowElem
      open={open}
      onOpenChange={setOpen}
      placement='bottom-start'
      offset={4}
    >
      <PortalToFollowElemTrigger
        onClick={() => !disabled && setOpen(v => !v)}
      >
        <div
          className={classNames(
            'flex items-center px-2 py-1 gap-0.5 rounded-lg bg-components-input-bg-normal',
            disabled ? 'cursor-not-allowed !bg-components-input-bg-disabled' : 'cursor-pointer hover:bg-state-base-hover-alt',
            open && 'bg-state-base-hover-alt',
            className,
          )}
        >
          <div className='flex p-1 items-center'>
            <span
              className={`truncate overflow-hidden text-ellipsis system-sm-regular
                ${selectedItem ? 'text-components-input-text-filled' : 'text-components-input-text-disabled'}`}
            >
              {selectedItem?.name ? t(`${i18nPrefix}.operations.${selectedItem?.name}`) : t(`${i18nPrefix}.operations.title`)}
            </span>
          </div>
          <RiArrowDownSLine className={`h-4 w-4 text-text-quaternary ${disabled && 'text-components-input-text-placeholder'} ${open && 'text-text-secondary'}`} />
        </div>
      </PortalToFollowElemTrigger>
 
      <PortalToFollowElemContent className={`z-20 ${popupClassName}`}>
        <div className='flex w-[140px] flex-col items-start rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg'>
          <div className='flex p-1 flex-col items-start self-stretch'>
            <div className='flex px-3 pt-1 pb-0.5 items-start self-stretch'>
              <div className='flex grow text-text-tertiary system-xs-medium-uppercase'>{t(`${i18nPrefix}.operations.title`)}</div>
            </div>
            {items.map(item => (
              item.value === 'divider'
                ? (
                  <Divider key="divider" className="my-1" />
                )
                : (
                  <div
                    key={item.value}
                    className={classNames(
                      'flex items-center px-2 py-1 gap-1 self-stretch rounded-lg',
                      'cursor-pointer hover:bg-state-base-hover',
                    )}
                    onClick={() => {
                      onSelect(item)
                      setOpen(false)
                    }}
                  >
                    <div className='flex min-h-5 px-1 items-center gap-1 grow'>
                      <span className={'flex flex-grow text-text-secondary system-sm-medium'}>{t(`${i18nPrefix}.operations.${item.name}`)}</span>
                    </div>
                    {item.value === value && (
                      <div className='flex justify-center items-center'>
                        <RiCheckLine className='h-4 w-4 text-text-accent' />
                      </div>
                    )}
                  </div>
                )
            ))}
          </div>
        </div>
      </PortalToFollowElemContent>
    </PortalToFollowElem>
  )
}
 
export default OperationSelector