Feat: Add DualRangeSlider #3221 (#5386)

### What problem does this PR solve?

Feat: Add DualRangeSlider #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu 2025-02-26 17:02:42 +08:00 committed by GitHub
parent cdcaae17c6
commit 63e3398f49
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 127 additions and 21 deletions

View File

@ -98,6 +98,7 @@ export function KnowledgeBaseFormField() {
placeholder={t('knowledgeBasesMessage')}
variant="inverted"
maxCount={100}
defaultValue={field.value}
{...field}
/>
</FormControl>

View File

@ -3,6 +3,7 @@ import { useTranslate } from '@/hooks/common-hooks';
import { useSelectLlmOptionsByModelType } from '@/hooks/llm-hooks';
import { Select as AntSelect, Form, Slider } from 'antd';
import { useFormContext } from 'react-hook-form';
import { SingleFormSlider } from './ui/dual-range-slider';
import {
FormControl,
FormField,
@ -19,7 +20,6 @@ import {
SelectTrigger,
SelectValue,
} from './ui/select';
import { FormSlider } from './ui/slider';
type FieldType = {
rerank_id?: string;
@ -140,7 +140,11 @@ export function RerankFormFields() {
<FormItem>
<FormLabel>{t('topK')}</FormLabel>
<FormControl>
<FormSlider {...field} max={2048} min={1}></FormSlider>
<SingleFormSlider
{...field}
max={2048}
min={1}
></SingleFormSlider>
</FormControl>
<FormMessage />
</FormItem>

View File

@ -1,6 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { Form, Slider } from 'antd';
import { useFormContext } from 'react-hook-form';
import { SingleFormSlider } from '../ui/dual-range-slider';
import {
FormControl,
FormField,
@ -8,7 +9,6 @@ import {
FormLabel,
FormMessage,
} from '../ui/form';
import { FormSlider } from '../ui/slider';
type FieldType = {
similarity_threshold?: number;
@ -51,28 +51,51 @@ const SimilaritySlider = ({
export default SimilaritySlider;
interface SimilaritySliderFormFieldProps {
name?: string;
vectorSimilarityWeightName?: string;
}
export function SimilaritySliderFormField({
name = 'vector_similarity_weight',
vectorSimilarityWeightName = 'vector_similarity_weight',
}: SimilaritySliderFormFieldProps) {
const form = useFormContext();
const { t } = useTranslate('knowledgeDetails');
return (
<FormField
control={form.control}
name={name}
render={({ field }) => (
<FormItem>
<FormLabel>{t('vectorSimilarityWeight')}</FormLabel>
<FormControl>
<FormSlider {...field}></FormSlider>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<>
<FormField
control={form.control}
name={'similarity_threshold'}
render={({ field }) => (
<FormItem>
<FormLabel>{t('similarityThreshold')}</FormLabel>
<FormControl>
<SingleFormSlider
{...field}
max={1}
step={0.01}
></SingleFormSlider>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name={vectorSimilarityWeightName}
render={({ field }) => (
<FormItem>
<FormLabel>{t('vectorSimilarityWeight')}</FormLabel>
<FormControl>
<SingleFormSlider
{...field}
max={1}
step={0.01}
></SingleFormSlider>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</>
);
}

View File

@ -1,6 +1,7 @@
import { useTranslate } from '@/hooks/common-hooks';
import { Form, Slider } from 'antd';
import { useFormContext } from 'react-hook-form';
import { SingleFormSlider } from './ui/dual-range-slider';
import {
FormControl,
FormField,
@ -8,7 +9,6 @@ import {
FormLabel,
FormMessage,
} from './ui/form';
import { FormSlider } from './ui/slider';
type FieldType = {
top_n?: number;
@ -52,7 +52,7 @@ export function TopNFormField({ max = 30 }: SimilaritySliderFormFieldProps) {
<FormItem>
<FormLabel>{t('topN')}</FormLabel>
<FormControl>
<FormSlider {...field} max={max}></FormSlider>
<SingleFormSlider {...field} max={max}></SingleFormSlider>
</FormControl>
<FormMessage />
</FormItem>

View File

@ -0,0 +1,78 @@
'use client';
import * as SliderPrimitive from '@radix-ui/react-slider';
import * as React from 'react';
import { cn } from '@/lib/utils';
interface DualRangeSliderProps
extends React.ComponentProps<typeof SliderPrimitive.Root> {
labelPosition?: 'top' | 'bottom';
label?: (value: number | undefined) => React.ReactNode;
}
const DualRangeSlider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
DualRangeSliderProps
>(({ className, label, labelPosition = 'top', ...props }, ref) => {
const initialValue = Array.isArray(props.value)
? props.value
: [props.min, props.max];
return (
<SliderPrimitive.Root
ref={ref}
className={cn(
'relative flex w-full touch-none select-none items-center',
className,
)}
{...props}
>
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track>
{initialValue.map((value, index) => (
<React.Fragment key={index}>
<SliderPrimitive.Thumb className="relative block h-4 w-4 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 cursor-pointer">
{label && (
<span
className={cn(
'absolute flex w-full justify-center',
labelPosition === 'top' && '-top-7',
labelPosition === 'bottom' && 'top-4',
)}
>
{label(value)}
</span>
)}
</SliderPrimitive.Thumb>
</React.Fragment>
))}
</SliderPrimitive.Root>
);
});
DualRangeSlider.displayName = 'DualRangeSlider';
type SingleSliderProps = Omit<
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>,
'onChange' | 'value'
> & { onChange: (value: number) => void; value: number };
const SingleFormSlider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
SingleSliderProps
>(({ value, onChange, ...props }, ref) => {
return (
<DualRangeSlider
ref={ref}
label={(value) => value}
value={[value]}
onValueChange={(vals) => {
onChange(vals[0]);
}}
{...props}
/>
);
});
export { DualRangeSlider, SingleFormSlider };

View File

@ -26,7 +26,7 @@ const RetrievalForm = ({ form, node }: INextOperatorForm) => {
}}
>
<DynamicVariableForm></DynamicVariableForm>
<SimilaritySliderFormField name="keywords_similarity_weight"></SimilaritySliderFormField>
<SimilaritySliderFormField vectorSimilarityWeightName="keywords_similarity_weight"></SimilaritySliderFormField>
<TopNFormField></TopNFormField>
<RerankFormFields></RerankFormFields>
<KnowledgeBaseFormField></KnowledgeBaseFormField>