fix: node default
parent
2613a380b6
commit
66176c4d71
@ -0,0 +1,58 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { RiEditLine } from '@remixicon/react'
|
||||||
|
import cn from '@/utils/classnames'
|
||||||
|
import SegmentedControl from '@/app/components/base/segmented-control'
|
||||||
|
import { VariableX } from '@/app/components/base/icons/src/vender/workflow'
|
||||||
|
import type { LabelProps } from '../label'
|
||||||
|
import Label from '../label'
|
||||||
|
|
||||||
|
type VariableOrConstantInputFieldProps = {
|
||||||
|
label: string
|
||||||
|
labelOptions?: Omit<LabelProps, 'htmlFor' | 'label'>
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const VariableOrConstantInputField = ({
|
||||||
|
className,
|
||||||
|
label,
|
||||||
|
labelOptions,
|
||||||
|
}: VariableOrConstantInputFieldProps) => {
|
||||||
|
const [variableType, setVariableType] = useState('variable')
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
{
|
||||||
|
Icon: VariableX,
|
||||||
|
text: '',
|
||||||
|
value: 'variable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Icon: RiEditLine,
|
||||||
|
text: '',
|
||||||
|
value: 'constant',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const handleVariableOrConstantChange = (value: string) => {
|
||||||
|
setVariableType(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cn('flex flex-col gap-y-0.5', className)}>
|
||||||
|
<Label
|
||||||
|
htmlFor={'variable-or-constant'}
|
||||||
|
label={label}
|
||||||
|
{...(labelOptions ?? {})}
|
||||||
|
/>
|
||||||
|
<div className='flex items-center'>
|
||||||
|
<SegmentedControl
|
||||||
|
className='mr-1 shrink-0'
|
||||||
|
value={variableType}
|
||||||
|
onChange={handleVariableOrConstantChange}
|
||||||
|
options={options as any}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VariableOrConstantInputField
|
||||||
@ -0,0 +1,239 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { type InputFieldConfiguration, InputFieldType } from './types'
|
||||||
|
import { withForm } from '../..'
|
||||||
|
import { useStore } from '@tanstack/react-form'
|
||||||
|
|
||||||
|
type InputFieldProps<T> = {
|
||||||
|
initialData?: T
|
||||||
|
config: InputFieldConfiguration<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodePanelField = <T,>({
|
||||||
|
initialData,
|
||||||
|
config,
|
||||||
|
}: InputFieldProps<T>) => withForm({
|
||||||
|
defaultValues: initialData,
|
||||||
|
render: function Render({
|
||||||
|
form,
|
||||||
|
}) {
|
||||||
|
const {
|
||||||
|
type,
|
||||||
|
label,
|
||||||
|
placeholder,
|
||||||
|
variable,
|
||||||
|
tooltip,
|
||||||
|
showConditions,
|
||||||
|
max,
|
||||||
|
min,
|
||||||
|
required,
|
||||||
|
showOptional,
|
||||||
|
supportFile,
|
||||||
|
description,
|
||||||
|
options,
|
||||||
|
listeners,
|
||||||
|
popupProps,
|
||||||
|
} = config
|
||||||
|
|
||||||
|
const isAllConditionsMet = useStore(form.store, (state) => {
|
||||||
|
const fieldValues = state.values
|
||||||
|
return showConditions.every((condition) => {
|
||||||
|
const { variable, value } = condition
|
||||||
|
const fieldValue = fieldValues[variable as keyof typeof fieldValues]
|
||||||
|
return fieldValue === value
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!isAllConditionsMet)
|
||||||
|
return <></>
|
||||||
|
|
||||||
|
if (type === InputFieldType.textInput) {
|
||||||
|
return (
|
||||||
|
<form.AppField
|
||||||
|
name={variable}
|
||||||
|
children={field => (
|
||||||
|
<field.TextField
|
||||||
|
label={label}
|
||||||
|
labelOptions={{
|
||||||
|
tooltip,
|
||||||
|
isRequired: required,
|
||||||
|
showOptional,
|
||||||
|
}}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === InputFieldType.numberInput) {
|
||||||
|
return (
|
||||||
|
<form.AppField
|
||||||
|
name={variable}
|
||||||
|
children={field => (
|
||||||
|
<field.NumberInputField
|
||||||
|
label={label}
|
||||||
|
labelOptions={{
|
||||||
|
tooltip,
|
||||||
|
isRequired: required,
|
||||||
|
showOptional,
|
||||||
|
}}
|
||||||
|
placeholder={placeholder}
|
||||||
|
max={max}
|
||||||
|
min={min}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === InputFieldType.numberSlider) {
|
||||||
|
return (
|
||||||
|
<form.AppField
|
||||||
|
name={variable}
|
||||||
|
children={field => (
|
||||||
|
<field.NumberSliderField
|
||||||
|
label={label}
|
||||||
|
labelOptions={{
|
||||||
|
tooltip,
|
||||||
|
isRequired: required,
|
||||||
|
showOptional,
|
||||||
|
}}
|
||||||
|
description={description}
|
||||||
|
max={max}
|
||||||
|
min={min}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === InputFieldType.checkbox) {
|
||||||
|
return (
|
||||||
|
<form.AppField
|
||||||
|
name={variable}
|
||||||
|
children={field => (
|
||||||
|
<field.CheckboxField
|
||||||
|
label={label}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === InputFieldType.select) {
|
||||||
|
return (
|
||||||
|
<form.AppField
|
||||||
|
name={variable}
|
||||||
|
children={field => (
|
||||||
|
<field.SelectField
|
||||||
|
label={label}
|
||||||
|
labelOptions={{
|
||||||
|
tooltip,
|
||||||
|
isRequired: required,
|
||||||
|
showOptional,
|
||||||
|
}}
|
||||||
|
options={options!}
|
||||||
|
popupProps={popupProps}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === InputFieldType.inputTypeSelect) {
|
||||||
|
return (
|
||||||
|
<form.AppField
|
||||||
|
name={variable}
|
||||||
|
listeners={listeners}
|
||||||
|
children={field => (
|
||||||
|
<field.InputTypeSelectField
|
||||||
|
label={label}
|
||||||
|
labelOptions={{
|
||||||
|
tooltip,
|
||||||
|
isRequired: required,
|
||||||
|
showOptional,
|
||||||
|
}}
|
||||||
|
supportFile={!!supportFile}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === InputFieldType.uploadMethod) {
|
||||||
|
return (
|
||||||
|
<form.AppField
|
||||||
|
name={variable}
|
||||||
|
children={field => (
|
||||||
|
<field.UploadMethodField
|
||||||
|
label={label}
|
||||||
|
labelOptions={{
|
||||||
|
tooltip,
|
||||||
|
isRequired: required,
|
||||||
|
showOptional,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === InputFieldType.fileTypes) {
|
||||||
|
return (
|
||||||
|
<form.AppField
|
||||||
|
name={variable}
|
||||||
|
children={field => (
|
||||||
|
<field.FileTypesField
|
||||||
|
label={label}
|
||||||
|
labelOptions={{
|
||||||
|
tooltip,
|
||||||
|
isRequired: required,
|
||||||
|
showOptional,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === InputFieldType.options) {
|
||||||
|
return (
|
||||||
|
<form.AppField
|
||||||
|
name={variable}
|
||||||
|
children={field => (
|
||||||
|
<field.OptionsField
|
||||||
|
label={label}
|
||||||
|
labelOptions={{
|
||||||
|
tooltip,
|
||||||
|
isRequired: required,
|
||||||
|
showOptional,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === InputFieldType.variableOrConstant) {
|
||||||
|
return (
|
||||||
|
<form.AppField
|
||||||
|
name={variable}
|
||||||
|
children={field => (
|
||||||
|
<field.VariableOrConstantInputField
|
||||||
|
label={label}
|
||||||
|
labelOptions={{
|
||||||
|
tooltip,
|
||||||
|
isRequired: required,
|
||||||
|
showOptional,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <></>
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default NodePanelField
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
import type { DeepKeys, FieldListeners } from '@tanstack/react-form'
|
||||||
|
import type { NumberConfiguration, SelectConfiguration, ShowCondition } from '../base/types'
|
||||||
|
|
||||||
|
export enum InputFieldType {
|
||||||
|
textInput = 'textInput',
|
||||||
|
numberInput = 'numberInput',
|
||||||
|
numberSlider = 'numberSlider',
|
||||||
|
checkbox = 'checkbox',
|
||||||
|
options = 'options',
|
||||||
|
select = 'select',
|
||||||
|
inputTypeSelect = 'inputTypeSelect',
|
||||||
|
uploadMethod = 'uploadMethod',
|
||||||
|
fileTypes = 'fileTypes',
|
||||||
|
variableOrConstant = 'variableOrConstant',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InputTypeSelectConfiguration = {
|
||||||
|
supportFile: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NumberSliderConfiguration = {
|
||||||
|
description: string
|
||||||
|
max?: number
|
||||||
|
min?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InputFieldConfiguration<T> = {
|
||||||
|
label: string
|
||||||
|
variable: DeepKeys<T> // Variable name
|
||||||
|
maxLength?: number // Max length for text input
|
||||||
|
placeholder?: string
|
||||||
|
required: boolean
|
||||||
|
showOptional?: boolean // show optional label
|
||||||
|
showConditions: ShowCondition<T>[] // Show this field only when all conditions are met
|
||||||
|
type: InputFieldType
|
||||||
|
tooltip?: string // Tooltip for this field
|
||||||
|
listeners?: FieldListeners<T, DeepKeys<T>> // Listener for this field
|
||||||
|
} & NumberConfiguration & Partial<InputTypeSelectConfiguration>
|
||||||
|
& Partial<NumberSliderConfiguration>
|
||||||
|
& Partial<SelectConfiguration>
|
||||||
Loading…
Reference in New Issue