Compare commits

...

5 Commits

Author SHA1 Message Date
Asuka Minato
4df2d70d65 Merge branch 'main' into copilot/fix-fc039c44-aa24-4844-82b2-e9ac237a13e9 2025-10-11 03:01:39 +09:00
copilot-swe-agent[bot]
fdce781a11 Changes before error encountered
Co-authored-by: asukaminato0721 <30024051+asukaminato0721@users.noreply.github.com>
2025-09-27 18:36:13 +09:00
copilot-swe-agent[bot]
b81cafa6c3 Changes before error encountered
Co-authored-by: asukaminato0721 <30024051+asukaminato0721@users.noreply.github.com>
2025-09-27 18:36:13 +09:00
copilot-swe-agent[bot]
a259800fe4 Fix additional prefer-read-only-props violations in workflow and header components
Co-authored-by: asukaminato0721 <30024051+asukaminato0721@users.noreply.github.com>
2025-09-27 18:36:13 +09:00
copilot-swe-agent[bot]
d3554b76e9 Changes before error encountered
Co-authored-by: asukaminato0721 <30024051+asukaminato0721@users.noreply.github.com>
2025-09-27 18:36:13 +09:00
45 changed files with 163 additions and 140 deletions

View File

@@ -3,13 +3,13 @@ import s from './style.module.css'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
type ISliderProps = { type ISliderProps = {
className?: string readonly className?: string
value: number readonly value: number
max?: number readonly max?: number
min?: number readonly min?: number
step?: number readonly step?: number
disabled?: boolean readonly disabled?: boolean
onChange: (value: number) => void readonly onChange: (value: number) => void
} }
const Slider: React.FC<ISliderProps> = ({ className, max, min, step, value, disabled, onChange }) => { const Slider: React.FC<ISliderProps> = ({ className, max, min, step, value, disabled, onChange }) => {

View File

@@ -21,7 +21,7 @@ export const inputVariants = cva(
}, },
) )
export type InputProps = { type BaseInputProps = {
showLeftIcon?: boolean showLeftIcon?: boolean
showClearIcon?: boolean showClearIcon?: boolean
onClear?: () => void onClear?: () => void
@@ -31,28 +31,31 @@ export type InputProps = {
styleCss?: CSSProperties styleCss?: CSSProperties
unit?: string unit?: string
ref?: React.Ref<HTMLInputElement> ref?: React.Ref<HTMLInputElement>
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> & VariantProps<typeof inputVariants> }
export type InputProps = Readonly<BaseInputProps> & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> & VariantProps<typeof inputVariants>
const removeLeadingZeros = (value: string) => value.replace(/^(-?)0+(?=\d)/, '$1') const removeLeadingZeros = (value: string) => value.replace(/^(-?)0+(?=\d)/, '$1')
const Input = ({ const Input: React.FC<InputProps> = (props: Readonly<InputProps>) => {
size, const {
disabled, size,
destructive, disabled,
showLeftIcon, destructive,
showClearIcon, showLeftIcon,
onClear, showClearIcon,
wrapperClassName, onClear,
className, wrapperClassName,
styleCss, className,
value, styleCss,
placeholder, value,
onChange = noop, placeholder,
onBlur = noop, onChange = noop,
unit, onBlur = noop,
ref, unit,
...props ref,
}: InputProps) => { ...restProps
} = props
const { t } = useTranslation() const { t } = useTranslation()
const handleNumberChange: ChangeEventHandler<HTMLInputElement> = (e) => { const handleNumberChange: ChangeEventHandler<HTMLInputElement> = (e) => {
if (value === 0) { if (value === 0) {
@@ -102,10 +105,10 @@ const Input = ({
? (t('common.operation.search') || '') ? (t('common.operation.search') || '')
: (t('common.placeholder.input') || ''))} : (t('common.placeholder.input') || ''))}
value={value} value={value}
onChange={props.type === 'number' ? handleNumberChange : onChange} onChange={restProps.type === 'number' ? handleNumberChange : onChange}
onBlur={props.type === 'number' ? handleNumberBlur : onBlur} onBlur={restProps.type === 'number' ? handleNumberBlur : onBlur}
disabled={disabled} disabled={disabled}
{...props} {...restProps}
/> />
{showClearIcon && value && !disabled && !destructive && ( {showClearIcon && value && !disabled && !destructive && (
<div className={cn('group absolute right-2 top-1/2 -translate-y-1/2 cursor-pointer p-[1px]')} onClick={onClear}> <div className={cn('group absolute right-2 top-1/2 -translate-y-1/2 cursor-pointer p-[1px]')} onClick={onClear}>

View File

@@ -10,8 +10,8 @@ import cn from '@/utils/classnames'
import GridMask from '@/app/components/base/grid-mask' import GridMask from '@/app/components/base/grid-mask'
type Props = { type Props = {
show: boolean readonly show: boolean
onHide: () => void readonly onHide: () => void
} }
const AnnotationFullModal: FC<Props> = ({ const AnnotationFullModal: FC<Props> = ({
show, show,

View File

@@ -7,7 +7,7 @@ import UsageInfo from '../usage-info'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
type Props = { type Props = {
className?: string readonly className?: string
} }
const Usage: FC<Props> = ({ const Usage: FC<Props> = ({

View File

@@ -15,7 +15,7 @@ import cn from '@/utils/classnames'
const LOW = 50 const LOW = 50
const MIDDLE = 80 const MIDDLE = 80
const AppsFull: FC<{ loc: string; className?: string; }> = ({ const AppsFull: FC<{ readonly loc: string; readonly className?: string }> = ({
loc, loc,
className, className,
}) => { }) => {

View File

@@ -7,8 +7,8 @@ import cn from '@/utils/classnames'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
type Props = { type Props = {
onClick?: () => void readonly onClick?: () => void
isDisplayOnly?: boolean readonly isDisplayOnly?: boolean
} }
const HeaderBillingBtn: FC<Props> = ({ const HeaderBillingBtn: FC<Props> = ({

View File

@@ -24,7 +24,7 @@ import { useModalContextSelector } from '@/context/modal-context'
import { Enterprise, Professional, Sandbox, Team } from './assets' import { Enterprise, Professional, Sandbox, Team } from './assets'
type Props = { type Props = {
loc: string readonly loc: string
} }
const PlanComp: FC<Props> = ({ const PlanComp: FC<Props> = ({

View File

@@ -1,5 +1,5 @@
type CloudProps = { type CloudProps = {
isActive: boolean readonly isActive: boolean
} }
const Cloud = ({ const Cloud = ({

View File

@@ -1,5 +1,5 @@
type SelfHostedProps = { type SelfHostedProps = {
isActive: boolean readonly isActive: boolean
} }
const SelfHosted = ({ const SelfHosted = ({

View File

@@ -6,8 +6,8 @@ import { type Category, CategoryEnum } from '.'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
type FooterProps = { type FooterProps = {
pricingPageURL: string readonly pricingPageURL: string
currentCategory: Category readonly currentCategory: Category
} }
const Footer = ({ const Footer = ({

View File

@@ -9,10 +9,10 @@ import type { PlanRange } from './plan-range-switcher'
import PlanRangeSwitcher from './plan-range-switcher' import PlanRangeSwitcher from './plan-range-switcher'
type PlanSwitcherProps = { type PlanSwitcherProps = {
currentCategory: Category readonly currentCategory: Category
currentPlanRange: PlanRange readonly currentPlanRange: PlanRange
onChangeCategory: (category: Category) => void readonly onChangeCategory: (category: Category) => void
onChangePlanRange: (value: PlanRange) => void readonly onChangePlanRange: (value: PlanRange) => void
} }
const PlanSwitcher: FC<PlanSwitcherProps> = ({ const PlanSwitcher: FC<PlanSwitcherProps> = ({

View File

@@ -10,8 +10,8 @@ export enum PlanRange {
} }
type PlanRangeSwitcherProps = { type PlanRangeSwitcherProps = {
value: PlanRange readonly value: PlanRange
onChange: (value: PlanRange) => void readonly onChange: (value: PlanRange) => void
} }
const PlanRangeSwitcher: FC<PlanRangeSwitcherProps> = ({ const PlanRangeSwitcher: FC<PlanRangeSwitcherProps> = ({

View File

@@ -3,8 +3,8 @@ import { SelectionMod } from '../base/icons/src/public/knowledge'
import type { QA } from '@/models/datasets' import type { QA } from '@/models/datasets'
export type ChunkLabelProps = { export type ChunkLabelProps = {
label: string readonly label: string
characterCount: number readonly characterCount: number
} }
export const ChunkLabel: FC<ChunkLabelProps> = (props) => { export const ChunkLabel: FC<ChunkLabelProps> = (props) => {

View File

@@ -6,8 +6,8 @@ import Badge from '@/app/components/base/badge'
import { GeneralChunk, ParentChildChunk } from '@/app/components/base/icons/src/vender/knowledge' import { GeneralChunk, ParentChildChunk } from '@/app/components/base/icons/src/vender/knowledge'
type Props = { type Props = {
isGeneralMode: boolean readonly isGeneralMode: boolean
isQAMode: boolean readonly isQAMode: boolean
} }
const ChunkingModeLabel: FC<Props> = ({ const ChunkingModeLabel: FC<Props> = ({

View File

@@ -2,10 +2,10 @@ import cn from '@/utils/classnames'
import React, { useCallback, useMemo, useState } from 'react' import React, { useCallback, useMemo, useState } from 'react'
type CredentialIconProps = { type CredentialIconProps = {
avatar_url?: string readonly avatar_url?: string
name: string readonly name: string
size?: number readonly size?: number
className?: string readonly className?: string
} }
const ICON_BG_COLORS = [ const ICON_BG_COLORS = [

View File

@@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
const Tag = ({ text, className }: { text: string; className?: string }) => { const Tag = ({ text, className }: { readonly text: string; readonly className?: string }) => {
return ( return (
<div className={cn('inline-flex items-center gap-x-0.5', className)}> <div className={cn('inline-flex items-center gap-x-0.5', className)}>
<span className='text-xs font-medium text-text-quaternary'>#</span> <span className='text-xs font-medium text-text-quaternary'>#</span>

View File

@@ -6,8 +6,8 @@ import CopyFeedback from '@/app/components/base/copy-feedback'
import SecretKeyButton from '@/app/components/develop/secret-key/secret-key-button' import SecretKeyButton from '@/app/components/develop/secret-key/secret-key-button'
type ApiServerProps = { type ApiServerProps = {
apiBaseUrl: string readonly apiBaseUrl: string
appId?: string readonly appId?: string
} }
const ApiServer: FC<ApiServerProps> = ({ const ApiServer: FC<ApiServerProps> = ({
apiBaseUrl, apiBaseUrl,

View File

@@ -3,18 +3,18 @@ import type { PropsWithChildren } from 'react'
import classNames from '@/utils/classnames' import classNames from '@/utils/classnames'
type IChildrenProps = { type IChildrenProps = {
children: React.ReactNode readonly children: React.ReactNode
id?: string readonly id?: string
tag?: any readonly tag?: any
label?: any readonly label?: any
anchor: boolean readonly anchor: boolean
} }
type IHeaderingProps = { type IHeaderingProps = {
url: string readonly url: string
method: 'PUT' | 'DELETE' | 'GET' | 'POST' | 'PATCH' readonly method: 'PUT' | 'DELETE' | 'GET' | 'POST' | 'PATCH'
title: string readonly title: string
name: string readonly name: string
} }
export const Heading = function H2({ export const Heading = function H2({
@@ -66,7 +66,7 @@ export function Row({ children }: IChildrenProps) {
} }
type IColProps = IChildrenProps & { type IColProps = IChildrenProps & {
sticky: boolean readonly sticky: boolean
} }
export function Col({ children, sticky = false }: IColProps) { export function Col({ children, sticky = false }: IColProps) {
return ( return (
@@ -95,8 +95,8 @@ export function Properties({ children }: IChildrenProps) {
} }
type IProperty = IChildrenProps & { type IProperty = IChildrenProps & {
name: string readonly name: string
type: string readonly type: string
} }
export function Property({ name, type, children }: IProperty) { export function Property({ name, type, children }: IProperty) {
return ( return (
@@ -120,8 +120,8 @@ export function Property({ name, type, children }: IProperty) {
} }
type ISubProperty = IChildrenProps & { type ISubProperty = IChildrenProps & {
name: string readonly name: string
type: string readonly type: string
} }
export function SubProperty({ name, type, children }: ISubProperty) { export function SubProperty({ name, type, children }: ISubProperty) {
return ( return (
@@ -144,7 +144,7 @@ export function SubProperty({ name, type, children }: ISubProperty) {
) )
} }
export function PropertyInstruction({ children }: PropsWithChildren<{}>) { export function PropertyInstruction({ children }: Readonly<PropsWithChildren<{}>>) {
return ( return (
<li className="m-0 px-0 py-4 italic first:pt-0">{children}</li> <li className="m-0 px-0 py-4 italic first:pt-0">{children}</li>
) )

View File

@@ -6,9 +6,9 @@ import Tooltip from '@/app/components/base/tooltip'
import CopyFeedback from '@/app/components/base/copy-feedback' import CopyFeedback from '@/app/components/base/copy-feedback'
type IInputCopyProps = { type IInputCopyProps = {
value?: string readonly value?: string
className?: string readonly className?: string
children?: React.ReactNode readonly children?: React.ReactNode
} }
const InputCopy = ({ const InputCopy = ({

View File

@@ -6,9 +6,9 @@ import Button from '@/app/components/base/button'
import SecretKeyModal from '@/app/components/develop/secret-key/secret-key-modal' import SecretKeyModal from '@/app/components/develop/secret-key/secret-key-modal'
type ISecretKeyButtonProps = { type ISecretKeyButtonProps = {
className?: string readonly className?: string
appId?: string readonly appId?: string
textCls?: string readonly textCls?: string
} }
const SecretKeyButton = ({ className, appId, textCls }: ISecretKeyButtonProps) => { const SecretKeyButton = ({ className, appId, textCls }: ISecretKeyButtonProps) => {

View File

@@ -41,9 +41,9 @@ const valueColorMap = {
} as { [key: string]: string } } as { [key: string]: string }
type ITagProps = { type ITagProps = {
children: string readonly children: string
color?: string readonly color?: string
variant?: string readonly variant?: string
} }
export function Tag({ export function Tag({

View File

@@ -12,8 +12,8 @@ import DifyLogo from '@/app/components/base/logo/dify-logo'
import { useGlobalPublicStore } from '@/context/global-public-context' import { useGlobalPublicStore } from '@/context/global-public-context'
type IAccountSettingProps = { type IAccountSettingProps = {
langGeniusVersionInfo: LangGeniusVersionResponse readonly langGeniusVersionInfo: LangGeniusVersionResponse
onCancel: () => void readonly onCancel: () => void
} }
export default function AccountAbout({ export default function AccountAbout({

View File

@@ -26,7 +26,7 @@ enum DocName {
} }
type UpgradeOrDownloadProps = { type UpgradeOrDownloadProps = {
doc_name: DocName readonly doc_name: DocName
} }
const UpgradeOrDownload: FC<UpgradeOrDownloadProps> = ({ doc_name }) => { const UpgradeOrDownload: FC<UpgradeOrDownloadProps> = ({ doc_name }) => {
const { t } = useTranslation() const { t } = useTranslation()

View File

@@ -7,7 +7,7 @@ import classNames from '@/utils/classnames'
import type { AppDetailResponse } from '@/models/app' import type { AppDetailResponse } from '@/models/app'
type IAppBackProps = { type IAppBackProps = {
curApp: AppDetailResponse readonly curApp: AppDetailResponse
} }
export default function AppBack({ curApp }: IAppBackProps) { export default function AppBack({ curApp }: IAppBackProps) {
const { t } = useTranslation() const { t } = useTranslation()

View File

@@ -12,8 +12,8 @@ import { useAppContext } from '@/context/app-context'
import { noop } from 'lodash-es' import { noop } from 'lodash-es'
type IAppSelectorProps = { type IAppSelectorProps = {
appItems: AppDetailResponse[] readonly appItems: AppDetailResponse[]
curApp: AppDetailResponse readonly curApp: AppDetailResponse
} }
export default function AppSelector({ appItems, curApp }: IAppSelectorProps) { export default function AppSelector({ appItems, curApp }: IAppSelectorProps) {

View File

@@ -6,7 +6,7 @@ import { useEventEmitterContextContext } from '@/context/event-emitter'
import classNames from '@/utils/classnames' import classNames from '@/utils/classnames'
type HeaderWrapperProps = { type HeaderWrapperProps = {
children: React.ReactNode readonly children: React.ReactNode
} }
const HeaderWrapper = ({ const HeaderWrapper = ({

View File

@@ -3,8 +3,8 @@
import classNames from '@/utils/classnames' import classNames from '@/utils/classnames'
export type IndicatorProps = { export type IndicatorProps = {
color?: 'green' | 'orange' | 'red' | 'blue' | 'yellow' | 'gray' readonly color?: 'green' | 'orange' | 'red' | 'blue' | 'yellow' | 'gray'
className?: string readonly className?: string
} }
export type ColorMap = { export type ColorMap = {

View File

@@ -9,10 +9,10 @@ import PremiumBadge from '../../base/premium-badge'
import { Plan } from '../../billing/type' import { Plan } from '../../billing/type'
type PlanBadgeProps = { type PlanBadgeProps = {
plan: Plan readonly plan: Plan
allowHover?: boolean readonly allowHover?: boolean
sandboxAsUpgrade?: boolean readonly sandboxAsUpgrade?: boolean
onClick?: () => void readonly onClick?: () => void
} }
const PlanBadge: FC<PlanBadgeProps> = ({ plan, allowHover, sandboxAsUpgrade = false, onClick }) => { const PlanBadge: FC<PlanBadgeProps> = ({ plan, allowHover, sandboxAsUpgrade = false, onClick }) => {

View File

@@ -10,7 +10,7 @@ import type { ToolWithProvider } from '@/app/components/workflow/types'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
type Props = { type Props = {
searchText: string readonly searchText: string
} }
function renderDefaultCard() { function renderDefaultCard() {

View File

@@ -1,12 +1,12 @@
type CustomEdgeLinearGradientRenderProps = { type CustomEdgeLinearGradientRenderProps = {
id: string readonly id: string
startColor: string readonly startColor: string
stopColor: string readonly stopColor: string
position: { readonly position: {
x1: number readonly x1: number
x2: number readonly x2: number
y1: number readonly y1: number
y2: number readonly y2: number
} }
} }
const CustomEdgeLinearGradientRender = ({ const CustomEdgeLinearGradientRender = ({

View File

@@ -28,6 +28,7 @@ import CustomEdgeLinearGradientRender from './custom-edge-linear-gradient-render
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types' import { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types'
// eslint-disable-next-line @eslint-react/prefer-read-only-props
const CustomEdge = ({ const CustomEdge = ({
id, id,
data, data,

View File

@@ -9,9 +9,9 @@ import {
VariableLabelInText, VariableLabelInText,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label' } from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
type Props = { type Props = {
nodeId: string readonly nodeId: string
value: string readonly value: string
className?: string readonly className?: string
} }
const VAR_PLACEHOLDER = '@#!@#!' const VAR_PLACEHOLDER = '@#!@#!'

View File

@@ -11,8 +11,8 @@ import AppIcon from '@/app/components/base/app-icon'
type Status = 'not-installed' | 'not-authorized' | undefined type Status = 'not-installed' | 'not-authorized' | undefined
export type ToolIconProps = { export type ToolIconProps = {
id: string readonly id: string
providerName: string readonly providerName: string
} }
export const ToolIcon = memo(({ providerName }: ToolIconProps) => { export const ToolIcon = memo(({ providerName }: ToolIconProps) => {

View File

@@ -11,6 +11,7 @@ import { FormTypeEnum } from '@/app/components/header/account-setting/model-prov
import { useRenderI18nObject } from '@/hooks/use-i18n' import { useRenderI18nObject } from '@/hooks/use-i18n'
import { ModelBar } from './components/model-bar' import { ModelBar } from './components/model-bar'
// eslint-disable-next-line @eslint-react/prefer-read-only-props
const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => { const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
const { inputs, currentStrategy, currentStrategyStatus, pluginDetail } = useConfig(props.id, props.data) const { inputs, currentStrategy, currentStrategyStatus, pluginDetail } = useConfig(props.id, props.data)
const renderI18nObject = useRenderI18nObject() const renderI18nObject = useRenderI18nObject()

View File

@@ -25,6 +25,7 @@ export function strategyParamToCredientialForm(param: StrategyParamItem): Creden
} }
} }
// eslint-disable-next-line @eslint-react/prefer-read-only-props
const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => { const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
const { const {
inputs, inputs,

View File

@@ -2,10 +2,10 @@ import React, { type FC } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
type CardProps = { type CardProps = {
name: string readonly name: string
type: string readonly type: string
required: boolean readonly required: boolean
description?: string readonly description?: string
} }
const Card: FC<CardProps> = ({ const Card: FC<CardProps> = ({

View File

@@ -13,13 +13,13 @@ import AddField from './add-field'
import { JSON_SCHEMA_MAX_DEPTH } from '@/config' import { JSON_SCHEMA_MAX_DEPTH } from '@/config'
type SchemaNodeProps = { type SchemaNodeProps = {
name: string readonly name: string
required: boolean readonly required: boolean
schema: Field readonly schema: Field
path: string[] readonly path: string[]
parentPath?: string[] readonly parentPath?: string[]
depth: number readonly depth: number
readOnly?: boolean readonly readOnly?: boolean
} }
// Support 10 levels of indentation // Support 10 levels of indentation

View File

@@ -12,12 +12,12 @@ import type { ModelConfig } from '@/app/components/workflow/types'
import { useHooksStore } from '../../../hooks-store' import { useHooksStore } from '../../../hooks-store'
type Props = { type Props = {
className?: string readonly className?: string
onGenerated?: (prompt: string) => void readonly onGenerated?: (prompt: string) => void
modelConfig?: ModelConfig readonly modelConfig?: ModelConfig
nodeId: string readonly nodeId: string
editorId?: string readonly editorId?: string
currentPrompt?: string readonly currentPrompt?: string
} }
const PromptGeneratorBtn: FC<Props> = ({ const PromptGeneratorBtn: FC<Props> = ({

View File

@@ -5,9 +5,9 @@ import Field from '@/app/components/workflow/nodes/_base/components/field'
import Switch from '@/app/components/base/switch' import Switch from '@/app/components/base/switch'
type ReasoningFormatConfigProps = { type ReasoningFormatConfigProps = {
value?: 'tagged' | 'separated' readonly value?: 'tagged' | 'separated'
onChange: (value: 'tagged' | 'separated') => void readonly onChange: (value: 'tagged' | 'separated') => void
readonly?: boolean readonly readonly?: boolean
} }
const ReasoningFormatConfig: FC<ReasoningFormatConfigProps> = ({ const ReasoningFormatConfig: FC<ReasoningFormatConfigProps> = ({

View File

@@ -8,8 +8,8 @@ import { Resolution } from '@/types/app'
const i18nPrefix = 'workflow.nodes.llm' const i18nPrefix = 'workflow.nodes.llm'
type Props = { type Props = {
value: Resolution readonly value: Resolution
onChange: (value: Resolution) => void readonly onChange: (value: Resolution) => void
} }
const ResolutionPicker: FC<Props> = ({ const ResolutionPicker: FC<Props> = ({

View File

@@ -29,8 +29,8 @@ import {
} from '@/app/components/workflow/types' } from '@/app/components/workflow/types'
type AddBlockProps = { type AddBlockProps = {
renderTrigger?: (open: boolean) => React.ReactNode readonly renderTrigger?: (open: boolean) => React.ReactNode
offset?: OffsetOptions readonly offset?: OffsetOptions
} }
const AddBlock = ({ const AddBlock = ({
renderTrigger, renderTrigger,

View File

@@ -7,8 +7,8 @@ import VariableInspectPanel from '../variable-inspect'
import { useStore } from '../store' import { useStore } from '../store'
export type OperatorProps = { export type OperatorProps = {
handleUndo: () => void readonly handleUndo: () => void
handleRedo: () => void readonly handleRedo: () => void
} }
const Operator = ({ handleUndo, handleRedo }: OperatorProps) => { const Operator = ({ handleUndo, handleRedo }: OperatorProps) => {

View File

@@ -3,9 +3,9 @@ import ShortcutsName from '../shortcuts-name'
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
type TipPopupProps = { type TipPopupProps = {
title: string readonly title: string
children: React.ReactNode readonly children: React.ReactNode
shortcuts?: string[] readonly shortcuts?: string[]
} }
const TipPopup = ({ const TipPopup = ({
title, title,

View File

@@ -3,8 +3,8 @@ import { getKeyboardKeyNameBySystem } from './utils'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
type ShortcutsNameProps = { type ShortcutsNameProps = {
keys: string[] readonly keys: string[]
className?: string readonly className?: string
} }
const ShortcutsName = ({ const ShortcutsName = ({
keys, keys,

View File

@@ -10,6 +10,7 @@ import reactHooks from 'eslint-plugin-react-hooks'
import sonar from 'eslint-plugin-sonarjs' import sonar from 'eslint-plugin-sonarjs'
import oxlint from 'eslint-plugin-oxlint' import oxlint from 'eslint-plugin-oxlint'
import next from '@next/eslint-plugin-next' import next from '@next/eslint-plugin-next'
import eslintReact from '@eslint-react/eslint-plugin'
// import reactRefresh from 'eslint-plugin-react-refresh' // import reactRefresh from 'eslint-plugin-react-refresh'
@@ -144,6 +145,22 @@ export default combine(
'react-hooks': reactHooks, 'react-hooks': reactHooks,
}, },
}, },
// eslint-react
{
files: ['**/*.{ts,tsx}'],
plugins: {
'@eslint-react': eslintReact,
},
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
'@eslint-react/prefer-read-only-props': 'error',
},
},
// sonar // sonar
{ {
rules: { rules: {