chore(deps): bump antd to 6.5 and migrate deprecated component props

Upgrade frontend deps (antd 6.4.5 -> 6.5.0, Ant Design icons, TanStack
Query, i18next, eslint) and fasthttp 1.71 -> 1.72.

AntD 6.5 deprecated several Input/Card/Space props, so adapt the panel UI:
- Input/InputNumber addonBefore/addonAfter -> prefix/suffix
- Card bordered -> variant="outlined"
- Space direction -> orientation
- swap the hand-rolled Telegram SVG for the new TelegramFilled icon
- guard SettingListItem against cloning aria-labelledby onto a Fragment,
  which only accepts key/children
This commit is contained in:
MHSanaei
2026-06-29 16:57:55 +02:00
parent d8221a8153
commit 8332ba67ae
13 changed files with 154 additions and 162 deletions
@@ -47,7 +47,7 @@ export default function RemarkTemplateField({ value = '', onChange, maxLength, p
maxLength={maxLength}
placeholder={placeholder}
onChange={(e) => onChange?.(e.target.value)}
addonAfter={
suffix={
<Popover
content={<RemarkVarPicker onPick={insertToken} />}
trigger="click"
@@ -55,7 +55,7 @@ export default function RemarkTemplateField({ value = '', onChange, maxLength, p
title={t('pages.hosts.remarkVars.title')}
>
<Tooltip title={t('pages.hosts.remarkVars.title')}>
<Button type="text" size="small" icon={<CodeOutlined />} aria-label={t('pages.hosts.remarkVars.title')} style={{ margin: '0 -7px' }} />
<Button type="text" size="small" icon={<CodeOutlined />} aria-label={t('pages.hosts.remarkVars.title')} style={{ marginInlineEnd: -7 }} />
</Tooltip>
</Popover>
}
@@ -1,4 +1,4 @@
import { cloneElement, isValidElement, useId, type ReactElement, type ReactNode } from 'react';
import { cloneElement, Fragment, isValidElement, useId, type ReactElement, type ReactNode } from 'react';
import { Col, Row } from 'antd';
import './SettingListItem.css';
@@ -20,7 +20,7 @@ export default function SettingListItem({
const padding = paddings === 'small' ? '10px 20px' : '20px';
const titleId = useId();
const node = control ?? children;
const labelledNode = title && isValidElement(node)
const labelledNode = title && isValidElement(node) && node.type !== Fragment
? cloneElement(node as ReactElement<{ 'aria-labelledby'?: string }>, { 'aria-labelledby': titleId })
: node;
return (
@@ -12,7 +12,7 @@ export function NotificationCard({ icon, title, extra, children }: Props) {
return (
<Card
size="small"
bordered
variant="outlined"
title={<span>{icon} {title}</span>}
extra={extra}
style={{ borderWidth: 1 }}
@@ -40,7 +40,7 @@ export function NotificationGroup({ config, selected, onToggle, onToggleAll, all
/>
}
>
<Space direction="vertical" size={8} style={{ width: '100%' }}>
<Space orientation="vertical" size={8} style={{ width: '100%' }}>
{config.events.map((event) => (
<NotificationEvent
key={event.key}
@@ -444,7 +444,7 @@ function FragmentRangeList({
>
<Input
placeholder={placeholder}
addonAfter={fields.length > minItems
suffix={fields.length > minItems
? (
<DeleteOutlined
className="danger-icon"
@@ -854,7 +854,7 @@ function GeckoPacketSizeInput({
return (
<Space.Compact block>
<InputNumber
addonBefore="Min"
prefix="Min"
min={GECKO_MIN_PACKET_SIZE}
max={GECKO_MAX_PACKET_SIZE}
precision={0}
@@ -864,7 +864,7 @@ function GeckoPacketSizeInput({
style={{ width: '50%' }}
/>
<InputNumber
addonBefore="Max"
prefix="Max"
min={GECKO_MIN_PACKET_SIZE}
max={GECKO_MAX_PACKET_SIZE}
precision={0}
@@ -97,7 +97,7 @@ export default function FallbacksCard({
<Row gutter={[8, 8]}>
<Col xs={24} sm={12}>
<Input
addonBefore="SNI"
prefix="SNI"
placeholder={t('pages.inbounds.fallbacks.matchAny') || 'any'}
value={record.name}
onChange={(e) => updateFallback(record.rowKey, { name: e.target.value })}
@@ -105,7 +105,7 @@ export default function FallbacksCard({
</Col>
<Col xs={24} sm={12}>
<Input
addonBefore="ALPN"
prefix="ALPN"
placeholder={t('pages.inbounds.fallbacks.matchAny') || 'any'}
value={record.alpn}
onChange={(e) => updateFallback(record.rowKey, { alpn: e.target.value })}
@@ -113,7 +113,7 @@ export default function FallbacksCard({
</Col>
<Col xs={24} sm={12}>
<Input
addonBefore="Path"
prefix="Path"
placeholder="/"
value={record.path}
onChange={(e) => updateFallback(record.rowKey, { path: e.target.value })}
@@ -121,7 +121,7 @@ export default function FallbacksCard({
</Col>
<Col xs={24} sm={12}>
<Input
addonBefore="Dest"
prefix="Dest"
placeholder={t('pages.inbounds.fallbacks.destPlaceholder') || 'auto'}
value={record.dest}
onChange={(e) => updateFallback(record.rowKey, { dest: e.target.value })}
@@ -129,7 +129,7 @@ export default function FallbacksCard({
</Col>
<Col xs={24} sm={12}>
<InputNumber
addonBefore="xver"
prefix="xver"
min={0}
max={2}
style={{ width: '100%' }}
@@ -243,7 +243,7 @@ export default function TlsForm({
name={[certField.name, 'ocspStapling']}
label="OCSP Stapling"
>
<InputNumber min={0} addonAfter="s" style={{ width: '50%' }} />
<InputNumber min={0} suffix="s" style={{ width: '50%' }} />
</Form.Item>
<Form.Item
name={[certField.name, 'oneTimeLoading']}
+2 -10
View File
@@ -34,6 +34,7 @@ import {
DatabaseOutlined,
ForkOutlined,
CopyOutlined,
TelegramFilled,
} from '@ant-design/icons';
import { HttpUtil, SizeFormatter, TimeFormatter, ClipboardManager, FileManager } from '@/utils';
@@ -245,16 +246,7 @@ export default function IndexPage() {
hoverable
actions={[
<Space className="action" key="tg" role="button" tabIndex={0} aria-label="@XrayUI" onClick={openTelegram} onKeyDown={activateOnKey(openTelegram)}>
<svg
viewBox="0 0 24 24"
width="14"
height="14"
fill="currentColor"
className="tg-icon"
aria-hidden="true"
>
<path d="M21.93 4.34a1.5 1.5 0 0 0-2.05-1.6L2.97 9.6c-.92.36-.91 1.66.02 1.99l4.32 1.53 1.7 5.23a1 1 0 0 0 1.68.36l2.43-2.43 4.36 3.21a1.5 1.5 0 0 0 2.36-.91l3.09-13.86a1.5 1.5 0 0 0 0-.38ZM9.97 14.66l-.55 3.36-1.36-4.2 9.8-7.05-7.89 7.89Z" />
</svg>
<TelegramFilled className="tg-icon" aria-hidden="true" />
{!isMobile && <span>@XrayUI</span>}
</Space>,
<Space
+2 -2
View File
@@ -341,7 +341,7 @@ export default function BasicsTab({
min={0}
style={{ width: '100%' }}
placeholder="300"
addonAfter={t('pages.xray.seconds')}
suffix={t('pages.xray.seconds')}
onChange={(v) => setLevel0('connIdle', v as number | null)}
/>
}
@@ -356,7 +356,7 @@ export default function BasicsTab({
min={0}
style={{ width: '100%' }}
placeholder={t('pages.xray.bufferSizePlaceholder')}
addonAfter="KB"
suffix="KB"
onChange={(v) => setLevel0('bufferSize', v as number | null)}
/>
}