feat: add new form components including CheckboxField, NumberInputField, SelectField, TextField, and SubmitButton with updated input sizes

This commit is contained in:
twwu 2025-04-17 13:33:33 +08:00
parent 71f78e0d33
commit 0345eb4659
12 changed files with 80 additions and 33 deletions

View File

@ -1,6 +1,6 @@
import cn from '@/utils/classnames'
import { useFieldContext } from '..'
import Checkbox from '../../checkbox'
import { useFieldContext } from '../..'
import Checkbox from '../../../checkbox'
type CheckboxFieldProps = {
label: string;

View File

@ -0,0 +1,37 @@
import React from 'react'
import { useFieldContext } from '../..'
import Label from '../label'
import cn from '@/utils/classnames'
import { InputNumber } from '../../../input-number'
type TextFieldProps = {
label: string
className?: string
labelClassName?: string
}
const NumberInputField = ({
label,
className,
labelClassName,
}: TextFieldProps) => {
const field = useFieldContext<number | undefined>()
return (
<div className={cn('flex flex-col gap-y-0.5', className)}>
<Label
htmlFor={field.name}
label={label}
labelClassName={labelClassName}
/>
<InputNumber
id={field.name}
value={field.state.value}
onChange={value => field.handleChange(value)}
onBlur={field.handleBlur}
/>
</div>
)
}
export default NumberInputField

View File

@ -1,7 +1,7 @@
import cn from '@/utils/classnames'
import { useFieldContext } from '..'
import PureSelect from '../../select/pure'
import Label from './label'
import { useFieldContext } from '../..'
import PureSelect from '../../../select/pure'
import Label from '../label'
type SelectOption = {
value: string

View File

@ -1,7 +1,7 @@
import React from 'react'
import { useFieldContext } from '..'
import Input from '../../input'
import Label from './label'
import { useFieldContext } from '../..'
import Input from '../../../input'
import Label from '../label'
import cn from '@/utils/classnames'
type TextFieldProps = {

View File

@ -1,6 +1,6 @@
import { useStore } from '@tanstack/react-form'
import { useFormContext } from '..'
import Button, { type ButtonProps } from '../../button'
import { useFormContext } from '../..'
import Button, { type ButtonProps } from '../../../button'
type SubmitButtonProps = Omit<ButtonProps, 'disabled' | 'loading' | 'onClick'>

View File

@ -1,8 +1,9 @@
import { createFormHook, createFormHookContexts } from '@tanstack/react-form'
import TextField from './components/text-field'
import CheckboxField from './components/checkbox-field'
import SelectField from './components/select-filed'
import SubmitButton from './components/submit-button'
import TextField from './components/field/text'
import NumberInputField from './components/field/number-input'
import CheckboxField from './components/field/checkbox'
import SelectField from './components/field/select'
import SubmitButton from './components/form/submit-button'
export const { fieldContext, useFieldContext, formContext, useFormContext }
= createFormHookContexts()
@ -10,6 +11,7 @@ export const { fieldContext, useFieldContext, formContext, useFormContext }
export const { useAppForm, withForm } = createFormHook({
fieldComponents: {
TextField,
NumberInputField,
CheckboxField,
SelectField,
},

View File

@ -8,7 +8,7 @@ export type InputNumberProps = {
value?: number
onChange: (value?: number) => void
amount?: number
size?: 'sm' | 'md'
size?: 'regular' | 'large'
max?: number
min?: number
defaultValue?: number
@ -19,7 +19,7 @@ export type InputNumberProps = {
} & Omit<InputProps, 'value' | 'onChange' | 'size' | 'min' | 'max' | 'defaultValue'>
export const InputNumber: FC<InputNumberProps> = (props) => {
const { unit, className, onChange, amount = 1, value, size = 'md', max, min, defaultValue, wrapClassName, controlWrapClassName, controlClassName, disabled, ...rest } = props
const { unit, className, onChange, amount = 1, value, size = 'regular', max, min, defaultValue, wrapClassName, controlWrapClassName, controlClassName, disabled, ...rest } = props
const isValidValue = (v: number) => {
if (max && v > max)
@ -76,29 +76,37 @@ export const InputNumber: FC<InputNumberProps> = (props) => {
onChange(parsed)
}}
unit={unit}
size={size}
/>
<div className={classNames(
'flex flex-col bg-components-input-bg-normal rounded-r-md border-l border-divider-subtle text-text-tertiary focus:shadow-xs',
disabled && 'opacity-50 cursor-not-allowed',
controlWrapClassName)}
>
<button onClick={inc} disabled={disabled} className={classNames(
size === 'sm' ? 'pt-1' : 'pt-1.5',
'px-1.5 hover:bg-components-input-bg-hover',
disabled && 'cursor-not-allowed hover:bg-transparent',
controlClassName,
)}>
<RiArrowUpSLine className='size-3' />
</button>
<button
onClick={dec}
type='button'
onClick={inc}
disabled={disabled}
className={classNames(
size === 'sm' ? 'pb-1' : 'pb-1.5',
size === 'regular' ? 'pt-1' : 'pt-1.5',
'px-1.5 hover:bg-components-input-bg-hover',
disabled && 'cursor-not-allowed hover:bg-transparent',
controlClassName,
)}>
)}
>
<RiArrowUpSLine className='size-3' />
</button>
<button
type='button'
onClick={dec}
disabled={disabled}
className={classNames(
size === 'regular' ? 'pb-1' : 'pb-1.5',
'px-1.5 hover:bg-components-input-bg-hover',
disabled && 'cursor-not-allowed hover:bg-transparent',
controlClassName,
)}
>
<RiArrowDownSLine className='size-3' />
</button>
</div>

View File

@ -30,7 +30,7 @@ export type InputProps = {
wrapperClassName?: string
styleCss?: CSSProperties
unit?: string
} & React.InputHTMLAttributes<HTMLInputElement> & VariantProps<typeof inputVariants>
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> & VariantProps<typeof inputVariants>
const Input = ({
size,

View File

@ -54,7 +54,7 @@ const ParamItem: FC<Props> = ({ className, id, name, noTooltip, tip, step = 0.1,
max={max}
step={step}
amount={step}
size='sm'
size='regular'
value={value}
onChange={(value) => {
onChange(id, value)

View File

@ -47,7 +47,7 @@ export const MaxLengthInput: FC<InputNumberProps> = (props) => {
</div>}>
<InputNumber
type="number"
className='h-9'
size='large'
placeholder={`${maxValue}`}
max={maxValue}
min={1}
@ -70,7 +70,7 @@ export const OverlapInput: FC<InputNumberProps> = (props) => {
</div>}>
<InputNumber
type="number"
className='h-9'
size='large'
placeholder={t('datasetCreation.stepTwo.overlap') || ''}
min={1}
{...props}

View File

@ -40,7 +40,7 @@ const InputCombined: FC<Props> = ({
className={cn(className, 'rounded-l-md')}
value={value}
onChange={onChange}
size='sm'
size='regular'
controlWrapClassName='overflow-hidden'
controlClassName='pt-0 pb-0'
readOnly={readOnly}

View File

@ -133,7 +133,7 @@ export const AgentStrategy = memo((props: AgentStrategyProps) => {
// TODO: maybe empty, handle this
onChange={onChange as any}
defaultValue={defaultValue}
size='sm'
size='regular'
min={def.min}
max={def.max}
className='w-12'