mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-05-03 00:37:48 +08:00
Fix: Fixed some errors in the console (#13317)
### What problem does this PR solve? Fix: Fixed some errors in the console ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { forwardRef } from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { SingleFormSlider } from '../ui/dual-range-slider';
|
||||
import {
|
||||
@ -25,82 +26,96 @@ type SliderInputSwitchFormFieldProps = {
|
||||
numberInputClassName?: string;
|
||||
};
|
||||
|
||||
export function SliderInputSwitchFormField({
|
||||
max,
|
||||
min,
|
||||
step,
|
||||
label,
|
||||
name,
|
||||
defaultValue,
|
||||
onChange,
|
||||
className,
|
||||
checkName,
|
||||
numberInputClassName,
|
||||
}: SliderInputSwitchFormFieldProps) {
|
||||
const form = useFormContext();
|
||||
const disabled = !form.watch(checkName);
|
||||
const { t } = useTranslate('chat');
|
||||
export const SliderInputSwitchFormField = forwardRef<
|
||||
HTMLDivElement,
|
||||
SliderInputSwitchFormFieldProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
max,
|
||||
min,
|
||||
step,
|
||||
label,
|
||||
name,
|
||||
defaultValue,
|
||||
onChange,
|
||||
className,
|
||||
checkName,
|
||||
numberInputClassName,
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const form = useFormContext();
|
||||
const disabled = !form.watch(checkName);
|
||||
const { t } = useTranslate('chat');
|
||||
|
||||
return (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={name}
|
||||
defaultValue={defaultValue}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel tooltip={t(`${label}Tip`)}>{t(label)}</FormLabel>
|
||||
<div
|
||||
className={cn('flex items-center gap-4 justify-between', className)}
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={checkName}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
return (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={name}
|
||||
defaultValue={defaultValue}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel tooltip={t(`${label}Tip`)}>{t(label)}</FormLabel>
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex items-center gap-4 justify-between',
|
||||
className,
|
||||
)}
|
||||
/>
|
||||
<FormControl>
|
||||
<SingleFormSlider
|
||||
{...field}
|
||||
onChange={(value: number) => {
|
||||
onChange?.(value);
|
||||
field.onChange(value);
|
||||
}}
|
||||
max={max}
|
||||
min={min}
|
||||
step={step}
|
||||
disabled={disabled}
|
||||
></SingleFormSlider>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<NumberInput
|
||||
disabled={disabled}
|
||||
className={cn(
|
||||
'h-6 w-10 p-1 border border-border-button rounded-sm',
|
||||
numberInputClassName,
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={checkName}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Switch
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
max={max}
|
||||
min={min}
|
||||
step={step}
|
||||
{...field}
|
||||
onChange={(value: number) => {
|
||||
onChange?.(value);
|
||||
field.onChange(value);
|
||||
}}
|
||||
></NumberInput>
|
||||
</FormControl>
|
||||
</div>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
/>
|
||||
<FormControl>
|
||||
<SingleFormSlider
|
||||
{...field}
|
||||
onChange={(value: number) => {
|
||||
onChange?.(value);
|
||||
field.onChange(value);
|
||||
}}
|
||||
max={max}
|
||||
min={min}
|
||||
step={step}
|
||||
disabled={disabled}
|
||||
></SingleFormSlider>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<NumberInput
|
||||
disabled={disabled}
|
||||
className={cn(
|
||||
'h-6 w-10 p-1 border border-border-button rounded-sm',
|
||||
numberInputClassName,
|
||||
)}
|
||||
max={max}
|
||||
min={min}
|
||||
step={step}
|
||||
{...field}
|
||||
onChange={(value: number) => {
|
||||
onChange?.(value);
|
||||
field.onChange(value);
|
||||
}}
|
||||
></NumberInput>
|
||||
</FormControl>
|
||||
</div>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
SliderInputSwitchFormField.displayName = 'SliderInputSwitchFormField';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { FormLayout } from '@/constants/form';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { ReactNode, useMemo } from 'react';
|
||||
import { forwardRef, ReactNode, useMemo } from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { SingleFormSlider } from './ui/dual-range-slider';
|
||||
import {
|
||||
@ -29,88 +29,104 @@ type SliderInputFormFieldProps = {
|
||||
percentage?: boolean;
|
||||
} & FormLayoutType;
|
||||
|
||||
export function SliderInputFormField({
|
||||
max,
|
||||
min,
|
||||
step,
|
||||
label,
|
||||
name,
|
||||
tooltip,
|
||||
defaultValue,
|
||||
className,
|
||||
numberInputClassName,
|
||||
layout = FormLayout.Horizontal,
|
||||
percentage = false,
|
||||
}: SliderInputFormFieldProps) {
|
||||
const form = useFormContext();
|
||||
export const SliderInputFormField = forwardRef<
|
||||
HTMLDivElement,
|
||||
SliderInputFormFieldProps
|
||||
>(
|
||||
(
|
||||
{
|
||||
max,
|
||||
min,
|
||||
step,
|
||||
label,
|
||||
name,
|
||||
tooltip,
|
||||
defaultValue,
|
||||
className,
|
||||
numberInputClassName,
|
||||
layout = FormLayout.Horizontal,
|
||||
percentage = false,
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const form = useFormContext();
|
||||
|
||||
const isHorizontal = useMemo(() => layout !== FormLayout.Vertical, [layout]);
|
||||
const displayMax = percentage ? (max || 1) * 100 : max;
|
||||
const displayMin = percentage ? (min || 0) * 100 : min;
|
||||
const displayStep = percentage ? (step || 0.01) * 100 : step;
|
||||
return (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={name}
|
||||
defaultValue={defaultValue || 0}
|
||||
render={({ field }) => (
|
||||
<FormItem
|
||||
className={cn({ 'flex items-center gap-1 space-y-0': isHorizontal })}
|
||||
>
|
||||
<FormLabel
|
||||
tooltip={tooltip}
|
||||
const isHorizontal = useMemo(
|
||||
() => layout !== FormLayout.Vertical,
|
||||
[layout],
|
||||
);
|
||||
const displayMax = percentage ? (max || 1) * 100 : max;
|
||||
const displayMin = percentage ? (min || 0) * 100 : min;
|
||||
const displayStep = percentage ? (step || 0.01) * 100 : step;
|
||||
return (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={name}
|
||||
defaultValue={defaultValue || 0}
|
||||
render={({ field }) => (
|
||||
<FormItem
|
||||
ref={ref}
|
||||
className={cn({
|
||||
'text-sm whitespace-break-spaces w-1/4': isHorizontal,
|
||||
'flex items-center gap-1 space-y-0': isHorizontal,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</FormLabel>
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center gap-4 justify-between',
|
||||
{ 'w-3/4': isHorizontal },
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<FormControl>
|
||||
<SingleFormSlider
|
||||
{...field}
|
||||
value={percentage ? field.value * 100 : field.value}
|
||||
onChange={(value) =>
|
||||
field.onChange(percentage ? value / 100 : value)
|
||||
}
|
||||
max={displayMax}
|
||||
min={displayMin}
|
||||
step={displayStep}
|
||||
></SingleFormSlider>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<NumberInput
|
||||
className={cn(
|
||||
'h-6 w-10 p-0 text-center bg-bg-input border border-border-button text-text-secondary',
|
||||
'[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
|
||||
numberInputClassName,
|
||||
)}
|
||||
max={displayMax}
|
||||
min={displayMin}
|
||||
step={displayStep}
|
||||
value={
|
||||
percentage ? (field.value * 100).toFixed(0) : field.value
|
||||
}
|
||||
onChange={(val) => {
|
||||
const value = Number(val || 0);
|
||||
if (!isNaN(value)) {
|
||||
field.onChange(
|
||||
percentage ? (value / 100).toFixed(0) : value,
|
||||
);
|
||||
<FormLabel
|
||||
tooltip={tooltip}
|
||||
className={cn({
|
||||
'text-sm whitespace-break-spaces w-1/4': isHorizontal,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</FormLabel>
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center gap-4 justify-between',
|
||||
{ 'w-3/4': isHorizontal },
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<FormControl>
|
||||
<SingleFormSlider
|
||||
{...field}
|
||||
value={percentage ? field.value * 100 : field.value}
|
||||
onChange={(value) =>
|
||||
field.onChange(percentage ? value / 100 : value)
|
||||
}
|
||||
}}
|
||||
></NumberInput>
|
||||
</FormControl>
|
||||
</div>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
max={displayMax}
|
||||
min={displayMin}
|
||||
step={displayStep}
|
||||
></SingleFormSlider>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<NumberInput
|
||||
className={cn(
|
||||
'h-6 w-10 p-0 text-center bg-bg-input border border-border-button text-text-secondary',
|
||||
'[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
|
||||
numberInputClassName,
|
||||
)}
|
||||
max={displayMax}
|
||||
min={displayMin}
|
||||
step={displayStep}
|
||||
value={
|
||||
percentage ? (field.value * 100).toFixed(0) : field.value
|
||||
}
|
||||
onChange={(val) => {
|
||||
const value = Number(val || 0);
|
||||
if (!isNaN(value)) {
|
||||
field.onChange(
|
||||
percentage ? (value / 100).toFixed(0) : value,
|
||||
);
|
||||
}
|
||||
}}
|
||||
></NumberInput>
|
||||
</FormControl>
|
||||
</div>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
SliderInputFormField.displayName = 'SliderInputFormField';
|
||||
|
||||
@ -6,25 +6,29 @@ import * as React from 'react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
function RadioGroup({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
|
||||
const RadioGroup = React.forwardRef<
|
||||
React.ElementRef<typeof RadioGroupPrimitive.Root>,
|
||||
React.ComponentProps<typeof RadioGroupPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => {
|
||||
return (
|
||||
<RadioGroupPrimitive.Root
|
||||
ref={ref}
|
||||
data-slot="radio-group"
|
||||
className={cn('grid gap-3', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
function RadioGroupItem({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {
|
||||
RadioGroup.displayName = 'RadioGroup';
|
||||
|
||||
const RadioGroupItem = React.forwardRef<
|
||||
React.ElementRef<typeof RadioGroupPrimitive.Item>,
|
||||
React.ComponentProps<typeof RadioGroupPrimitive.Item>
|
||||
>(({ className, ...props }, ref) => {
|
||||
return (
|
||||
<RadioGroupPrimitive.Item
|
||||
ref={ref}
|
||||
data-slot="radio-group-item"
|
||||
className={cn(
|
||||
'text-primary aspect-square size-4 shrink-0 rounded-full',
|
||||
@ -45,6 +49,8 @@ function RadioGroupItem({
|
||||
</RadioGroupPrimitive.Indicator>
|
||||
</RadioGroupPrimitive.Item>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
RadioGroupItem.displayName = 'RadioGroupItem';
|
||||
|
||||
export { RadioGroup, RadioGroupItem };
|
||||
|
||||
@ -74,59 +74,66 @@ type RadioGroupProps = {
|
||||
direction?: 'horizontal' | 'vertical';
|
||||
};
|
||||
|
||||
function Group({
|
||||
value,
|
||||
defaultValue,
|
||||
onChange,
|
||||
disabled,
|
||||
children,
|
||||
className,
|
||||
direction = 'horizontal',
|
||||
}: RadioGroupProps) {
|
||||
const [internalValue, setInternalValue] = useState(defaultValue || '');
|
||||
const Group = React.forwardRef<HTMLDivElement, RadioGroupProps>(
|
||||
(
|
||||
{
|
||||
value,
|
||||
defaultValue,
|
||||
onChange,
|
||||
disabled,
|
||||
children,
|
||||
className,
|
||||
direction = 'horizontal',
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const [internalValue, setInternalValue] = useState(defaultValue || '');
|
||||
|
||||
const isControlled = value !== undefined;
|
||||
const mergedValue = isControlled ? value : internalValue;
|
||||
const isControlled = value !== undefined;
|
||||
const mergedValue = isControlled ? value : internalValue;
|
||||
|
||||
const handleChange = (val: string | number) => {
|
||||
if (disabled) return;
|
||||
const handleChange = (val: string | number) => {
|
||||
if (disabled) return;
|
||||
|
||||
if (!isControlled) {
|
||||
setInternalValue(val);
|
||||
}
|
||||
if (!isControlled) {
|
||||
setInternalValue(val);
|
||||
}
|
||||
|
||||
if (onChange) {
|
||||
onChange(val);
|
||||
}
|
||||
};
|
||||
if (onChange) {
|
||||
onChange(val);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<RadioGroupContext.Provider
|
||||
value={{
|
||||
value: mergedValue,
|
||||
onChange: handleChange,
|
||||
disabled,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
'flex gap-4',
|
||||
direction === 'vertical' ? 'flex-col' : 'flex-row',
|
||||
className,
|
||||
)}
|
||||
return (
|
||||
<RadioGroupContext.Provider
|
||||
value={{
|
||||
value: mergedValue,
|
||||
onChange: handleChange,
|
||||
disabled,
|
||||
}}
|
||||
>
|
||||
{React.Children.map(children, (child) =>
|
||||
React.cloneElement(child as React.ReactElement, {
|
||||
disabled: disabled || child?.props?.disabled,
|
||||
}),
|
||||
)}
|
||||
</div>
|
||||
</RadioGroupContext.Provider>
|
||||
);
|
||||
}
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex gap-4',
|
||||
direction === 'vertical' ? 'flex-col' : 'flex-row',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{React.Children.map(children, (child) =>
|
||||
React.cloneElement(child as React.ReactElement, {
|
||||
disabled: disabled || child?.props?.disabled,
|
||||
}),
|
||||
)}
|
||||
</div>
|
||||
</RadioGroupContext.Provider>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
const RadioComponent = Object.assign(Radio, {
|
||||
Group,
|
||||
});
|
||||
|
||||
Group.displayName = 'RadioGroup';
|
||||
export { RadioComponent as Radio };
|
||||
|
||||
@ -59,63 +59,71 @@ export interface SegmentedProps extends Omit<
|
||||
buttonSize?: keyof typeof segmentedVariants.buttonSize;
|
||||
}
|
||||
|
||||
export function Segmented({
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
className,
|
||||
activeClassName,
|
||||
itemClassName,
|
||||
rounded = 'default',
|
||||
sizeType = 'default',
|
||||
buttonSize = 'default',
|
||||
}: SegmentedProps) {
|
||||
const [selectedValue, setSelectedValue] = React.useState<
|
||||
SegmentedValue | undefined
|
||||
>(value);
|
||||
React.useEffect(() => {
|
||||
setSelectedValue(value);
|
||||
}, [value]);
|
||||
const handleOnChange = (e: SegmentedValue) => {
|
||||
if (onChange) {
|
||||
onChange(e);
|
||||
}
|
||||
setSelectedValue(e);
|
||||
};
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center p-1 gap-2 bg-bg-card',
|
||||
segmentedVariants.round[rounded],
|
||||
segmentedVariants.size[sizeType],
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{options.map((option) => {
|
||||
const isObject = typeof option === 'object';
|
||||
const actualValue = isObject ? option.value : option;
|
||||
export const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
|
||||
(
|
||||
{
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
className,
|
||||
activeClassName,
|
||||
itemClassName,
|
||||
rounded = 'default',
|
||||
sizeType = 'default',
|
||||
buttonSize = 'default',
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const [selectedValue, setSelectedValue] = React.useState<
|
||||
SegmentedValue | undefined
|
||||
>(value);
|
||||
React.useEffect(() => {
|
||||
setSelectedValue(value);
|
||||
}, [value]);
|
||||
const handleOnChange = (e: SegmentedValue) => {
|
||||
if (onChange) {
|
||||
onChange(e);
|
||||
}
|
||||
setSelectedValue(e);
|
||||
};
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex items-center p-1 gap-2 bg-bg-card',
|
||||
segmentedVariants.round[rounded],
|
||||
segmentedVariants.size[sizeType],
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{options.map((option) => {
|
||||
const isObject = typeof option === 'object';
|
||||
const actualValue = isObject ? option.value : option;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={actualValue}
|
||||
className={cn(
|
||||
'inline-flex items-center text-base font-normal cursor-pointer',
|
||||
segmentedVariants.round[rounded],
|
||||
segmentedVariants.buttonSize[buttonSize],
|
||||
{
|
||||
'text-text-primary bg-bg-base': selectedValue === actualValue,
|
||||
},
|
||||
itemClassName,
|
||||
activeClassName && selectedValue === actualValue
|
||||
? activeClassName
|
||||
: '',
|
||||
)}
|
||||
onClick={() => handleOnChange(actualValue)}
|
||||
>
|
||||
{isObject ? option.label : option}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div
|
||||
key={actualValue}
|
||||
className={cn(
|
||||
'inline-flex items-center text-base font-normal cursor-pointer',
|
||||
segmentedVariants.round[rounded],
|
||||
segmentedVariants.buttonSize[buttonSize],
|
||||
{
|
||||
'text-text-primary bg-bg-base': selectedValue === actualValue,
|
||||
},
|
||||
itemClassName,
|
||||
activeClassName && selectedValue === actualValue
|
||||
? activeClassName
|
||||
: '',
|
||||
)}
|
||||
onClick={() => handleOnChange(actualValue)}
|
||||
>
|
||||
{isObject ? option.label : option}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Segmented.displayName = 'Segmented';
|
||||
|
||||
Reference in New Issue
Block a user