Compare commits

...

2 Commits

Author SHA1 Message Date
yyh
674432b7a7 fix test 2026-02-18 21:45:06 +08:00
yyh
1c1a724173 refactor(web): make Switch controlled-only and migrate call sites 2026-02-18 20:32:39 +08:00
58 changed files with 182 additions and 223 deletions

View File

@@ -94,7 +94,7 @@ const ConfigPopup: FC<PopupProps> = ({
const switchContent = (
<Switch
className="ml-3"
defaultValue={enabled}
value={enabled}
onChange={onStatusChange}
disabled={providerAllNotConfigured}
/>

View File

@@ -144,7 +144,7 @@ const Annotation: FC<Props> = (props) => {
return (
<div className="flex h-full flex-col">
<p className="system-sm-regular text-text-tertiary">{t('description', { ns: 'appLog' })}</p>
<p className="text-text-tertiary system-sm-regular">{t('description', { ns: 'appLog' })}</p>
<div className="relative flex h-full flex-1 flex-col py-4">
<Filter appId={appDetail.id} queryParams={queryParams} setQueryParams={setQueryParams}>
<div className="flex items-center space-x-2">
@@ -152,10 +152,10 @@ const Annotation: FC<Props> = (props) => {
<>
<div className={cn(!annotationConfig?.enabled && 'pr-2', 'flex h-7 items-center space-x-1 rounded-lg border border-components-panel-border bg-components-panel-bg-blur pl-2')}>
<MessageFast className="h-4 w-4 text-util-colors-indigo-indigo-600" />
<div className="system-sm-medium text-text-primary">{t('name', { ns: 'appAnnotation' })}</div>
<div className="text-text-primary system-sm-medium">{t('name', { ns: 'appAnnotation' })}</div>
<Switch
key={controlRefreshSwitch}
defaultValue={annotationConfig?.enabled}
value={annotationConfig?.enabled ?? false}
size="md"
onChange={async (value) => {
if (value) {

View File

@@ -121,7 +121,7 @@ const ConfigVision: FC = () => {
<ParamConfig />
<div className="ml-1 mr-3 h-3.5 w-[1px] bg-divider-regular"></div>
<Switch
defaultValue={isImageEnabled}
value={isImageEnabled}
onChange={handleChange}
size="md"
/>

View File

@@ -298,7 +298,7 @@ const AgentTools: FC = () => {
<div className={cn(item.isDeleted && 'opacity-50')}>
{!item.notAuthor && (
<Switch
defaultValue={item.isDeleted ? false : item.enabled}
value={item.isDeleted ? false : item.enabled}
disabled={item.isDeleted || readonly}
size="md"
onChange={(enabled) => {

View File

@@ -69,7 +69,7 @@ const ConfigAudio: FC = () => {
<div className="flex shrink-0 items-center">
<div className="ml-1 mr-3 h-3.5 w-[1px] bg-divider-subtle"></div>
<Switch
defaultValue={isAudioEnabled}
value={isAudioEnabled}
onChange={handleChange}
size="md"
/>

View File

@@ -69,7 +69,7 @@ const ConfigDocument: FC = () => {
<div className="flex shrink-0 items-center">
<div className="ml-1 mr-3 h-3.5 w-[1px] bg-divider-subtle"></div>
<Switch
defaultValue={isDocumentEnabled}
value={isDocumentEnabled}
onChange={handleChange}
size="md"
/>

View File

@@ -188,14 +188,14 @@ const ConfigContent: FC<Props> = ({
return (
<div>
<div className="system-xl-semibold text-text-primary">{t('retrievalSettings', { ns: 'dataset' })}</div>
<div className="system-xs-regular text-text-tertiary">
<div className="text-text-primary system-xl-semibold">{t('retrievalSettings', { ns: 'dataset' })}</div>
<div className="text-text-tertiary system-xs-regular">
{t('defaultRetrievalTip', { ns: 'dataset' })}
</div>
{type === RETRIEVE_TYPE.multiWay && (
<>
<div className="my-2 flex flex-col items-center py-1">
<div className="system-xs-semibold-uppercase mb-2 mr-2 shrink-0 text-text-secondary">
<div className="mb-2 mr-2 shrink-0 text-text-secondary system-xs-semibold-uppercase">
{t('rerankSettings', { ns: 'dataset' })}
</div>
<Divider bgStyle="gradient" className="m-0 !h-px" />
@@ -203,21 +203,21 @@ const ConfigContent: FC<Props> = ({
{
selectedDatasetsMode.inconsistentEmbeddingModel
&& (
<div className="system-xs-medium mt-4 text-text-warning">
<div className="mt-4 text-text-warning system-xs-medium">
{t('inconsistentEmbeddingModelTip', { ns: 'dataset' })}
</div>
)
}
{
selectedDatasetsMode.mixtureInternalAndExternal && (
<div className="system-xs-medium mt-4 text-text-warning">
<div className="mt-4 text-text-warning system-xs-medium">
{t('mixtureInternalAndExternalTip', { ns: 'dataset' })}
</div>
)
}
{
selectedDatasetsMode.allExternal && (
<div className="system-xs-medium mt-4 text-text-warning">
<div className="mt-4 text-text-warning system-xs-medium">
{t('allExternalTip', { ns: 'dataset' })}
</div>
)
@@ -225,7 +225,7 @@ const ConfigContent: FC<Props> = ({
{
selectedDatasetsMode.mixtureHighQualityAndEconomic
&& (
<div className="system-xs-medium mt-4 text-text-warning">
<div className="mt-4 text-text-warning system-xs-medium">
{t('mixtureHighQualityAndEconomicTip', { ns: 'dataset' })}
</div>
)
@@ -238,7 +238,7 @@ const ConfigContent: FC<Props> = ({
<div
key={option.value}
className={cn(
'system-sm-medium flex h-8 w-[calc((100%-8px)/2)] cursor-pointer items-center justify-center rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary',
'flex h-8 w-[calc((100%-8px)/2)] cursor-pointer items-center justify-center rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg text-text-secondary system-sm-medium',
selectedRerankMode === option.value && 'border-[1.5px] border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg text-text-primary',
)}
onClick={() => handleRerankModeChange(option.value)}
@@ -267,12 +267,12 @@ const ConfigContent: FC<Props> = ({
canManuallyToggleRerank && (
<Switch
size="md"
defaultValue={showRerankModel}
value={showRerankModel ?? false}
onChange={handleManuallyToggleRerank}
/>
)
}
<div className="system-sm-semibold ml-1 leading-[32px] text-text-secondary">{t('modelProvider.rerankModel.key', { ns: 'common' })}</div>
<div className="ml-1 leading-[32px] text-text-secondary system-sm-semibold">{t('modelProvider.rerankModel.key', { ns: 'common' })}</div>
<Tooltip
popupContent={(
<div className="w-[200px]">

View File

@@ -130,7 +130,7 @@ const Tools = () => {
className="flex h-7 cursor-pointer items-center px-3 text-xs font-medium text-gray-700"
onClick={() => handleOpenExternalDataToolModal({}, -1)}
>
<RiAddLine className="mr-[5px] h-3.5 w-3.5 " />
<RiAddLine className="mr-[5px] h-3.5 w-3.5" />
{t('operation.add', { ns: 'common' })}
</div>
</div>
@@ -180,7 +180,7 @@ const Tools = () => {
<div className="ml-2 mr-3 hidden h-3.5 w-[1px] bg-gray-200 group-hover:block" />
<Switch
size="l"
defaultValue={item.enabled}
value={item.enabled ?? false}
onChange={(enabled: boolean) => handleSaveExternalDataToolModal({ ...item, enabled }, index)}
/>
</div>

View File

@@ -260,7 +260,7 @@ function AppCard({
offset={24}
>
<div>
<Switch defaultValue={runningStatus} onChange={onChangeStatus} disabled={toggleDisabled} />
<Switch value={runningStatus} onChange={onChangeStatus} disabled={toggleDisabled} />
</div>
</Tooltip>
</div>

View File

@@ -281,7 +281,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
<div className="flex items-center justify-between">
<div className={cn('system-sm-semibold py-1 text-text-secondary')}>{t('answerIcon.title', { ns: 'app' })}</div>
<Switch
defaultValue={inputInfo.use_icon_as_answer_icon}
value={inputInfo.use_icon_as_answer_icon}
onChange={v => setInputInfo({ ...inputInfo, use_icon_as_answer_icon: v })}
/>
</div>
@@ -315,7 +315,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
/>
<div className="flex items-center justify-between">
<p className={cn('body-xs-regular text-text-tertiary')}>{t(`${prefixSettings}.chatColorThemeInverted`, { ns: 'appOverview' })}</p>
<Switch defaultValue={inputInfo.chatColorThemeInverted} onChange={v => setInputInfo({ ...inputInfo, chatColorThemeInverted: v })}></Switch>
<Switch value={inputInfo.chatColorThemeInverted} onChange={v => setInputInfo({ ...inputInfo, chatColorThemeInverted: v })}></Switch>
</div>
</div>
</div>
@@ -326,7 +326,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
<div className={cn('system-sm-semibold py-1 text-text-secondary')}>{t(`${prefixSettings}.workflow.subTitle`, { ns: 'appOverview' })}</div>
<Switch
disabled={!(appInfo.mode === AppModeEnum.WORKFLOW || appInfo.mode === AppModeEnum.ADVANCED_CHAT)}
defaultValue={inputInfo.show_workflow_steps}
value={inputInfo.show_workflow_steps}
onChange={v => setInputInfo({ ...inputInfo, show_workflow_steps: v })}
/>
</div>
@@ -380,7 +380,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
>
<Switch
disabled={!webappCopyrightEnabled}
defaultValue={inputInfo.copyrightSwitchValue}
value={inputInfo.copyrightSwitchValue}
onChange={v => setInputInfo({ ...inputInfo, copyrightSwitchValue: v })}
/>
</Tooltip>

View File

@@ -192,7 +192,7 @@ function TriggerCard({ appInfo, onToggleResult }: ITriggerCardProps) {
</div>
<div className="shrink-0">
<Switch
defaultValue={trigger.status === 'enabled'}
value={trigger.status === 'enabled'}
onChange={enabled => onToggleTrigger(trigger, enabled)}
disabled={!isCurrentWorkspaceEditor}
/>

View File

@@ -48,7 +48,7 @@ const FeatureCard = ({
</Tooltip>
)}
</div>
<Switch disabled={disabled} className="shrink-0" onChange={state => onChange?.(state)} defaultValue={value} />
<Switch disabled={disabled} className="shrink-0" onChange={state => onChange?.(state)} value={value} />
</div>
{description && (
<div className="system-xs-regular line-clamp-2 min-h-8 text-text-tertiary">{description}</div>

View File

@@ -38,7 +38,7 @@ const ModerationContent: FC<ModerationContentProps> = ({
}
<Switch
size="l"
defaultValue={config.enabled}
value={config.enabled}
onChange={v => handleConfigChange('enabled', v)}
/>
</div>

View File

@@ -232,7 +232,7 @@ const VoiceParamConfig = ({
</div>
<Switch
className="shrink-0"
defaultValue={text2speech?.autoPlay === TtsAutoPlay.enabled}
value={text2speech?.autoPlay === TtsAutoPlay.enabled}
onChange={(value: boolean) => {
handleChange({
autoPlay: value ? TtsAutoPlay.enabled : TtsAutoPlay.disabled,

View File

@@ -30,7 +30,7 @@ const ParamItem: FC<Props> = ({ className, id, name, noTooltip, tip, step = 0.1,
<Switch
size="md"
className="mr-2"
defaultValue={enable}
value={enable}
onChange={async (val) => {
onSwitchChange?.(id, val)
}}

View File

@@ -4,41 +4,54 @@ import { describe, expect, it, vi } from 'vitest'
import Switch from './index'
describe('Switch', () => {
it('should render in unchecked state by default', () => {
render(<Switch />)
it('should render in unchecked state when value is false', () => {
render(<Switch value={false} />)
const switchElement = screen.getByRole('switch')
expect(switchElement).toBeInTheDocument()
expect(switchElement).toHaveAttribute('aria-checked', 'false')
})
it('should render in checked state when defaultValue is true', () => {
render(<Switch defaultValue={true} />)
it('should render in checked state when value is true', () => {
render(<Switch value={true} />)
const switchElement = screen.getByRole('switch')
expect(switchElement).toHaveAttribute('aria-checked', 'true')
})
it('should toggle state and call onChange when clicked', async () => {
it('should call onChange with next value when clicked', async () => {
const onChange = vi.fn()
const user = userEvent.setup()
render(<Switch onChange={onChange} />)
render(<Switch value={false} onChange={onChange} />)
const switchElement = screen.getByRole('switch')
await user.click(switchElement)
expect(switchElement).toHaveAttribute('aria-checked', 'true')
expect(onChange).toHaveBeenCalledWith(true)
expect(onChange).toHaveBeenCalledTimes(1)
await user.click(switchElement)
// Controlled component stays the same until parent updates value.
expect(switchElement).toHaveAttribute('aria-checked', 'false')
expect(onChange).toHaveBeenCalledWith(false)
expect(onChange).toHaveBeenCalledTimes(2)
})
it('should work in controlled mode with value prop', async () => {
const onChange = vi.fn()
const user = userEvent.setup()
const { rerender } = render(<Switch value={false} onChange={onChange} />)
const switchElement = screen.getByRole('switch')
expect(switchElement).toHaveAttribute('aria-checked', 'false')
await user.click(switchElement)
expect(onChange).toHaveBeenCalledWith(true)
expect(switchElement).toHaveAttribute('aria-checked', 'false')
rerender(<Switch value={true} onChange={onChange} />)
expect(switchElement).toHaveAttribute('aria-checked', 'true')
})
it('should not call onChange when disabled', async () => {
const onChange = vi.fn()
const user = userEvent.setup()
render(<Switch disabled onChange={onChange} />)
render(<Switch value={false} disabled onChange={onChange} />)
const switchElement = screen.getByRole('switch')
expect(switchElement).toHaveClass('!cursor-not-allowed', '!opacity-50')
@@ -48,37 +61,36 @@ describe('Switch', () => {
})
it('should apply correct size classes', () => {
const { rerender } = render(<Switch size="xs" />)
const { rerender } = render(<Switch value={false} size="xs" />)
// We only need to find the element once
const switchElement = screen.getByRole('switch')
expect(switchElement).toHaveClass('h-2.5', 'w-3.5', 'rounded-sm')
rerender(<Switch size="sm" />)
rerender(<Switch value={false} size="sm" />)
expect(switchElement).toHaveClass('h-3', 'w-5')
rerender(<Switch size="md" />)
rerender(<Switch value={false} size="md" />)
expect(switchElement).toHaveClass('h-4', 'w-7')
rerender(<Switch size="l" />)
rerender(<Switch value={false} size="l" />)
expect(switchElement).toHaveClass('h-5', 'w-9')
rerender(<Switch size="lg" />)
rerender(<Switch value={false} size="lg" />)
expect(switchElement).toHaveClass('h-6', 'w-11')
})
it('should apply custom className', () => {
render(<Switch className="custom-test-class" />)
render(<Switch value={false} className="custom-test-class" />)
expect(screen.getByRole('switch')).toHaveClass('custom-test-class')
})
it('should apply correct background colors based on state', async () => {
const user = userEvent.setup()
render(<Switch />)
it('should apply correct background colors based on value prop', () => {
const { rerender } = render(<Switch value={false} />)
const switchElement = screen.getByRole('switch')
expect(switchElement).toHaveClass('bg-components-toggle-bg-unchecked')
await user.click(switchElement)
rerender(<Switch value={true} />)
expect(switchElement).toHaveClass('bg-components-toggle-bg')
})
})

View File

@@ -14,15 +14,18 @@ const meta = {
},
},
tags: ['autodocs'],
args: {
value: false,
},
argTypes: {
size: {
control: 'select',
options: ['xs', 'sm', 'md', 'lg', 'l'],
description: 'Switch size',
},
defaultValue: {
value: {
control: 'boolean',
description: 'Default checked state',
description: 'Checked state (controlled)',
},
disabled: {
control: 'boolean',
@@ -36,14 +39,14 @@ type Story = StoryObj<typeof meta>
// Interactive demo wrapper
const SwitchDemo = (args: any) => {
const [enabled, setEnabled] = useState(args.defaultValue || false)
const [enabled, setEnabled] = useState(args.value ?? false)
return (
<div style={{ width: '300px' }}>
<div className="flex items-center gap-3">
<Switch
{...args}
defaultValue={enabled}
value={enabled}
onChange={(value) => {
setEnabled(value)
console.log('Switch toggled:', value)
@@ -62,7 +65,7 @@ export const Default: Story = {
render: args => <SwitchDemo {...args} />,
args: {
size: 'md',
defaultValue: false,
value: false,
disabled: false,
},
}
@@ -72,7 +75,7 @@ export const DefaultOn: Story = {
render: args => <SwitchDemo {...args} />,
args: {
size: 'md',
defaultValue: true,
value: true,
disabled: false,
},
}
@@ -82,7 +85,7 @@ export const DisabledOff: Story = {
render: args => <SwitchDemo {...args} />,
args: {
size: 'md',
defaultValue: false,
value: false,
disabled: true,
},
}
@@ -92,7 +95,7 @@ export const DisabledOn: Story = {
render: args => <SwitchDemo {...args} />,
args: {
size: 'md',
defaultValue: true,
value: true,
disabled: true,
},
}
@@ -111,31 +114,31 @@ const SizeComparisonDemo = () => {
<div style={{ width: '400px' }} className="space-y-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Switch size="xs" defaultValue={states.xs} onChange={v => setStates({ ...states, xs: v })} />
<Switch size="xs" value={states.xs} onChange={v => setStates({ ...states, xs: v })} />
<span className="text-sm text-gray-700">Extra Small (xs)</span>
</div>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Switch size="sm" defaultValue={states.sm} onChange={v => setStates({ ...states, sm: v })} />
<Switch size="sm" value={states.sm} onChange={v => setStates({ ...states, sm: v })} />
<span className="text-sm text-gray-700">Small (sm)</span>
</div>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Switch size="md" defaultValue={states.md} onChange={v => setStates({ ...states, md: v })} />
<Switch size="md" value={states.md} onChange={v => setStates({ ...states, md: v })} />
<span className="text-sm text-gray-700">Medium (md)</span>
</div>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Switch size="l" defaultValue={states.l} onChange={v => setStates({ ...states, l: v })} />
<Switch size="l" value={states.l} onChange={v => setStates({ ...states, l: v })} />
<span className="text-sm text-gray-700">Large (l)</span>
</div>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Switch size="lg" defaultValue={states.lg} onChange={v => setStates({ ...states, lg: v })} />
<Switch size="lg" value={states.lg} onChange={v => setStates({ ...states, lg: v })} />
<span className="text-sm text-gray-700">Extra Large (lg)</span>
</div>
</div>
@@ -160,7 +163,7 @@ const WithLabelsDemo = () => {
</div>
<Switch
size="md"
defaultValue={enabled}
value={enabled}
onChange={setEnabled}
/>
</div>
@@ -197,7 +200,7 @@ const SettingsPanelDemo = () => {
</div>
<Switch
size="md"
defaultValue={settings.notifications}
value={settings.notifications}
onChange={v => updateSetting('notifications', v)}
/>
</div>
@@ -209,7 +212,7 @@ const SettingsPanelDemo = () => {
</div>
<Switch
size="md"
defaultValue={settings.autoSave}
value={settings.autoSave}
onChange={v => updateSetting('autoSave', v)}
/>
</div>
@@ -221,7 +224,7 @@ const SettingsPanelDemo = () => {
</div>
<Switch
size="md"
defaultValue={settings.darkMode}
value={settings.darkMode}
onChange={v => updateSetting('darkMode', v)}
/>
</div>
@@ -233,7 +236,7 @@ const SettingsPanelDemo = () => {
</div>
<Switch
size="md"
defaultValue={settings.analytics}
value={settings.analytics}
onChange={v => updateSetting('analytics', v)}
/>
</div>
@@ -245,7 +248,7 @@ const SettingsPanelDemo = () => {
</div>
<Switch
size="md"
defaultValue={settings.emailUpdates}
value={settings.emailUpdates}
onChange={v => updateSetting('emailUpdates', v)}
/>
</div>
@@ -279,7 +282,7 @@ const PrivacyControlsDemo = () => {
</div>
<Switch
size="md"
defaultValue={privacy.profilePublic}
value={privacy.profilePublic}
onChange={v => setPrivacy({ ...privacy, profilePublic: v })}
/>
</div>
@@ -291,7 +294,7 @@ const PrivacyControlsDemo = () => {
</div>
<Switch
size="md"
defaultValue={privacy.showEmail}
value={privacy.showEmail}
onChange={v => setPrivacy({ ...privacy, showEmail: v })}
/>
</div>
@@ -303,7 +306,7 @@ const PrivacyControlsDemo = () => {
</div>
<Switch
size="md"
defaultValue={privacy.allowMessages}
value={privacy.allowMessages}
onChange={v => setPrivacy({ ...privacy, allowMessages: v })}
/>
</div>
@@ -315,7 +318,7 @@ const PrivacyControlsDemo = () => {
</div>
<Switch
size="md"
defaultValue={privacy.shareActivity}
value={privacy.shareActivity}
onChange={v => setPrivacy({ ...privacy, shareActivity: v })}
/>
</div>
@@ -351,7 +354,7 @@ const FeatureTogglesDemo = () => {
</div>
<Switch
size="md"
defaultValue={features.betaFeatures}
value={features.betaFeatures}
onChange={v => setFeatures({ ...features, betaFeatures: v })}
/>
</div>
@@ -366,7 +369,7 @@ const FeatureTogglesDemo = () => {
</div>
<Switch
size="md"
defaultValue={features.experimentalUI}
value={features.experimentalUI}
onChange={v => setFeatures({ ...features, experimentalUI: v })}
/>
</div>
@@ -381,7 +384,7 @@ const FeatureTogglesDemo = () => {
</div>
<Switch
size="md"
defaultValue={features.advancedMode}
value={features.advancedMode}
onChange={v => setFeatures({ ...features, advancedMode: v })}
/>
</div>
@@ -396,7 +399,7 @@ const FeatureTogglesDemo = () => {
</div>
<Switch
size="md"
defaultValue={features.developerTools}
value={features.developerTools}
onChange={v => setFeatures({ ...features, developerTools: v })}
/>
</div>
@@ -440,7 +443,7 @@ const NotificationPreferencesDemo = () => {
</div>
<Switch
size="md"
defaultValue={notifications.email}
value={notifications.email}
onChange={v => setNotifications({ ...notifications, email: v })}
/>
</div>
@@ -455,7 +458,7 @@ const NotificationPreferencesDemo = () => {
</div>
<Switch
size="md"
defaultValue={notifications.push}
value={notifications.push}
onChange={v => setNotifications({ ...notifications, push: v })}
/>
</div>
@@ -470,7 +473,7 @@ const NotificationPreferencesDemo = () => {
</div>
<Switch
size="md"
defaultValue={notifications.sms}
value={notifications.sms}
onChange={v => setNotifications({ ...notifications, sms: v })}
/>
</div>
@@ -485,7 +488,7 @@ const NotificationPreferencesDemo = () => {
</div>
<Switch
size="md"
defaultValue={notifications.desktop}
value={notifications.desktop}
onChange={v => setNotifications({ ...notifications, desktop: v })}
/>
</div>
@@ -523,7 +526,7 @@ const APIAccessControlDemo = () => {
</div>
<Switch
size="md"
defaultValue={access.readAccess}
value={access.readAccess}
onChange={v => setAccess({ ...access, readAccess: v })}
/>
</div>
@@ -539,7 +542,7 @@ const APIAccessControlDemo = () => {
</div>
<Switch
size="md"
defaultValue={access.writeAccess}
value={access.writeAccess}
onChange={v => setAccess({ ...access, writeAccess: v })}
/>
</div>
@@ -555,7 +558,7 @@ const APIAccessControlDemo = () => {
</div>
<Switch
size="md"
defaultValue={access.deleteAccess}
value={access.deleteAccess}
onChange={v => setAccess({ ...access, deleteAccess: v })}
/>
</div>
@@ -571,7 +574,7 @@ const APIAccessControlDemo = () => {
</div>
<Switch
size="md"
defaultValue={access.adminAccess}
value={access.adminAccess}
onChange={v => setAccess({ ...access, adminAccess: v })}
/>
</div>
@@ -609,7 +612,7 @@ const CompactListDemo = () => {
<span className="text-sm text-gray-700">{item.name}</span>
<Switch
size="sm"
defaultValue={item.enabled}
value={item.enabled}
onChange={() => toggleItem(item.id)}
/>
</div>
@@ -628,7 +631,7 @@ export const Playground: Story = {
render: args => <SwitchDemo {...args} />,
args: {
size: 'md',
defaultValue: false,
value: false,
disabled: false,
},
}

View File

@@ -1,13 +1,12 @@
'use client'
import { Switch as OriginalSwitch } from '@headlessui/react'
import * as React from 'react'
import { useEffect, useState } from 'react'
import { cn } from '@/utils/classnames'
type SwitchProps = {
value: boolean
onChange?: (value: boolean) => void
size?: 'xs' | 'sm' | 'md' | 'lg' | 'l'
defaultValue?: boolean
disabled?: boolean
className?: string
}
@@ -15,19 +14,15 @@ type SwitchProps = {
const Switch = (
{
ref: propRef,
value,
onChange,
size = 'md',
defaultValue = false,
disabled = false,
className,
}: SwitchProps & {
ref?: React.RefObject<HTMLButtonElement>
},
) => {
const [enabled, setEnabled] = useState(defaultValue)
useEffect(() => {
setEnabled(defaultValue)
}, [defaultValue])
const wrapStyle = {
lg: 'h-6 w-11',
l: 'h-5 w-9',
@@ -54,18 +49,17 @@ const Switch = (
return (
<OriginalSwitch
ref={propRef}
checked={enabled}
checked={value}
onChange={(checked: boolean) => {
if (disabled)
return
setEnabled(checked)
onChange?.(checked)
}}
className={cn(wrapStyle[size], enabled ? 'bg-components-toggle-bg' : 'bg-components-toggle-bg-unchecked', 'relative inline-flex shrink-0 cursor-pointer rounded-[5px] border-2 border-transparent transition-colors duration-200 ease-in-out', disabled ? '!cursor-not-allowed !opacity-50' : '', size === 'xs' && 'rounded-sm', className)}
className={cn(wrapStyle[size], value ? 'bg-components-toggle-bg' : 'bg-components-toggle-bg-unchecked', 'relative inline-flex shrink-0 cursor-pointer rounded-[5px] border-2 border-transparent transition-colors duration-200 ease-in-out', disabled ? '!cursor-not-allowed !opacity-50' : '', size === 'xs' && 'rounded-sm', className)}
>
<span
aria-hidden="true"
className={cn(circleStyle[size], enabled ? translateLeft[size] : 'translate-x-0', size === 'xs' && 'rounded-[1px]', 'pointer-events-none inline-block rounded-[3px] bg-components-toggle-knob shadow ring-0 transition duration-200 ease-in-out')}
className={cn(circleStyle[size], value ? translateLeft[size] : 'translate-x-0', size === 'xs' && 'rounded-[1px]', 'pointer-events-none inline-block rounded-[3px] bg-components-toggle-knob shadow ring-0 transition duration-200 ease-in-out')}
/>
</OriginalSwitch>
)

View File

@@ -24,12 +24,12 @@ const PlanRangeSwitcher: FC<PlanRangeSwitcherProps> = ({
<div className="flex items-center justify-end gap-x-3 pr-5">
<Switch
size="l"
defaultValue={value === PlanRange.yearly}
value={value === PlanRange.yearly}
onChange={(v) => {
onChange(v ? PlanRange.yearly : PlanRange.monthly)
}}
/>
<span className="system-md-regular text-text-tertiary">
<span className="text-text-tertiary system-md-regular">
{t('plansCommon.annualBilling', { ns: 'billing', percent: 17 })}
</span>
</div>

View File

@@ -116,19 +116,19 @@ const CustomWebAppBrand = () => {
return (
<div className="py-4">
<div className="system-md-medium mb-2 flex items-center justify-between rounded-xl bg-background-section-burn p-4 text-text-primary">
<div className="mb-2 flex items-center justify-between rounded-xl bg-background-section-burn p-4 text-text-primary system-md-medium">
{t('webapp.removeBrand', { ns: 'custom' })}
<Switch
size="l"
defaultValue={webappBrandRemoved}
value={webappBrandRemoved ?? false}
disabled={isSandbox || !isCurrentWorkspaceManager}
onChange={handleSwitch}
/>
</div>
<div className={cn('flex h-14 items-center justify-between rounded-xl bg-background-section-burn px-4', webappBrandRemoved && 'opacity-30')}>
<div>
<div className="system-md-medium text-text-primary">{t('webapp.changeLogo', { ns: 'custom' })}</div>
<div className="system-xs-regular text-text-tertiary">{t('webapp.changeLogoTip', { ns: 'custom' })}</div>
<div className="text-text-primary system-md-medium">{t('webapp.changeLogo', { ns: 'custom' })}</div>
<div className="text-text-tertiary system-xs-regular">{t('webapp.changeLogoTip', { ns: 'custom' })}</div>
</div>
<div className="flex items-center">
{(!uploadDisabled && webappLogo && !webappBrandRemoved) && (
@@ -204,7 +204,7 @@ const CustomWebAppBrand = () => {
<div className="mt-2 text-xs text-[#D92D20]">{t('uploadedFail', { ns: 'custom' })}</div>
)}
<div className="mb-2 mt-5 flex items-center gap-2">
<div className="system-xs-medium-uppercase shrink-0 text-text-tertiary">{t('overview.appInfo.preview', { ns: 'appOverview' })}</div>
<div className="shrink-0 text-text-tertiary system-xs-medium-uppercase">{t('overview.appInfo.preview', { ns: 'appOverview' })}</div>
<Divider bgStyle="gradient" className="grow" />
</div>
<div className="relative mb-2 flex items-center gap-3">
@@ -215,7 +215,7 @@ const CustomWebAppBrand = () => {
<div className={cn('inline-flex h-8 w-8 items-center justify-center rounded-lg border border-divider-regular', 'bg-components-icon-bg-blue-light-solid')}>
<BubbleTextMod className="h-4 w-4 text-components-avatar-shape-fill-stop-100" />
</div>
<div className="system-md-semibold grow text-text-secondary">Chatflow App</div>
<div className="grow text-text-secondary system-md-semibold">Chatflow App</div>
<div className="p-1.5">
<RiLayoutLeft2Line className="h-4 w-4 text-text-tertiary" />
</div>
@@ -246,7 +246,7 @@ const CustomWebAppBrand = () => {
<div className="flex items-center gap-1.5">
{!webappBrandRemoved && (
<>
<div className="system-2xs-medium-uppercase text-text-tertiary">POWERED BY</div>
<div className="text-text-tertiary system-2xs-medium-uppercase">POWERED BY</div>
{
systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
? <img src={systemFeatures.branding.workspace_logo} alt="logo" className="block h-5 w-auto" />
@@ -262,12 +262,12 @@ const CustomWebAppBrand = () => {
<div className="flex w-[138px] grow flex-col justify-between p-2 pr-0">
<div className="flex grow flex-col justify-between rounded-l-2xl border-[0.5px] border-r-0 border-components-panel-border-subtle bg-chatbot-bg pb-4 pl-[22px] pt-16">
<div className="w-[720px] rounded-2xl border border-divider-subtle bg-chat-bubble-bg px-4 py-3">
<div className="body-md-regular mb-1 text-text-primary">Hello! How can I assist you today?</div>
<div className="mb-1 text-text-primary body-md-regular">Hello! How can I assist you today?</div>
<Button size="small">
<div className="h-2 w-[144px] rounded-sm bg-text-quaternary opacity-20"></div>
</Button>
</div>
<div className="body-lg-regular flex h-[52px] w-[578px] items-center rounded-xl border border-components-chat-input-border bg-components-panel-bg-blur pl-3.5 text-text-placeholder shadow-md backdrop-blur-sm">Talk to Dify</div>
<div className="flex h-[52px] w-[578px] items-center rounded-xl border border-components-chat-input-border bg-components-panel-bg-blur pl-3.5 text-text-placeholder shadow-md backdrop-blur-sm body-lg-regular">Talk to Dify</div>
</div>
</div>
</div>
@@ -278,14 +278,14 @@ const CustomWebAppBrand = () => {
<div className={cn('inline-flex h-8 w-8 items-center justify-center rounded-lg border border-divider-regular', 'bg-components-icon-bg-indigo-solid')}>
<RiExchange2Fill className="h-4 w-4 text-components-avatar-shape-fill-stop-100" />
</div>
<div className="system-md-semibold grow text-text-secondary">Workflow App</div>
<div className="grow text-text-secondary system-md-semibold">Workflow App</div>
<div className="p-1.5">
<RiLayoutLeft2Line className="h-4 w-4 text-text-tertiary" />
</div>
</div>
<div className="flex items-center gap-4">
<div className="system-md-semibold-uppercase flex h-10 shrink-0 items-center border-b-2 border-components-tab-active text-text-primary">RUN ONCE</div>
<div className="system-md-semibold-uppercase flex h-10 grow items-center border-b-2 border-transparent text-text-tertiary">RUN BATCH</div>
<div className="flex h-10 shrink-0 items-center border-b-2 border-components-tab-active text-text-primary system-md-semibold-uppercase">RUN ONCE</div>
<div className="flex h-10 grow items-center border-b-2 border-transparent text-text-tertiary system-md-semibold-uppercase">RUN BATCH</div>
</div>
</div>
<div className="grow bg-components-panel-bg">
@@ -293,7 +293,7 @@ const CustomWebAppBrand = () => {
<div className="mb-1 py-2">
<div className="h-2 w-20 rounded-sm bg-text-quaternary opacity-20"></div>
</div>
<div className="h-16 w-full rounded-lg bg-components-input-bg-normal "></div>
<div className="h-16 w-full rounded-lg bg-components-input-bg-normal"></div>
</div>
<div className="flex items-center justify-between px-4 py-3">
<Button size="small">
@@ -308,7 +308,7 @@ const CustomWebAppBrand = () => {
<div className="flex h-12 shrink-0 items-center gap-1.5 bg-components-panel-bg p-4 pt-3">
{!webappBrandRemoved && (
<>
<div className="system-2xs-medium-uppercase text-text-tertiary">POWERED BY</div>
<div className="text-text-tertiary system-2xs-medium-uppercase">POWERED BY</div>
{
systemFeatures.branding.enabled && systemFeatures.branding.workspace_logo
? <img src={systemFeatures.branding.workspace_logo} alt="logo" className="block h-5 w-auto" />

View File

@@ -123,11 +123,11 @@ vi.mock('@/app/components/base/radio-card', () => ({
}))
vi.mock('@/app/components/base/switch', () => ({
default: ({ defaultValue, onChange }: { defaultValue: boolean, onChange: (v: boolean) => void }) => (
default: ({ value, onChange }: { value: boolean, onChange?: (v: boolean) => void }) => (
<button
data-testid="rerank-switch"
data-checked={defaultValue}
onClick={() => onChange(!defaultValue)}
data-checked={value}
onClick={() => onChange?.(!value)}
>
Switch
</button>

View File

@@ -122,7 +122,7 @@ const RetrievalParamConfig: FC<Props> = ({
{canToggleRerankModalEnable && (
<Switch
size="md"
defaultValue={value.reranking_enable}
value={value.reranking_enable}
onChange={handleToggleRerankEnable}
/>
)}

View File

@@ -191,7 +191,7 @@ const Operations = ({
return (
<div className="flex items-center" onClick={e => e.stopPropagation()}>
{isListScene && !embeddingAvailable && (
<Switch defaultValue={false} onChange={noop} disabled={true} size="md" />
<Switch value={false} onChange={noop} disabled={true} size="md" />
)}
{isListScene && embeddingAvailable && (
<>
@@ -202,11 +202,11 @@ const Operations = ({
popupClassName="!font-semibold"
>
<div>
<Switch defaultValue={false} onChange={noop} disabled={true} size="md" />
<Switch value={false} onChange={noop} disabled={true} size="md" />
</div>
</Tooltip>
)
: <Switch defaultValue={enabled} onChange={v => handleSwitch(v ? 'enable' : 'disable')} size="md" />}
: <Switch value={enabled} onChange={v => handleSwitch(v ? 'enable' : 'disable')} size="md" />}
<Divider className="!ml-4 !mr-2 !h-3" type="vertical" />
</>
)}

View File

@@ -216,7 +216,7 @@ const SegmentCard: FC<ISegmentCardProps> = ({
<Switch
size="md"
disabled={archived || detail?.status !== 'completed'}
defaultValue={enabled}
value={enabled}
onChange={async (val) => {
await onChangeSwitch?.(val, id)
}}

View File

@@ -119,7 +119,7 @@ const StatusItem = ({
disabled={!archived}
>
<Switch
defaultValue={archived ? false : enabled}
value={archived ? false : enabled}
onChange={v => !archived && handleSwitch(v ? 'enable' : 'disable')}
disabled={embedding || archived}
size="md"

View File

@@ -60,7 +60,7 @@ const Card = ({
</div>
</div>
<Switch
defaultValue={apiEnabled}
value={apiEnabled}
onChange={onToggle}
disabled={!isCurrentWorkspaceManager}
/>

View File

@@ -204,7 +204,7 @@ const DatasetMetadataDrawer: FC<Props> = ({
<div className="mt-3 flex h-6 items-center">
<Switch
defaultValue={isBuiltInEnabled}
value={isBuiltInEnabled}
onChange={onIsBuiltInEnabledChange}
/>
<div className="system-sm-semibold ml-2 mr-0.5 text-text-secondary">{t(`${i18nPrefix}.builtIn`, { ns: 'dataset' })}</div>

View File

@@ -72,7 +72,7 @@ const SummaryIndexSetting = ({
</Tooltip>
</div>
<Switch
defaultValue={summaryIndexSetting?.enable ?? false}
value={summaryIndexSetting?.enable ?? false}
onChange={handleSummaryIndexEnableChange}
size="md"
/>
@@ -119,7 +119,7 @@ const SummaryIndexSetting = ({
<div className="system-sm-semibold flex items-center text-text-secondary">
<Switch
className="mr-2"
defaultValue={summaryIndexSetting?.enable ?? false}
value={summaryIndexSetting?.enable ?? false}
onChange={handleSummaryIndexEnableChange}
size="md"
/>
@@ -184,7 +184,7 @@ const SummaryIndexSetting = ({
<div className="flex h-6 items-center">
<Switch
className="mr-2"
defaultValue={summaryIndexSetting?.enable ?? false}
value={summaryIndexSetting?.enable ?? false}
onChange={handleSummaryIndexEnableChange}
size="md"
/>

View File

@@ -166,7 +166,7 @@ const CreateAppModal = ({
<div className="flex items-center justify-between">
<div className="py-2 text-sm font-medium leading-[20px] text-text-primary">{t('answerIcon.title', { ns: 'app' })}</div>
<Switch
defaultValue={useIconAsAnswerIcon}
value={useIconAsAnswerIcon}
onChange={v => setUseIconAsAnswerIcon(v)}
/>
</div>

View File

@@ -257,7 +257,7 @@ const ParameterItem: FC<ParameterItemProps> = ({
!parameterRule.required && parameterRule.name !== 'stop' && (
<div className="mr-2 w-7">
<Switch
defaultValue={!isNullOrUndefined(value)}
value={!isNullOrUndefined(value)}
onChange={handleSwitch}
size="md"
/>

View File

@@ -92,13 +92,13 @@ const ModelListItem = ({ model, provider, isConfigurable, onChange, onModifyLoad
}
offset={{ mainAxis: 4 }}
>
<Switch defaultValue={false} disabled size="md" />
<Switch value={false} disabled size="md" />
</Tooltip>
)
: (isCurrentWorkspaceManager && (
<Switch
className="ml-2"
defaultValue={model?.status === ModelStatusEnum.active}
value={model?.status === ModelStatusEnum.active}
disabled={![ModelStatusEnum.active, ModelStatusEnum.disabled].includes(model.status)}
size="md"
onChange={onEnablingStateChange}

View File

@@ -167,7 +167,7 @@ const ModelLoadBalancingConfigs = ({
{
withSwitch && (
<Switch
defaultValue={Boolean(draftConfig.enabled)}
value={Boolean(draftConfig.enabled)}
size="l"
className="ml-3 justify-self-end"
disabled={!modelLoadBalancingEnabled && !draftConfig.enabled}
@@ -227,7 +227,7 @@ const ModelLoadBalancingConfigs = ({
<>
<span className="mr-2 h-3 border-r border-r-divider-subtle" />
<Switch
defaultValue={credential?.not_allowed_to_use ? false : Boolean(config.enabled)}
value={credential?.not_allowed_to_use ? false : Boolean(config.enabled)}
size="md"
className="justify-self-end"
onChange={value => toggleConfigEntryEnabled(index, value)}

View File

@@ -181,7 +181,7 @@ const EndpointCard = ({
)}
<Switch
className="ml-3"
defaultValue={active}
value={active}
onChange={handleSwitch}
size="sm"
/>

View File

@@ -258,7 +258,7 @@ const ReasoningConfigForm: React.FC<Props> = ({
<span className="system-xs-medium text-text-secondary">{t('detailPanel.toolSelector.auto', { ns: 'plugin' })}</span>
<Switch
size="xs"
defaultValue={!!auto}
value={!!auto}
onChange={val => handleAutomatic(variable, val, type)}
/>
</div>

View File

@@ -95,8 +95,8 @@ const ToolItem = ({
</div>
)}
<div className={cn('grow truncate pl-0.5', isTransparent && 'opacity-50', isShowCanNotChooseMCPTip && 'opacity-30')}>
<div className="system-2xs-medium-uppercase text-text-tertiary">{providerNameText}</div>
<div className="system-xs-medium text-text-secondary">{toolLabel}</div>
<div className="text-text-tertiary system-2xs-medium-uppercase">{providerNameText}</div>
<div className="text-text-secondary system-xs-medium">{toolLabel}</div>
</div>
<div className="hidden items-center gap-1 group-hover:flex">
{!noAuth && !isError && !uninstalled && !versionMismatch && !isShowCanNotChooseMCPTip && (
@@ -120,7 +120,7 @@ const ToolItem = ({
<div className="mr-1" onClick={e => e.stopPropagation()}>
<Switch
size="md"
defaultValue={switchValue}
value={switchValue ?? false}
onChange={onSwitchChange}
/>
</div>

View File

@@ -250,7 +250,7 @@ const MCPServiceCard: FC<IAppCardProps> = ({
offset={24}
>
<div>
<Switch defaultValue={activated} onChange={onChangeStatus} disabled={toggleDisabled} />
<Switch value={activated} onChange={onChangeStatus} disabled={toggleDisabled} />
</div>
</Tooltip>
</div>

View File

@@ -32,7 +32,7 @@ const AuthenticationSection: FC<AuthenticationSectionProps> = ({
<div className="mb-1 flex h-6 items-center">
<Switch
className="mr-2"
defaultValue={isDynamicRegistration}
value={isDynamicRegistration}
onChange={onDynamicRegistrationChange}
/>
<span className="system-sm-medium text-text-secondary">{t('mcp.modal.useDynamicClientRegistration', { ns: 'tools' })}</span>

View File

@@ -65,7 +65,7 @@ const ConfigVision: FC<Props> = ({
popupContent={t('vision.onlySupportVisionModelTip', { ns: 'appDebug' })!}
disabled={isVisionModel}
>
<Switch disabled={readOnly || !isVisionModel} size="md" defaultValue={!isVisionModel ? false : enabled} onChange={onEnabledChange} />
<Switch disabled={readOnly || !isVisionModel} size="md" value={!isVisionModel ? false : enabled} onChange={onEnabledChange} />
</Tooltip>
)}
>

View File

@@ -136,7 +136,7 @@ const MemoryConfig: FC<Props> = ({
tooltip={t(`${i18nPrefix}.memoryTip`, { ns: 'workflow' })!}
operations={(
<Switch
defaultValue={!!payload}
value={!!payload}
onChange={handleMemoryEnabledChange}
size="md"
disabled={readonly}
@@ -149,7 +149,7 @@ const MemoryConfig: FC<Props> = ({
<div className="flex justify-between">
<div className="flex h-8 items-center space-x-2">
<Switch
defaultValue={payload?.window?.enabled}
value={payload?.window?.enabled}
onChange={handleWindowEnabledChange}
size="md"
disabled={readonly}

View File

@@ -196,7 +196,7 @@ const Editor: FC<Props> = ({
<Jinja className="h-3 w-6 text-text-quaternary" />
<Switch
size="sm"
defaultValue={editionType === EditionType.jinja2}
value={editionType === EditionType.jinja2}
onChange={(checked) => {
onEditionTypeChange?.(checked ? EditionType.jinja2 : EditionType.basic)
}}

View File

@@ -55,10 +55,10 @@ const RetryOnPanel = ({
<div className="pt-2">
<div className="flex h-10 items-center justify-between px-4 py-2">
<div className="flex items-center">
<div className="system-sm-semibold-uppercase mr-0.5 text-text-secondary">{t('nodes.common.retry.retryOnFailure', { ns: 'workflow' })}</div>
<div className="mr-0.5 text-text-secondary system-sm-semibold-uppercase">{t('nodes.common.retry.retryOnFailure', { ns: 'workflow' })}</div>
</div>
<Switch
defaultValue={retry_config?.retry_enabled}
value={retry_config?.retry_enabled ?? false}
onChange={v => handleRetryEnabledChange(v)}
/>
</div>
@@ -66,7 +66,7 @@ const RetryOnPanel = ({
retry_config?.retry_enabled && (
<div className="px-4 pb-2">
<div className="mb-1 flex w-full items-center">
<div className="system-xs-medium-uppercase mr-2 grow text-text-secondary">{t('nodes.common.retry.maxRetries', { ns: 'workflow' })}</div>
<div className="mr-2 grow text-text-secondary system-xs-medium-uppercase">{t('nodes.common.retry.maxRetries', { ns: 'workflow' })}</div>
<Slider
className="mr-3 w-[108px]"
value={retry_config?.max_retries || 3}
@@ -87,7 +87,7 @@ const RetryOnPanel = ({
/>
</div>
<div className="flex items-center">
<div className="system-xs-medium-uppercase mr-2 grow text-text-secondary">{t('nodes.common.retry.retryInterval', { ns: 'workflow' })}</div>
<div className="mr-2 grow text-text-secondary system-xs-medium-uppercase">{t('nodes.common.retry.retryInterval', { ns: 'workflow' })}</div>
<Slider
className="mr-3 w-[108px]"
value={retry_config?.retry_interval || 1000}

View File

@@ -131,7 +131,7 @@ const Panel: FC<NodePanelProps<HttpNodeType>> = ({
tooltip={t(`${i18nPrefix}.verifySSL.warningTooltip`, { ns: 'workflow' })}
operations={(
<Switch
defaultValue={!!inputs.ssl_verify}
value={!!inputs.ssl_verify}
onChange={handleSSLVerifyChange}
size="md"
disabled={readOnly}

View File

@@ -149,7 +149,7 @@ const EmailConfigureModal = ({
</div>
</div>
<Switch
defaultValue={debugMode}
value={debugMode}
onChange={checked => setDebugMode(checked)}
/>
</div>

View File

@@ -160,7 +160,7 @@ const DeliveryMethodItem: FC<DeliveryMethodItemProps> = ({
)}
{(method.config || method.type === DeliveryMethodType.WebApp) && (
<Switch
defaultValue={method.enabled}
value={method.enabled}
onChange={handleEnableStatusChange}
disabled={readonly}
/>

View File

@@ -91,7 +91,7 @@ const Recipient = ({
</div>
<div className={cn('system-sm-medium grow text-text-secondary')}>{t(`${i18nPrefix}.deliveryMethod.emailConfigure.allMembers`, { workspaceName: currentWorkspace.name.replace(/'/g, ''), ns: 'workflow' })}</div>
<Switch
defaultValue={data.whole_workspace}
value={data.whole_workspace}
onChange={checked => onChange({ ...data, whole_workspace: checked })}
/>
</div>

View File

@@ -92,7 +92,7 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({
</div>
<div className="px-4 pb-2">
<Field title={t(`${i18nPrefix}.parallelMode`, { ns: 'workflow' })} tooltip={<div className="w-[230px]">{t(`${i18nPrefix}.parallelPanelDesc`, { ns: 'workflow' })}</div>} inline>
<Switch defaultValue={inputs.is_parallel} onChange={changeParallel} />
<Switch value={inputs.is_parallel} onChange={changeParallel} />
</Field>
</div>
{
@@ -130,7 +130,7 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({
tooltip={<div className="w-[230px]">{t(`${i18nPrefix}.flattenOutputDesc`, { ns: 'workflow' })}</div>}
inline
>
<Switch defaultValue={inputs.flatten_output} onChange={changeFlattenOutput} />
<Switch value={inputs.flatten_output} onChange={changeFlattenOutput} />
</Field>
</div>
</div>

View File

@@ -166,10 +166,10 @@ const SearchMethodOption = ({
<div>
{
showRerankModelSelectorSwitch && (
<div className="system-sm-semibold mb-1 flex items-center text-text-secondary">
<div className="mb-1 flex items-center text-text-secondary system-sm-semibold">
<Switch
className="mr-1"
defaultValue={rerankingModelEnabled}
value={rerankingModelEnabled ?? false}
onChange={onRerankingModelEnabledChange}
disabled={readonly}
/>
@@ -192,7 +192,7 @@ const SearchMethodOption = ({
<div className="p-1">
<AlertTriangle className="size-4 text-text-warning-secondary" />
</div>
<span className="system-xs-medium text-text-primary">
<span className="text-text-primary system-xs-medium">
{t('form.retrievalSetting.multiModalTip', { ns: 'datasetSettings' })}
</span>
</div>

View File

@@ -56,7 +56,7 @@ const TopKAndScoreThreshold = ({
return (
<div className="grid grid-cols-2 gap-4">
<div>
<div className="system-xs-medium mb-0.5 flex h-6 items-center text-text-secondary">
<div className="mb-0.5 flex h-6 items-center text-text-secondary system-xs-medium">
{t('datasetConfig.top_k', { ns: 'appDebug' })}
<Tooltip
triggerClassName="ml-0.5 shrink-0 w-3.5 h-3.5"
@@ -78,11 +78,11 @@ const TopKAndScoreThreshold = ({
<div className="mb-0.5 flex h-6 items-center">
<Switch
className="mr-2"
defaultValue={isScoreThresholdEnabled}
value={isScoreThresholdEnabled ?? false}
onChange={onScoreThresholdEnabledChange}
disabled={readonly}
/>
<div className="system-sm-medium grow truncate text-text-secondary">
<div className="grow truncate text-text-secondary system-sm-medium">
{t('datasetConfig.score_threshold', { ns: 'appDebug' })}
</div>
<Tooltip

View File

@@ -56,7 +56,7 @@ const LimitConfig: FC<Props> = ({
title={t(`${i18nPrefix}.limit`, { ns: 'workflow' })}
operations={(
<Switch
defaultValue={payload.enabled}
value={payload.enabled}
onChange={handleLimitEnabledChange}
size="md"
disabled={readonly}

View File

@@ -65,7 +65,7 @@ const Panel: FC<NodePanelProps<ListFilterNodeType>> = ({
title={t(`${i18nPrefix}.filterCondition`, { ns: 'workflow' })}
operations={(
<Switch
defaultValue={inputs.filter_by?.enabled}
value={inputs.filter_by?.enabled}
onChange={handleFilterEnabledChange}
size="md"
disabled={readOnly}
@@ -90,7 +90,7 @@ const Panel: FC<NodePanelProps<ListFilterNodeType>> = ({
title={t(`${i18nPrefix}.extractsCondition`, { ns: 'workflow' })}
operations={(
<Switch
defaultValue={inputs.extract_by?.enabled}
value={inputs.extract_by?.enabled}
onChange={handleExtractsEnabledChange}
size="md"
disabled={readOnly}
@@ -123,7 +123,7 @@ const Panel: FC<NodePanelProps<ListFilterNodeType>> = ({
title={t(`${i18nPrefix}.orderBy`, { ns: 'workflow' })}
operations={(
<Switch
defaultValue={inputs.order_by?.enabled}
value={inputs.order_by?.enabled}
onChange={handleOrderByEnabledChange}
size="md"
disabled={readOnly}

View File

@@ -17,7 +17,7 @@ const RequiredSwitch: FC<RequiredSwitchProps> = ({
return (
<div className="flex items-center gap-x-1 rounded-[5px] border border-divider-subtle bg-background-default-lighter px-1.5 py-1">
<span className="system-2xs-medium-uppercase text-text-secondary">{t('nodes.llm.jsonSchema.required', { ns: 'workflow' })}</span>
<Switch size="xs" defaultValue={defaultValue} onChange={toggleRequired} />
<Switch size="xs" value={defaultValue} onChange={toggleRequired} />
</div>
)
}

View File

@@ -24,7 +24,7 @@ const ReasoningFormatConfig: FC<ReasoningFormatConfigProps> = ({
operations={(
// ON = separated, OFF = tagged
<Switch
defaultValue={value === 'separated'}
value={value === 'separated'}
onChange={enabled => onChange(enabled ? 'separated' : 'tagged')}
size="md"
disabled={readonly}

View File

@@ -285,7 +285,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
</Tooltip>
<Switch
className="ml-2"
defaultValue={!!inputs.structured_output_enabled}
value={!!inputs.structured_output_enabled}
onChange={handleStructureOutputEnableChange}
size="md"
disabled={readOnly}

View File

@@ -174,7 +174,7 @@ const AddExtractParameter: FC<Props> = ({
<Field title={t(`${i18nPrefix}.addExtractParameterContent.required`, { ns: 'workflow' })}>
<>
<div className="mb-1.5 text-xs font-normal leading-[18px] text-text-tertiary">{t(`${i18nPrefix}.addExtractParameterContent.requiredContent`, { ns: 'workflow' })}</div>
<Switch size="l" defaultValue={param.required} onChange={handleParamChange('required')} />
<Switch size="l" value={param.required ?? false} onChange={handleParamChange('required')} />
</>
</Field>
</div>

View File

@@ -90,7 +90,7 @@ const Panel: FC<NodePanelProps<VariableAssignerNodeType>> = ({
tooltip={t(`${i18nPrefix}.aggregationGroupTip`, { ns: 'workflow' })!}
operations={(
<Switch
defaultValue={isEnableGroup}
value={isEnableGroup}
onChange={handleGroupEnabledChange}
size="md"
disabled={readOnly}

View File

@@ -80,7 +80,7 @@ const Operator = ({
<div>{t('nodes.note.editor.showAuthor', { ns: 'workflow' })}</div>
<Switch
size="l"
defaultValue={showAuthor}
value={showAuthor}
onChange={onShowAuthorChange}
/>
</div>

View File

@@ -21,7 +21,7 @@ const FilterSwitch: FC<FilterSwitchProps> = ({
{t('versionHistory.filter.onlyShowNamedVersions', { ns: 'workflow' })}
</div>
<Switch
defaultValue={enabled}
value={enabled}
onChange={v => handleSwitch(v)}
size="md"
className="shrink-0"

View File

@@ -452,9 +452,6 @@
"react-hooks-extra/no-direct-set-state-in-use-effect": {
"count": 1
},
"tailwindcss/enforce-consistent-class-order": {
"count": 2
},
"ts/no-explicit-any": {
"count": 5
}
@@ -803,11 +800,6 @@
"count": 1
}
},
"app/components/app/configuration/dataset-config/params-config/config-content.tsx": {
"tailwindcss/enforce-consistent-class-order": {
"count": 9
}
},
"app/components/app/configuration/dataset-config/params-config/index.tsx": {
"react-hooks-extra/no-direct-set-state-in-use-effect": {
"count": 1
@@ -954,11 +946,6 @@
"count": 2
}
},
"app/components/app/configuration/tools/index.tsx": {
"tailwindcss/no-unnecessary-whitespace": {
"count": 1
}
},
"app/components/app/create-app-dialog/app-card/index.spec.tsx": {
"ts/no-explicit-any": {
"count": 1
@@ -2758,14 +2745,6 @@
"count": 1
}
},
"app/components/base/switch/index.tsx": {
"react-hooks-extra/no-direct-set-state-in-use-effect": {
"count": 1
},
"tailwindcss/no-unnecessary-whitespace": {
"count": 1
}
},
"app/components/base/tab-header/index.tsx": {
"tailwindcss/enforce-consistent-class-order": {
"count": 1
@@ -2927,9 +2906,6 @@
"app/components/billing/pricing/plan-switcher/plan-range-switcher.tsx": {
"react-refresh/only-export-components": {
"count": 1
},
"tailwindcss/enforce-consistent-class-order": {
"count": 1
}
},
"app/components/billing/pricing/plan-switcher/tab.tsx": {
@@ -3001,12 +2977,6 @@
}
},
"app/components/custom/custom-web-app-brand/index.tsx": {
"tailwindcss/enforce-consistent-class-order": {
"count": 12
},
"tailwindcss/no-unnecessary-whitespace": {
"count": 1
},
"ts/no-explicit-any": {
"count": 2
}
@@ -5034,11 +5004,6 @@
"count": 2
}
},
"app/components/plugins/plugin-detail-panel/tool-selector/components/tool-item.tsx": {
"tailwindcss/enforce-consistent-class-order": {
"count": 2
}
},
"app/components/plugins/plugin-detail-panel/tool-selector/components/tool-settings-panel.tsx": {
"tailwindcss/enforce-consistent-class-order": {
"count": 4
@@ -6319,11 +6284,6 @@
"count": 1
}
},
"app/components/workflow/nodes/_base/components/retry/retry-on-panel.tsx": {
"tailwindcss/enforce-consistent-class-order": {
"count": 3
}
},
"app/components/workflow/nodes/_base/components/selector.tsx": {
"tailwindcss/no-unnecessary-whitespace": {
"count": 2
@@ -6944,16 +6904,6 @@
"count": 1
}
},
"app/components/workflow/nodes/knowledge-base/components/retrieval-setting/search-method-option.tsx": {
"tailwindcss/enforce-consistent-class-order": {
"count": 2
}
},
"app/components/workflow/nodes/knowledge-base/components/retrieval-setting/top-k-and-score-threshold.tsx": {
"tailwindcss/enforce-consistent-class-order": {
"count": 2
}
},
"app/components/workflow/nodes/knowledge-base/components/retrieval-setting/type.ts": {
"ts/no-explicit-any": {
"count": 2