From a430284aa21e3ae1f0d5654e55b2ad2852519cc2 Mon Sep 17 00:00:00 2001
From: wwf <yearningwang@iqtogether.com>
Date: 星期三, 04 六月 2025 15:17:49 +0800
Subject: [PATCH] 初始化

---
 app/components/base/select/index.tsx |  151 +++++++++++++++++++++++++-------------------------
 1 files changed, 76 insertions(+), 75 deletions(-)

diff --git a/app/components/base/select/index.tsx b/app/components/base/select/index.tsx
index fa8730f..221d703 100644
--- a/app/components/base/select/index.tsx
+++ b/app/components/base/select/index.tsx
@@ -1,9 +1,8 @@
 'use client'
 import type { FC } from 'react'
-import React, { useEffect, useState } from 'react'
-import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions, Listbox, ListboxButton, ListboxOption, ListboxOptions } from '@headlessui/react'
+import React, { Fragment, useEffect, useState } from 'react'
+import { Combobox, Listbox, Transition } from '@headlessui/react'
 import { ChevronDownIcon, ChevronUpIcon, XMarkIcon } from '@heroicons/react/20/solid'
-import Badge from '../badge/index'
 import { RiCheckLine } from '@remixicon/react'
 import { useTranslation } from 'react-i18next'
 import classNames from '@/utils/classnames'
@@ -31,7 +30,7 @@
 export type ISelectProps = {
   className?: string
   wrapperClassName?: string
-  renderTrigger?: (value: Item | null) => React.JSX.Element | null
+  renderTrigger?: (value: Item | null) => JSX.Element | null
   items?: Item[]
   defaultValue?: number | string
   disabled?: boolean
@@ -59,7 +58,7 @@
   disabled = false,
   onSelect,
   allowSearch = true,
-  bgClassName = 'bg-components-input-bg-normal',
+  bgClassName = 'bg-gray-100',
   overlayClassName,
   optionClassName,
   renderOption,
@@ -99,44 +98,44 @@
         }
       }}>
       <div className={classNames('relative')}>
-        <div className='group text-text-secondary'>
+        <div className='group text-gray-800'>
           {allowSearch
-            ? <ComboboxInput
-              className={`w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm focus-visible:bg-state-base-hover focus-visible:outline-none group-hover:bg-state-base-hover sm:text-sm sm:leading-6 ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`}
+            ? <Combobox.Input
+              className={`w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200 ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`}
               onChange={(event) => {
                 if (!disabled)
                   setQuery(event.target.value)
               }}
               displayValue={(item: Item) => item?.name}
             />
-            : <ComboboxButton onClick={
+            : <Combobox.Button onClick={
               () => {
                 if (!disabled)
                   setOpen(!open)
               }
-            } className={classNames(`flex items-center h-9 w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover group-hover:bg-state-base-hover`, optionClassName)}>
-              <div className='w-0 grow truncate text-left' title={selectedItem?.name}>{selectedItem?.name}</div>
-            </ComboboxButton>}
-          <ComboboxButton className="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none" onClick={
+            } className={classNames(`flex items-center h-9 w-full rounded-lg border-0 ${bgClassName} py-1.5 pl-3 pr-10 shadow-sm sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-gray-200 group-hover:bg-gray-200`, optionClassName)}>
+              <div className='w-0 grow text-left truncate' title={selectedItem?.name}>{selectedItem?.name}</div>
+            </Combobox.Button>}
+          <Combobox.Button className="absolute inset-y-0 right-0 flex items-center rounded-r-md px-2 focus:outline-none group-hover:bg-gray-200" onClick={
             () => {
               if (!disabled)
                 setOpen(!open)
             }
           }>
             {open ? <ChevronUpIcon className="h-5 w-5" /> : <ChevronDownIcon className="h-5 w-5" />}
-          </ComboboxButton>
+          </Combobox.Button>
         </div>
 
         {(filteredItems.length > 0 && open) && (
-          <ComboboxOptions className={`absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md border-[0.5px] border-components-panel-border bg-components-panel-bg-blur px-1 py-1 text-base shadow-lg backdrop-blur-sm focus:outline-none sm:text-sm ${overlayClassName}`}>
+          <Combobox.Options className={`absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg border-gray-200 border-[0.5px] focus:outline-none sm:text-sm ${overlayClassName}`}>
             {filteredItems.map((item: Item) => (
-              <ComboboxOption
+              <Combobox.Option
                 key={item.value}
                 value={item}
                 className={({ active }: { active: boolean }) =>
                   classNames(
-                    'relative cursor-default select-none py-2 pl-3 pr-9 rounded-lg hover:bg-state-base-hover text-text-secondary',
-                    active ? 'bg-state-base-hover' : '',
+                    'relative cursor-default select-none py-2 pl-3 pr-9 rounded-lg hover:bg-gray-100 text-gray-700',
+                    active ? 'bg-gray-100' : '',
                     optionClassName,
                   )
                 }
@@ -151,7 +150,7 @@
                           {selected && (
                             <span
                               className={classNames(
-                                'absolute inset-y-0 right-0 flex items-center pr-4 text-text-secondary',
+                                'absolute inset-y-0 right-0 flex items-center pr-4 text-gray-700',
                               )}
                             >
                               <RiCheckLine className="h-4 w-4" aria-hidden="true" />
@@ -161,9 +160,9 @@
                       )}
                   </>
                 )}
-              </ComboboxOption>
+              </Combobox.Option>
             ))}
-          </ComboboxOptions>
+          </Combobox.Options>
         )}
       </div>
     </Combobox >
@@ -210,9 +209,9 @@
       }}
     >
       <div className={classNames('group/simple-select relative h-9', wrapperClassName)}>
-        {renderTrigger && <ListboxButton className='w-full'>{renderTrigger(selectedItem)}</ListboxButton>}
+        {renderTrigger && <Listbox.Button className='w-full'>{renderTrigger(selectedItem)}</Listbox.Button>}
         {!renderTrigger && (
-          <ListboxButton className={classNames(`flex items-center w-full h-full rounded-lg border-0 bg-components-input-bg-normal pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover-alt group-hover/simple-select:bg-state-base-hover-alt ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`, className)}>
+          <Listbox.Button className={classNames(`flex items-center w-full h-full rounded-lg border-0 bg-components-input-bg-normal pl-3 pr-10 sm:text-sm sm:leading-6 focus-visible:outline-none focus-visible:bg-state-base-hover-alt group-hover/simple-select:bg-state-base-hover-alt ${disabled ? 'cursor-not-allowed' : 'cursor-pointer'}`, className)}>
             <span className={classNames('block truncate text-left system-sm-regular text-components-input-text-filled', !selectedItem?.name && 'text-components-input-text-placeholder')}>{selectedItem?.name ?? localPlaceholder}</span>
             <span className="absolute inset-y-0 right-0 flex items-center pr-2">
               {(selectedItem && !notClearable)
@@ -223,7 +222,7 @@
                       setSelectedItem(null)
                       onSelect({ name: '', value: '' })
                     }}
-                    className="h-4 w-4 cursor-pointer text-text-quaternary"
+                    className="h-4 w-4 text-text-quaternary cursor-pointer"
                     aria-hidden="false"
                   />
                 )
@@ -234,44 +233,52 @@
                   />
                 )}
             </span>
-          </ListboxButton>
+          </Listbox.Button>
         )}
 
         {!disabled && (
-          <ListboxOptions className={classNames('absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-xl bg-components-panel-bg-blur backdrop-blur-sm py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm', optionWrapClassName)}>
-            {items.map((item: Item) => (
-              <ListboxOption
-                key={item.value}
-                className={
-                  classNames(
-                    'relative cursor-pointer select-none py-2 pl-3 pr-9 rounded-lg hover:bg-state-base-hover text-text-secondary',
-                    optionClassName,
-                  )
-                }
-                value={item}
-                disabled={disabled}
-              >
-                {({ /* active, */ selected }) => (
-                  <>
-                    {renderOption
-                      ? renderOption({ item, selected })
-                      : (<>
-                        <span className={classNames('block', selected && 'font-normal')}>{item.name}</span>
-                        {selected && !hideChecked && (
-                          <span
-                            className={classNames(
-                              'absolute inset-y-0 right-0 flex items-center pr-4 text-text-accent',
-                            )}
-                          >
-                            <RiCheckLine className="h-4 w-4" aria-hidden="true" />
-                          </span>
-                        )}
-                      </>)}
-                  </>
-                )}
-              </ListboxOption>
-            ))}
-          </ListboxOptions>
+          <Transition
+            as={Fragment}
+            leave="transition ease-in duration-100"
+            leaveFrom="opacity-100"
+            leaveTo="opacity-0"
+          >
+
+            <Listbox.Options className={classNames('absolute z-10 mt-1 px-1 max-h-60 w-full overflow-auto rounded-md bg-components-panel-bg-blur py-1 text-base shadow-lg border-components-panel-border border-[0.5px] focus:outline-none sm:text-sm', optionWrapClassName)}>
+              {items.map((item: Item) => (
+                <Listbox.Option
+                  key={item.value}
+                  className={({ active }) =>
+                    classNames(
+                      'relative cursor-pointer select-none py-2 pl-3 pr-9 rounded-lg hover:bg-state-base-hover text-text-secondary',
+                      optionClassName,
+                    )
+                  }
+                  value={item}
+                  disabled={disabled}
+                >
+                  {({ /* active, */ selected }) => (
+                    <>
+                      {renderOption
+                        ? renderOption({ item, selected })
+                        : (<>
+                          <span className={classNames('block', selected && 'font-normal')}>{item.name}</span>
+                          {selected && !hideChecked && (
+                            <span
+                              className={classNames(
+                                'absolute inset-y-0 right-0 flex items-center pr-4 text-text-accent',
+                              )}
+                            >
+                              <RiCheckLine className="h-4 w-4" aria-hidden="true" />
+                            </span>
+                          )}
+                        </>)}
+                    </>
+                  )}
+                </Listbox.Option>
+              ))}
+            </Listbox.Options>
+          </Transition>
         )}
       </div>
     </Listbox>
@@ -283,8 +290,7 @@
   onSelect: (value: Item) => void
   items: Item[]
   placeholder?: string
-  installedValue?: string | number
-  renderTrigger?: (value?: Item) => React.JSX.Element | null
+  renderTrigger?: (value?: Item) => JSX.Element | null
   triggerClassName?: string
   triggerClassNameFn?: (open: boolean) => string
   popupClassName?: string
@@ -297,7 +303,6 @@
   onSelect,
   items,
   placeholder,
-  installedValue,
   renderTrigger,
   triggerClassName,
   triggerClassNameFn,
@@ -309,7 +314,7 @@
   const { t } = useTranslation()
   const [open, setOpen] = useState(false)
   const localPlaceholder = placeholder || t('common.placeholder.select')
-  const selectedItem = value ? items.find(item => item.value === value) : undefined
+  const selectedItem = items.find(item => item.value === value)
 
   return (
     <PortalToFollowElem
@@ -324,34 +329,33 @@
           : (
             <div
               className={classNames(`
-            group flex items-center justify-between px-2.5 h-9 rounded-lg border-0 bg-components-input-bg-normal hover:bg-state-base-hover-alt text-sm ${readonly ? 'cursor-not-allowed' : 'cursor-pointer'}
+            flex items-center justify-between px-2.5 h-9 rounded-lg border-0 bg-gray-100 text-sm ${readonly ? 'cursor-not-allowed' : 'cursor-pointer'} 
           `, triggerClassName, triggerClassNameFn?.(open))}
               title={selectedItem?.name}
             >
               <span
                 className={`
               grow truncate
-              ${!selectedItem?.name && 'text-components-input-text-placeholder'}
+              ${!selectedItem?.name && 'text-gray-400'}
             `}
               >
                 {selectedItem?.name ?? localPlaceholder}
               </span>
-              <div className='mx-0.5'>{installedValue && selectedItem && selectedItem.value !== installedValue && <Badge>{installedValue} {'->'} {selectedItem.value} </Badge>}</div>
-              <ChevronDownIcon className='h-4 w-4 shrink-0 text-text-quaternary group-hover:text-text-secondary' />
+              <ChevronDownIcon className='shrink-0 h-4 w-4 text-gray-400' />
             </div>
           )}
 
       </PortalToFollowElemTrigger>
       <PortalToFollowElemContent className={`z-20 ${popupClassName}`}>
         <div
-          className={classNames('px-1 py-1 max-h-60 overflow-auto rounded-md text-base shadow-lg border-components-panel-border bg-components-panel-bg border-[0.5px] focus:outline-none sm:text-sm', popupInnerClassName)}
+          className={classNames('px-1 py-1 max-h-60 overflow-auto rounded-md bg-white text-base shadow-lg border-gray-200 border-[0.5px] focus:outline-none sm:text-sm', popupInnerClassName)}
         >
           {items.map((item: Item) => (
             <div
               key={item.value}
               className={`
-                flex h-9 cursor-pointer items-center justify-between rounded-lg px-2.5 text-text-secondary hover:bg-state-base-hover
-                ${item.value === value && 'bg-state-base-hover'}
+                flex items-center justify-between px-2.5 h-9 cursor-pointer rounded-lg hover:bg-gray-100 text-gray-700
+                ${item.value === value && 'bg-gray-100'}
               `}
               title={item.name}
               onClick={() => {
@@ -363,13 +367,10 @@
                 className='w-0 grow truncate'
                 title={item.name}
               >
-                <span className='truncate'>{item.name}</span>
-                {item.value === installedValue && (
-                  <Badge uppercase={true} className='ml-1 shrink-0'>INSTALLED</Badge>
-                )}
+                {item.name}
               </span>
               {!hideChecked && item.value === value && (
-                <RiCheckLine className='h-4 w-4 shrink-0 text-text-accent' />
+                <RiCheckLine className='shrink-0 h-4 w-4 text-text-accent' />
               )}
             </div>
           ))}

--
Gitblit v1.8.0