@nextclaw/ui 0.26.2 → 0.26.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/dist/.vite/manifest.json +366 -365
- package/dist/assets/{account-panel-ZM2qzKF4.js → account-panel-DVi_jhkG.js} +1 -1
- package/dist/assets/{api-Cjq-o1VN.js → api-BZvNpFOS.js} +2 -2
- package/dist/assets/app-presenter-provider-BcYL-VNe.js +124 -0
- package/dist/assets/{appearance-settings-page-B4zouKzg.js → appearance-settings-page-AZNBzLmT.js} +1 -1
- package/dist/assets/{book-open-AteA89HX.js → book-open-CmRdT3N1.js} +1 -1
- package/dist/assets/card-CdRBL1E0.js +1 -0
- package/dist/assets/{channels-list-page-fj8kMo-T.js → channels-list-page-eZN74FN3.js} +2 -2
- package/dist/assets/{circle-dashed-LSYZTzM7.js → circle-dashed-HOgt3gIJ.js} +1 -1
- package/dist/assets/{client-DudCRJw4.js → client-DKKbdJ6Q.js} +1 -1
- package/dist/assets/config-split-page-BA3V6b3Q.js +1 -0
- package/dist/assets/{confirm-dialog-DShT64F6.js → confirm-dialog-8vqYZ0wy.js} +1 -1
- package/dist/assets/context-menu-DHVVdHzN.js +1 -0
- package/dist/assets/{createLucideIcon-D7hvIHV-.js → createLucideIcon-DE0sB9Nu.js} +1 -1
- package/dist/assets/{desktop-capabilities-page-CzqzFZUY.js → desktop-capabilities-page-B9-B9k1A.js} +1 -1
- package/dist/assets/{desktop-update-config-CgeQ0Ffo.js → desktop-update-config-Cfr3IRUe.js} +1 -1
- package/dist/assets/{dialog-C7glmAQJ.js → dialog-BUfWO8hr.js} +2 -2
- package/dist/assets/{doc-browser-context-BlhBAOLH.js → doc-browser-context-ClLgMbxd.js} +1 -1
- package/dist/assets/doc-browser-w8q1j0jL.js +1 -0
- package/dist/assets/{download-BYgECE0n.js → download-CKqS1Ksj.js} +1 -1
- package/dist/assets/{es2015-CsjAAQ6X.js → es2015-BiB05Sav.js} +1 -1
- package/dist/assets/{extensions-qYL-NpL3.js → extensions-vPD4dGqt.js} +1 -1
- package/dist/assets/{eye-BBuTzJ53.js → eye-bKzylu3p.js} +1 -1
- package/dist/assets/{form-actions-CLGWO52v.js → form-actions-CCoxz33Q.js} +1 -1
- package/dist/assets/{i18n-qBGEbcW6.js → i18n-OGmF0Ws_.js} +2 -2
- package/dist/assets/{keyboard-shortcuts-settings-page-B-wK_6zG.js → keyboard-shortcuts-settings-page-D8rosOVh.js} +1 -1
- package/dist/assets/loader-circle-Clq1Gtb1.js +1 -0
- package/dist/assets/{login-page-Cd84lpVV.js → login-page-BT3GV3Sb.js} +1 -1
- package/dist/assets/login-page-DKId3By8.js +1 -0
- package/dist/assets/main-bEWCGDHr.js +2 -0
- package/dist/assets/main-i18n-catalog.config-Bpu5GcwF.js +1 -0
- package/dist/assets/main-kqMRTwOs.css +1 -0
- package/dist/assets/mcp-marketplace-page-CZIP6j3L.js +1 -0
- package/dist/assets/{model-config-page-D0DQlSDa.js → model-config-page-D21a-BO0.js} +1 -1
- package/dist/assets/{navigation-link-32iM1-e6.js → navigation-link-DC-Pku0Y.js} +1 -1
- package/dist/assets/panel-app-BYfQu_TS.js +1 -0
- package/dist/assets/panel-app-i18n-catalog.config-D44qmtfk.js +1 -0
- package/dist/assets/panelStandalone-BRg7B1EI.css +1 -0
- package/dist/assets/{panelStandalone-C9EKaApN.js → panelStandalone-CX8X2hjh.js} +2 -2
- package/dist/assets/{privacy-settings-page-Bxxx12OO.js → privacy-settings-page-e0LFHZJm.js} +1 -1
- package/dist/assets/projects-Rki7Fmth.js +1 -0
- package/dist/assets/provider-models-DFQgF4hS.js +1 -0
- package/dist/assets/provider-scoped-model-input-DaONL0j_.js +1 -0
- package/dist/assets/providers-config-page-CEOhQlMe.js +1 -0
- package/dist/assets/{puzzle-CWHfFyYN.js → puzzle-D_TiFXOv.js} +1 -1
- package/dist/assets/{pwa-CiGUjpcd.js → pwa-C9ac_1dg.js} +1 -1
- package/dist/assets/{refresh-cw-y3L6PyLt.js → refresh-cw-BG8VfcdA.js} +1 -1
- package/dist/assets/remote-DkSx5x4R.js +1 -0
- package/dist/assets/{rotate-cw-CNE9qSHi.js → rotate-cw-DPEegUU2.js} +1 -1
- package/dist/assets/{runtime-config-page-5o98T-TD.js → runtime-config-page-DDT1dVLt.js} +1 -1
- package/dist/assets/{save-B0p5a0ET.js → save-CPlctBjT.js} +1 -1
- package/dist/assets/{search-config-page-CpGcnIzi.js → search-config-page-CDwmd6eX.js} +1 -1
- package/dist/assets/{secrets-config-page-C4VTiW3r.js → secrets-config-page-1OvgmwPv.js} +1 -1
- package/dist/assets/security-config-Pv4CM-kw.js +1 -0
- package/dist/assets/{select-CctTN205.js → select-Y9IEbx9x.js} +1 -1
- package/dist/assets/service-apps-panel-DPrLeF3N.js +1 -0
- package/dist/assets/{settings-2-EPflrNk6.js → settings-2-CrGx9_De.js} +1 -1
- package/dist/assets/{status-dot-CensgJZC.js → status-dot-Cb8ewlUr.js} +1 -1
- package/dist/assets/{tag-chip-Bjzb4-qW.js → tag-chip-D-6aPuuh.js} +1 -1
- package/dist/assets/{theme-provider-hlle7Skk.js → theme-provider-BjF1Eowc.js} +1 -1
- package/dist/assets/{trash-2-C5KH5Rw9.js → trash-2-DER2EJKK.js} +1 -1
- package/dist/assets/{use-config-CPl_F79t.js → use-config-BM5jC65L.js} +1 -1
- package/dist/assets/{use-desktop-capabilities-CEg9-DrQ.js → use-desktop-capabilities-ezKJwKqg.js} +1 -1
- package/dist/assets/{use-viewport-layout-CPZUmTPi.js → use-viewport-layout-vmbQUNT6.js} +1 -1
- package/dist/assets/x-DSz9cGhy.js +1 -0
- package/dist/index.html +34 -34
- package/dist/panel-standalone.html +11 -11
- package/package.json +3 -3
- package/src/app/components/layout/__tests__/sidebar.layout.test.tsx +2 -2
- package/src/app/components/layout/page-layout.tsx +5 -2
- package/src/app/components/layout/sidebar-rail.styles.ts +3 -3
- package/src/app/configs/__tests__/app-navigation.config.test.ts +10 -0
- package/src/app/configs/app-navigation.config.ts +6 -2
- package/src/app/styles/charcoal-theme.css +0 -3
- package/src/app/styles/design-system.css +18 -6
- package/src/app/styles/island-theme.css +2 -15
- package/src/features/agents/components/agent-details-dialog.tsx +1 -1
- package/src/features/agents/components/agents-page.tsx +5 -3
- package/src/features/app-data/components/app-data-removal-choice.tsx +1 -1
- package/src/features/apps/components/app-package-card.tsx +7 -6
- package/src/features/channels/pages/channels-list-page.tsx +1 -1
- package/src/features/chat/components/chat-sidebar-list-mode-switch.tsx +1 -1
- package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +28 -16
- package/src/features/chat/components/conversation/chat-conversation-content.tsx +8 -2
- package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +3 -3
- package/src/features/chat/components/conversation/chat-conversation-header.tsx +4 -4
- package/src/features/chat/components/layout/__tests__/chat-sidebar-session-area.test.tsx +6 -4
- package/src/features/chat/components/layout/__tests__/chat-sidebar-toolbar.test.tsx +22 -1
- package/src/features/chat/components/layout/chat-page-shell.tsx +1 -1
- package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +10 -14
- package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +50 -12
- package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +4 -4
- package/src/features/chat/components/layout/chat-sidebar.tsx +2 -2
- package/src/features/chat/features/conversation/components/session-queued-input-rows.tsx +1 -1
- package/src/features/chat/features/message/components/chat-message-list.container.tsx +12 -1
- package/src/features/chat/features/message/components/chat-tool-call-stress-harness.tsx +32 -2
- package/src/features/chat/features/message/hooks/__tests__/use-chat-message-virtualizer.test.tsx +7 -5
- package/src/features/chat/features/message/hooks/use-chat-message-virtualizer.ts +7 -3
- package/src/features/chat/features/session/components/__tests__/chat-sidebar-project-groups.test.tsx +1 -1
- package/src/features/chat/features/session/components/chat-mobile-session-row.tsx +2 -2
- package/src/features/chat/features/session/components/chat-sidebar-context-card.tsx +1 -1
- package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +1 -1
- package/src/features/chat/features/session/components/chat-sidebar-session-item.tsx +7 -5
- package/src/features/chat/features/session/components/chat-sidebar-session-list.tsx +45 -10
- package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +1 -1
- package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +3 -5
- package/src/features/chat/features/session/components/session-header/chat-session-header-menu-item.tsx +4 -3
- package/src/features/chat/features/session/components/session-header/chat-session-more-actions-menu.tsx +3 -0
- package/src/features/chat/features/session/components/session-header/chat-session-switcher-groups.tsx +6 -6
- package/src/features/chat/features/session/components/session-header/chat-session-title-switcher.tsx +6 -5
- package/src/features/chat/features/session-type/components/chat-session-type-option-item.tsx +1 -1
- package/src/features/chat/features/welcome/components/chat-welcome-agent-picker.tsx +0 -1
- package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +1 -1
- package/src/features/chat/features/welcome/components/chat-welcome-prompt-suggestions.tsx +1 -1
- package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +1 -1
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumb-browser.tsx +2 -2
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +2 -2
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +1 -1
- package/src/features/chat/features/workspace/components/child-sessions/chat-session-child-sessions.tsx +2 -2
- package/src/features/chat/features/workspace/components/file-content-preview/workspace-spreadsheet-preview.tsx +2 -2
- package/src/features/chat/features/workspace/components/overview/chat-session-continuous-attention.tsx +3 -3
- package/src/features/chat/features/workspace/components/overview/chat-session-token-usage.tsx +1 -1
- package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +4 -3
- package/src/features/chat/features/workspace/components/project-files/workspace-new-folder-tree-item.tsx +2 -1
- package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +3 -1
- package/src/features/chat/features/workspace/components/session-cron-job-content.tsx +3 -3
- package/src/features/chat/features/workspace/components/workspace-file-content-preview.tsx +2 -2
- package/src/features/chat/features/workspace/components/workspace-markdown-outline.tsx +1 -1
- package/src/features/cron/components/cron-config.tsx +3 -2
- package/src/features/cron/components/cron-job-detail-dialog.tsx +1 -1
- package/src/features/cron/components/cron-job-row.tsx +7 -7
- package/src/features/cron/components/cron-task-discovery.tsx +1 -1
- package/src/features/inbox/components/inbox-delivery-content.tsx +1 -1
- package/src/features/inbox/pages/inbox-page.tsx +25 -29
- package/src/features/marketplace/components/curated-shelves/marketplace-curated-shelves.tsx +2 -2
- package/src/features/marketplace/components/curated-shelves/marketplace-shelf-card.tsx +2 -2
- package/src/features/marketplace/components/marketplace-list-card.tsx +4 -4
- package/src/features/marketplace/components/marketplace-page-parts.tsx +4 -3
- package/src/features/marketplace/components/marketplace-page.tsx +4 -4
- package/src/features/marketplace/components/mcp/mcp-marketplace-card.tsx +2 -2
- package/src/features/marketplace/components/mcp/mcp-marketplace-page.tsx +3 -3
- package/src/features/panel-apps/components/panel-app-list-item.tsx +3 -3
- package/src/features/panel-apps/components/panel-app-open-standalone-menu-item.tsx +3 -1
- package/src/features/projects/components/project-overview.tsx +1 -1
- package/src/features/projects/pages/project-home-page.tsx +11 -2
- package/src/features/projects/pages/projects-page.test.tsx +4 -2
- package/src/features/pwa/components/pwa-install-entry.tsx +1 -1
- package/src/features/right-panel-resources/components/__tests__/page-resource-sidebar-nav.test.tsx +9 -1
- package/src/features/right-panel-resources/components/page-resource-sidebar-nav.tsx +1 -1
- package/src/features/right-panel-resources/components/right-panel-resource-home-page.tsx +1 -1
- package/src/features/service-apps/components/service-action-row.tsx +3 -3
- package/src/features/service-apps/components/service-app-list-item.tsx +4 -4
- package/src/features/service-apps/components/service-apps-panel.tsx +1 -1
- package/src/features/settings/components/config/provider-model-list.tsx +5 -5
- package/src/features/settings/components/config/provider-model-suggestions-panel.tsx +4 -4
- package/src/features/settings/components/config/provider-pill-selector.tsx +1 -1
- package/src/features/settings/pages/appearance-settings-page.tsx +2 -2
- package/src/features/settings/pages/providers-config-page.tsx +6 -6
- package/src/features/side-dock/components/side-dock.tsx +4 -4
- package/src/index.css +4 -0
- package/src/platforms/desktop/components/desktop-window-chrome.tsx +1 -1
- package/src/platforms/mobile/components/mobile-app-shell.tsx +1 -1
- package/src/platforms/mobile/components/mobile-bottom-nav.tsx +10 -9
- package/src/platforms/mobile/components/mobile-settings-shell.tsx +24 -23
- package/src/platforms/mobile/components/mobile-topbar.tsx +10 -11
- package/src/shared/components/common/brand-header.tsx +1 -1
- package/src/shared/components/common/searchable-model-input.tsx +2 -2
- package/src/shared/components/config-split-page.tsx +3 -3
- package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +34 -2
- package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +38 -7
- package/src/shared/components/doc-browser/doc-browser.tsx +5 -1
- package/src/shared/components/path-picker/server-path-picker-locations.tsx +1 -1
- package/src/shared/components/settings/settings-page.tsx +1 -1
- package/src/shared/components/ui/actions/__tests__/icon-action-button.test.tsx +5 -5
- package/src/shared/components/ui/actions/action-feedback.ts +8 -0
- package/src/shared/components/ui/actions/icon-action-button.tsx +13 -12
- package/src/shared/components/ui/button.tsx +3 -3
- package/src/shared/components/ui/card.tsx +1 -1
- package/src/shared/components/ui/context-menu/context-menu-items.tsx +6 -5
- package/src/shared/components/ui/dialog.tsx +4 -3
- package/src/shared/components/ui/input.tsx +7 -2
- package/src/shared/components/ui/overlays/sheet.tsx +1 -1
- package/src/shared/components/ui/popover.tsx +1 -1
- package/src/shared/components/ui/select.tsx +3 -2
- package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +8 -6
- package/src/shared/components/ui/tabs.tsx +3 -3
- package/src/shared/components/ui/textarea.tsx +1 -0
- package/src/shared/components/workbench/workbench-surface-toolbar.tsx +3 -4
- package/src/shared/components/workbench/workbench-surface.tsx +2 -2
- package/src/shared/lib/i18n/locales/en-US/agents.json +2 -0
- package/src/shared/lib/i18n/locales/en-US/core.json +1 -0
- package/src/shared/lib/i18n/locales/en-US/desktop-update.json +1 -1
- package/src/shared/lib/i18n/locales/zh-CN/agents.json +2 -0
- package/src/shared/lib/i18n/locales/zh-CN/core.json +1 -0
- package/src/shared/lib/i18n/locales/zh-CN/desktop-update.json +1 -1
- package/dist/assets/app-presenter-provider-C02YPoMr.js +0 -124
- package/dist/assets/card-BLXvBstA.js +0 -1
- package/dist/assets/config-split-page-G7Kt2BnV.js +0 -1
- package/dist/assets/context-menu-rd7b_kVD.js +0 -1
- package/dist/assets/doc-browser-dBiR9Qi0.js +0 -1
- package/dist/assets/loader-circle-BA7EMkih.js +0 -1
- package/dist/assets/login-page-VdMyNkFf.js +0 -1
- package/dist/assets/main-CR0SrTBf.js +0 -2
- package/dist/assets/main-DXH6EdXI.css +0 -1
- package/dist/assets/main-i18n-catalog.config-Btp_OowF.js +0 -1
- package/dist/assets/mcp-marketplace-page-jacRwiI-.js +0 -1
- package/dist/assets/panel-app-CC0bVSu4.js +0 -1
- package/dist/assets/panel-app-i18n-catalog.config-LUSBp5Ce.js +0 -1
- package/dist/assets/panelStandalone-Y91OJkgV.css +0 -1
- package/dist/assets/projects-D56yAPNT.js +0 -1
- package/dist/assets/provider-models-C3frdXeW.js +0 -1
- package/dist/assets/provider-scoped-model-input-CYetrPYZ.js +0 -1
- package/dist/assets/providers-config-page-DESB1h8g.js +0 -1
- package/dist/assets/remote-DiGFV8nP.js +0 -1
- package/dist/assets/security-config-C5-RQVpS.js +0 -1
- package/dist/assets/service-apps-panel-CKE5HKNY.js +0 -1
- package/dist/assets/x--xxUvHKW.js +0 -1
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
TooltipTrigger,
|
|
7
7
|
} from '@/shared/components/ui/tooltip';
|
|
8
8
|
import { cn } from '@/shared/lib/utils';
|
|
9
|
+
import { ACTION_FEEDBACK } from './action-feedback';
|
|
9
10
|
|
|
10
11
|
type IconActionButtonSize = 'sm' | 'md' | 'lg';
|
|
11
12
|
type IconActionButtonTone = 'default' | 'surface' | 'strong';
|
|
@@ -17,7 +18,7 @@ type IconActionButtonProps = Omit<
|
|
|
17
18
|
icon: React.ReactNode;
|
|
18
19
|
label: string;
|
|
19
20
|
size?: IconActionButtonSize;
|
|
20
|
-
/**
|
|
21
|
+
/** @deprecated All neutral icon actions now share the theme feedback color. */
|
|
21
22
|
tone?: IconActionButtonTone;
|
|
22
23
|
tooltip?: string | false | null;
|
|
23
24
|
tooltipSide?: 'top' | 'right' | 'bottom' | 'left';
|
|
@@ -29,14 +30,9 @@ const SIZE_CLASS: Record<IconActionButtonSize, string> = {
|
|
|
29
30
|
lg: 'h-8 w-8 rounded-lg p-1.5',
|
|
30
31
|
};
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
surface:
|
|
36
|
-
'text-muted-foreground hover:bg-gray-200/60 hover:text-gray-900 active:bg-gray-200/80 disabled:text-muted-foreground/45 disabled:hover:bg-transparent disabled:hover:text-muted-foreground/45',
|
|
37
|
-
strong:
|
|
38
|
-
'text-muted-foreground hover:bg-black/10 hover:text-foreground disabled:text-muted-foreground/45 disabled:hover:bg-transparent disabled:hover:text-muted-foreground/45',
|
|
39
|
-
};
|
|
33
|
+
export function IconActionGroup({ children, className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
34
|
+
return <div {...props} className={cn('flex shrink-0 items-center gap-1 max-md:gap-0', className)}>{children}</div>;
|
|
35
|
+
}
|
|
40
36
|
|
|
41
37
|
const IconActionButton = React.forwardRef<HTMLButtonElement, IconActionButtonProps>(
|
|
42
38
|
(
|
|
@@ -60,14 +56,19 @@ const IconActionButton = React.forwardRef<HTMLButtonElement, IconActionButtonPro
|
|
|
60
56
|
type="button"
|
|
61
57
|
disabled={disabled}
|
|
62
58
|
aria-label={label}
|
|
59
|
+
data-tone={tone}
|
|
63
60
|
className={cn(
|
|
64
|
-
'inline-flex shrink-0 items-center justify-center transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:cursor-not-allowed',
|
|
61
|
+
'relative inline-flex shrink-0 items-center justify-center transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:cursor-not-allowed',
|
|
65
62
|
SIZE_CLASS[size],
|
|
66
|
-
|
|
63
|
+
'text-muted-foreground hover:text-accent-foreground disabled:text-muted-foreground/45 disabled:hover:text-muted-foreground/45',
|
|
64
|
+
ACTION_FEEDBACK.icon,
|
|
65
|
+
size === 'sm' ? 'max-md:h-8 max-md:w-8' : 'max-md:h-[var(--icon-control-size)] max-md:w-[var(--icon-control-size)]',
|
|
66
|
+
"before:pointer-events-none before:absolute before:inset-0 before:rounded-[inherit] before:transition-colors before:content-[''] max-md:before:inset-auto max-md:before:h-[var(--icon-feedback-size)] max-md:before:w-[var(--icon-feedback-size)]",
|
|
67
|
+
size === 'sm' && 'max-md:before:h-7 max-md:before:w-7',
|
|
67
68
|
className
|
|
68
69
|
)}
|
|
69
70
|
>
|
|
70
|
-
{icon}
|
|
71
|
+
<span className="relative inline-flex items-center justify-center">{icon}</span>
|
|
71
72
|
</button>
|
|
72
73
|
);
|
|
73
74
|
const content = tooltip === false ? null : tooltip ?? label;
|
|
@@ -7,13 +7,13 @@ const buttonVariants = cva(
|
|
|
7
7
|
{
|
|
8
8
|
variants: {
|
|
9
9
|
variant: {
|
|
10
|
-
default: 'bg-primary text-primary-foreground hover:bg-primary-
|
|
10
|
+
default: 'bg-primary text-primary-foreground hover:bg-[hsl(var(--primary-hover))] active:bg-[hsl(var(--primary-active))] shadow-sm',
|
|
11
11
|
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
|
12
12
|
outline: 'border border-border bg-card text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
|
|
13
13
|
secondary: 'bg-muted text-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
|
|
14
14
|
ghost: 'text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
|
|
15
15
|
link: 'text-primary underline-offset-4 hover:underline',
|
|
16
|
-
primary: 'bg-primary text-primary-foreground hover:bg-primary-
|
|
16
|
+
primary: 'bg-primary text-primary-foreground hover:bg-[hsl(var(--primary-hover))] active:bg-[hsl(var(--primary-active))] shadow-sm',
|
|
17
17
|
subtle: 'bg-muted text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
|
|
18
18
|
'primary-outline': 'border border-primary/30 text-primary hover:bg-primary hover:text-primary-foreground'
|
|
19
19
|
},
|
|
@@ -42,7 +42,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
42
42
|
({ className, variant, size, ...props }, ref) => {
|
|
43
43
|
return (
|
|
44
44
|
<button
|
|
45
|
-
className={cn(buttonVariants({ variant, size, className }))}
|
|
45
|
+
className={cn(buttonVariants({ variant, size, className }), size !== 'icon' && 'max-md:min-h-[var(--control-touch-size)]')}
|
|
46
46
|
ref={ref}
|
|
47
47
|
{...props}
|
|
48
48
|
/>
|
|
@@ -17,7 +17,7 @@ const Card = React.forwardRef<
|
|
|
17
17
|
? 'border-border shadow-card'
|
|
18
18
|
: 'border-border/75 shadow-none',
|
|
19
19
|
hover && surface === 'raised' && 'hover:border-primary/25 hover:shadow-card-hover',
|
|
20
|
-
hover && surface === 'flat' && 'hover:bg-
|
|
20
|
+
hover && surface === 'flat' && 'hover:bg-[var(--interaction-hover)]',
|
|
21
21
|
className
|
|
22
22
|
)}
|
|
23
23
|
{...props}
|
|
@@ -2,10 +2,11 @@ import { useCallback, useEffect, useRef, useState, type ReactNode } from "react"
|
|
|
2
2
|
import * as Popover from "@radix-ui/react-popover";
|
|
3
3
|
import { ChevronRight } from "lucide-react";
|
|
4
4
|
import { cn } from "@/shared/lib/utils";
|
|
5
|
+
import { ACTION_FEEDBACK, ACTION_MENU_ITEM_CLASS } from '@/shared/components/ui/actions/action-feedback';
|
|
5
6
|
import type { ContextMenuGroup, ContextMenuItem } from "./context-menu";
|
|
6
7
|
|
|
7
8
|
export const CONTEXT_MENU_SURFACE_CLASS =
|
|
8
|
-
"w-max min-w-52 max-w-[min(18rem,calc(100vw-16px))] overflow-y-auto rounded-xl border border-border bg-popover p-1 text-popover-foreground shadow-
|
|
9
|
+
"w-max min-w-52 max-w-[min(18rem,calc(100vw-16px))] overflow-y-auto rounded-xl border border-border/40 bg-popover p-1 text-popover-foreground shadow-floating outline-none";
|
|
9
10
|
|
|
10
11
|
function MenuItemContent({ item }: { item: ContextMenuItem }) {
|
|
11
12
|
return <>
|
|
@@ -59,7 +60,7 @@ function ContextSubmenu({ item, open, onOpenChange, onClose, className, children
|
|
|
59
60
|
aria-expanded={open}
|
|
60
61
|
disabled={item.disabled}
|
|
61
62
|
data-menu-key={item.key}
|
|
62
|
-
className={cn(className, open && "bg-
|
|
63
|
+
className={cn(className, open && "bg-[var(--interaction-hover)]")}
|
|
63
64
|
onPointerEnter={(event) => {
|
|
64
65
|
if (event.pointerType === "touch") return;
|
|
65
66
|
keyboardOpen.current = false;
|
|
@@ -151,11 +152,11 @@ export function ContextMenuItems({ groups, onClose }: {
|
|
|
151
152
|
}}
|
|
152
153
|
>
|
|
153
154
|
{groups.filter((group) => group.items.length).map((group, index) => <div key={group.key} role="group">
|
|
154
|
-
{index > 0 ? <div className="my-1 h-px bg-border" /> : null}
|
|
155
|
+
{index > 0 ? <div className="mx-2 my-1 h-px bg-border/50" /> : null}
|
|
155
156
|
{group.items.map((item) => {
|
|
156
157
|
const className = cn(
|
|
157
|
-
|
|
158
|
-
item.destructive ?
|
|
158
|
+
ACTION_MENU_ITEM_CLASS,
|
|
159
|
+
item.destructive ? ACTION_FEEDBACK.destructive : `text-foreground ${ACTION_FEEDBACK.item}`,
|
|
159
160
|
);
|
|
160
161
|
const content = <MenuItemContent item={item} />;
|
|
161
162
|
if (item.children) return <ContextSubmenu key={item.key} item={item} open={openKey === item.key}
|
|
@@ -40,6 +40,7 @@ const DialogContent = React.forwardRef<
|
|
|
40
40
|
data-theme-overlay="dialog"
|
|
41
41
|
className={cn(
|
|
42
42
|
"fixed left-[50%] top-[50%] z-[var(--z-modal,10050)] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl border border-border bg-popover p-6 text-popover-foreground shadow-xl duration-base data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
|
|
43
|
+
"max-md:max-w-[calc(100vw-1.5rem)] max-h-[calc(100dvh-1.5rem)] max-md:max-h-[calc(100dvh-env(safe-area-inset-top,0px)-env(safe-area-inset-bottom,0px)-1.5rem)] overflow-y-auto overscroll-contain",
|
|
43
44
|
className
|
|
44
45
|
)}
|
|
45
46
|
{...props}
|
|
@@ -48,7 +49,7 @@ const DialogContent = React.forwardRef<
|
|
|
48
49
|
}}
|
|
49
50
|
>
|
|
50
51
|
{children}
|
|
51
|
-
<DialogPrimitive.Close className="absolute right-
|
|
52
|
+
<DialogPrimitive.Close className="absolute right-1 top-1 flex h-11 w-11 items-center justify-center rounded-lg opacity-70 transition-all duration-fast hover:bg-[var(--interaction-hover)] hover:text-accent-foreground hover:opacity-100 focus:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:pointer-events-none sm:right-4 sm:top-4 sm:h-6 sm:w-6">
|
|
52
53
|
<X className="h-4 w-4 text-muted-foreground" />
|
|
53
54
|
<span className="sr-only">Close</span>
|
|
54
55
|
</DialogPrimitive.Close>
|
|
@@ -63,7 +64,7 @@ const DialogHeader = ({
|
|
|
63
64
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
64
65
|
<div
|
|
65
66
|
className={cn(
|
|
66
|
-
"flex flex-col space-y-2
|
|
67
|
+
"flex flex-col space-y-2 pr-7 text-left",
|
|
67
68
|
className
|
|
68
69
|
)}
|
|
69
70
|
{...props}
|
|
@@ -77,7 +78,7 @@ const DialogFooter = ({
|
|
|
77
78
|
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
78
79
|
<div
|
|
79
80
|
className={cn(
|
|
80
|
-
"flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-3",
|
|
81
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end sm:gap-3",
|
|
81
82
|
className
|
|
82
83
|
)}
|
|
83
84
|
{...props}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { cn } from '@/shared/lib/utils';
|
|
3
3
|
|
|
4
|
-
export type InputProps = React.InputHTMLAttributes<HTMLInputElement
|
|
4
|
+
export type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
5
|
+
density?: 'default' | 'compact';
|
|
6
|
+
};
|
|
5
7
|
|
|
6
8
|
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
7
|
-
({ className, type, ...props }, ref) => {
|
|
9
|
+
({ className, density = 'default', type, ...props }, ref) => {
|
|
8
10
|
return (
|
|
9
11
|
<input
|
|
10
12
|
type={type}
|
|
11
13
|
className={cn(
|
|
12
14
|
'flex h-9 w-full rounded-xl border border-border/75 bg-card px-3.5 py-2 text-sm text-foreground file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground/55 placeholder:font-normal transition-colors focus:outline-none focus:ring-0 disabled:cursor-not-allowed disabled:opacity-50',
|
|
15
|
+
density === 'default'
|
|
16
|
+
? 'max-md:min-h-[var(--control-touch-size)] max-md:text-base'
|
|
17
|
+
: 'text-[13px] max-md:min-h-0 max-md:text-[13px]',
|
|
13
18
|
className
|
|
14
19
|
)}
|
|
15
20
|
ref={ref}
|
|
@@ -69,7 +69,7 @@ const SheetContent = React.forwardRef<
|
|
|
69
69
|
}}
|
|
70
70
|
>
|
|
71
71
|
{children}
|
|
72
|
-
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-lg p-1.5 text-muted-foreground opacity-75 transition-colors hover:bg-
|
|
72
|
+
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-lg p-1.5 text-muted-foreground opacity-75 transition-colors hover:bg-[var(--interaction-hover)] hover:text-foreground hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:pointer-events-none">
|
|
73
73
|
<X className="h-4 w-4" />
|
|
74
74
|
<span className="sr-only">{closeLabel}</span>
|
|
75
75
|
</SheetPrimitive.Close>
|
|
@@ -31,7 +31,7 @@ const PopoverContent = React.forwardRef<
|
|
|
31
31
|
align={align}
|
|
32
32
|
collisionPadding={collisionPadding}
|
|
33
33
|
className={cn(
|
|
34
|
-
'z-[var(--z-popover,10100)] w-72 overflow-x-hidden overflow-y-auto rounded-
|
|
34
|
+
'z-[var(--z-popover,10100)] w-72 overflow-x-hidden overflow-y-auto rounded-xl border border-border/40 bg-popover p-4 text-popover-foreground shadow-floating animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
35
35
|
className,
|
|
36
36
|
variant === 'menu' && CONTEXT_MENU_SURFACE_CLASS
|
|
37
37
|
)}
|
|
@@ -26,6 +26,7 @@ const SelectTrigger = React.forwardRef<
|
|
|
26
26
|
ref={ref}
|
|
27
27
|
className={cn(
|
|
28
28
|
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-xl border border-border/75 bg-card px-3 py-2 text-sm text-foreground ring-offset-background placeholder:text-muted-foreground transition-colors focus:outline-none focus:ring-0 focus:border-border disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
29
|
+
'max-md:min-h-[var(--control-touch-size)]',
|
|
29
30
|
className
|
|
30
31
|
)}
|
|
31
32
|
{...props}
|
|
@@ -79,7 +80,7 @@ const SelectContent = React.forwardRef<
|
|
|
79
80
|
ref={ref}
|
|
80
81
|
data-theme-overlay="select"
|
|
81
82
|
className={cn(
|
|
82
|
-
"relative z-[var(--z-popover,10100)] flex max-h-96 min-w-[8rem] flex-col overflow-hidden rounded-
|
|
83
|
+
"relative z-[var(--z-popover,10100)] flex max-h-96 min-w-[8rem] flex-col overflow-hidden rounded-xl border border-border/40 bg-popover text-popover-foreground shadow-floating data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
83
84
|
position === "popper" &&
|
|
84
85
|
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
85
86
|
className
|
|
@@ -120,7 +121,7 @@ const SelectItem = React.forwardRef<
|
|
|
120
121
|
<SelectPrimitive.Item
|
|
121
122
|
ref={ref}
|
|
122
123
|
className={cn(
|
|
123
|
-
"relative flex w-full cursor-default select-none items-center rounded-
|
|
124
|
+
"relative flex max-md:min-h-[var(--control-touch-size)] w-full cursor-default select-none items-center rounded-lg py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-[var(--interaction-hover)] focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-[var(--interaction-hover)]",
|
|
124
125
|
className
|
|
125
126
|
)}
|
|
126
127
|
{...props}
|
|
@@ -2,6 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import { MoreVertical, X } from "lucide-react";
|
|
3
3
|
import {
|
|
4
4
|
IconActionButton,
|
|
5
|
+
IconActionGroup,
|
|
5
6
|
type IconActionButtonProps,
|
|
6
7
|
} from "@/shared/components/ui/actions/icon-action-button";
|
|
7
8
|
import {
|
|
@@ -235,9 +236,9 @@ function CompactTabItem({
|
|
|
235
236
|
"flex max-w-[180px] cursor-pointer items-center gap-1.5 border-r border-gray-200/70 border-b-2 px-2.5 py-2 transition-colors",
|
|
236
237
|
"group relative",
|
|
237
238
|
tab.active
|
|
238
|
-
? (activeTabClassName ?? "border-b-primary bg-
|
|
239
|
+
? (activeTabClassName ?? "border-b-primary bg-[var(--interaction-selection)] text-foreground")
|
|
239
240
|
: (inactiveTabClassName ??
|
|
240
|
-
"border-b-transparent bg-
|
|
241
|
+
"border-b-transparent bg-transparent text-muted-foreground hover:bg-[var(--interaction-hover)]"),
|
|
241
242
|
)}
|
|
242
243
|
>
|
|
243
244
|
<CompactTabLabelButton tab={tab} labelClassName={labelClassName} />
|
|
@@ -286,7 +287,7 @@ export function CompactTabStrip({
|
|
|
286
287
|
>
|
|
287
288
|
<div
|
|
288
289
|
className={cn(
|
|
289
|
-
"min-w-0 flex-1 overflow-x-auto overflow-y-hidden",
|
|
290
|
+
"flex min-w-0 flex-1 items-stretch overflow-x-auto overflow-y-hidden",
|
|
290
291
|
scrollClassName,
|
|
291
292
|
)}
|
|
292
293
|
onPointerDown={onScrollPointerDown}
|
|
@@ -305,13 +306,14 @@ export function CompactTabStrip({
|
|
|
305
306
|
))}
|
|
306
307
|
</div>
|
|
307
308
|
</div>
|
|
308
|
-
<
|
|
309
|
-
className={
|
|
309
|
+
<IconActionGroup
|
|
310
|
+
className={actionsClassName}
|
|
310
311
|
data-testid={actionsTestId}
|
|
311
312
|
onPointerDown={(event) => event.stopPropagation()}
|
|
312
313
|
>
|
|
313
314
|
{actions.map((action) => (
|
|
314
315
|
<IconActionButton
|
|
316
|
+
size="sm"
|
|
315
317
|
key={action.key}
|
|
316
318
|
icon={action.icon}
|
|
317
319
|
label={action.label}
|
|
@@ -320,7 +322,7 @@ export function CompactTabStrip({
|
|
|
320
322
|
className={actionButtonClassName}
|
|
321
323
|
/>
|
|
322
324
|
))}
|
|
323
|
-
</
|
|
325
|
+
</IconActionGroup>
|
|
324
326
|
</div>
|
|
325
327
|
);
|
|
326
328
|
}
|
|
@@ -63,7 +63,7 @@ export function TabsList({ children, className }: TabsListProps) {
|
|
|
63
63
|
role="tablist"
|
|
64
64
|
onKeyDown={handleKeyDown}
|
|
65
65
|
className={cn(
|
|
66
|
-
'inline-flex h-9 items-center justify-center rounded-xl bg-muted p-1 text-muted-foreground',
|
|
66
|
+
'inline-flex h-9 max-md:h-auto items-center justify-center rounded-xl bg-muted p-1 text-muted-foreground',
|
|
67
67
|
className
|
|
68
68
|
)}
|
|
69
69
|
>
|
|
@@ -87,9 +87,9 @@ export function TabsTrigger({ value, children, className }: TabsTriggerProps) {
|
|
|
87
87
|
tabIndex={isActive ? 0 : -1}
|
|
88
88
|
data-state={isActive ? 'active' : 'inactive'}
|
|
89
89
|
className={cn(
|
|
90
|
-
'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-[13px] font-medium transition-all duration-fast focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:pointer-events-none disabled:opacity-50',
|
|
90
|
+
'inline-flex max-md:min-h-[var(--control-touch-size)] items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-[13px] font-medium transition-all duration-fast focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:pointer-events-none disabled:opacity-50',
|
|
91
91
|
isActive
|
|
92
|
-
? 'bg-
|
|
92
|
+
? 'bg-[var(--interaction-selection)] text-foreground'
|
|
93
93
|
: 'text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground',
|
|
94
94
|
className
|
|
95
95
|
)}
|
|
@@ -8,6 +8,7 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
|
8
8
|
<textarea
|
|
9
9
|
className={cn(
|
|
10
10
|
"flex min-h-28 w-full rounded-xl border border-border/75 bg-card px-3.5 py-2.5 text-sm text-foreground placeholder:text-muted-foreground/55 placeholder:font-normal transition-colors focus:outline-none focus:ring-0 disabled:cursor-not-allowed disabled:opacity-50",
|
|
11
|
+
'max-md:text-base',
|
|
11
12
|
className,
|
|
12
13
|
)}
|
|
13
14
|
ref={ref}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
PictureInPicture2,
|
|
8
8
|
X,
|
|
9
9
|
} from "lucide-react";
|
|
10
|
-
import { IconActionButton } from "@/shared/components/ui/actions/icon-action-button";
|
|
10
|
+
import { IconActionButton, IconActionGroup } from "@/shared/components/ui/actions/icon-action-button";
|
|
11
11
|
import { t } from "@/shared/lib/i18n";
|
|
12
12
|
import type { WorkbenchSurfaceState } from "./types/workbench-surface.types";
|
|
13
13
|
|
|
@@ -33,8 +33,7 @@ export function WorkbenchSurfaceToolbar({
|
|
|
33
33
|
onOpenMain?: () => void;
|
|
34
34
|
}) {
|
|
35
35
|
return (
|
|
36
|
-
<
|
|
37
|
-
className="flex shrink-0 items-center gap-0.5"
|
|
36
|
+
<IconActionGroup
|
|
38
37
|
data-workbench-actions=""
|
|
39
38
|
>
|
|
40
39
|
{onOpenMain && (
|
|
@@ -97,6 +96,6 @@ export function WorkbenchSurfaceToolbar({
|
|
|
97
96
|
label={closeLabel}
|
|
98
97
|
onClick={onClose}
|
|
99
98
|
/>
|
|
100
|
-
</
|
|
99
|
+
</IconActionGroup>
|
|
101
100
|
);
|
|
102
101
|
}
|
|
@@ -265,8 +265,8 @@ export function WorkbenchSurface({
|
|
|
265
265
|
}}
|
|
266
266
|
>
|
|
267
267
|
<header
|
|
268
|
-
className="flex min-h-10 shrink-0 select-none items-center gap-
|
|
269
|
-
style={{ touchAction: floating ? "none" : undefined }}
|
|
268
|
+
className="flex min-h-10 shrink-0 select-none items-center gap-1 border-b border-border/60 bg-muted/30 px-2"
|
|
269
|
+
style={{ touchAction: floating ? "none" : undefined, paddingTop: isCompact ? "env(safe-area-inset-top, 0px)" : undefined }}
|
|
270
270
|
onPointerDown={(event) => startInteraction(event)}
|
|
271
271
|
onDoubleClick={(event) => {
|
|
272
272
|
if (!isCompact && !blocksDrag(event.target))
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"agentsPageTitle": "Agents",
|
|
3
|
+
"mobileAgents": "Agents",
|
|
4
|
+
"mobileNavigation": "Main navigation",
|
|
3
5
|
"agentsPageDescription": "Manage conversational agent identities. Each agent owns its home directory, setup, memory, and skills.",
|
|
4
6
|
"agentsHeroEyebrow": "Agent Gallery",
|
|
5
7
|
"agentsHeroTitle": "Give every agent the presence of a real collaborator",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"runtimeUpdatesPageDescription": "NextClaw checks every two hours; you choose when to start each update.",
|
|
5
5
|
"runtimeUpdatesUnavailableTitle": "Updates Are Currently Unavailable",
|
|
6
6
|
"runtimeUpdatesUnavailableDescription": "This runtime environment does not currently expose an update host.",
|
|
7
|
-
"runtimeUpdatesUnavailableHint": "
|
|
7
|
+
"runtimeUpdatesUnavailableHint": "Update using the method you used to install NextClaw. An update button will appear when in-app updates are supported.",
|
|
8
8
|
"runtimeUpdatesHostVersion": "Host Version",
|
|
9
9
|
"runtimeUpdatesDownloadedBannerDescription": "Version {version} has finished downloading and is ready to finish updating.",
|
|
10
10
|
"runtimeUpdatesActionsDescription": "Check manually, then complete the update in one action whenever you are ready.",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"runtimeUpdatesPageDescription": "系统每两小时自动检查新版本;发现更新后,由你决定何时开始更新。",
|
|
5
5
|
"runtimeUpdatesUnavailableTitle": "当前环境暂不支持更新",
|
|
6
6
|
"runtimeUpdatesUnavailableDescription": "这个运行环境暂时没有可用的更新宿主。",
|
|
7
|
-
"runtimeUpdatesUnavailableHint": "
|
|
7
|
+
"runtimeUpdatesUnavailableHint": "请使用安装 NextClaw 时的方式更新;支持应用内更新后,更新按钮会自动出现。",
|
|
8
8
|
"runtimeUpdatesHostVersion": "宿主版本",
|
|
9
9
|
"runtimeUpdatesDownloadedBannerDescription": "版本 {version} 已下载完成,可以继续完成更新。",
|
|
10
10
|
"runtimeUpdatesActionsDescription": "你可以手动检查,并在准备好之后一次完成更新。",
|