@
refactor(asset-center): 提取预览右键菜单子菜单为独立组件 - PreviewSubmenus.tsx(252 行):基材选择子菜单 + UV 渲染参数子菜单 - AssetCenterClient.tsx 3268→3085 行 @
This commit is contained in:
parent
85d9eb7acc
commit
fe80bc77ba
@ -176,6 +176,7 @@ import { VariantEditModal } from './VariantEditModal'
|
||||
import { FamilyEditModal } from './FamilyEditModal'
|
||||
import { CadImportModal } from './CadImportModal'
|
||||
import { FamilyListPanel } from './FamilyListPanel'
|
||||
import { SubstrateSubmenu, UvSettingsSubmenu } from './PreviewSubmenus'
|
||||
|
||||
// ---- 主组件内的渲染辅助函数 ----
|
||||
|
||||
@ -2898,212 +2899,28 @@ export default function AssetCenterClient({
|
||||
bodyMaxHeight={previewContextMenuBodyMaxHeight}
|
||||
>
|
||||
{activePreviewSubmenu === 'preview-substrate' ? (
|
||||
<div
|
||||
className="pointer-events-auto absolute animate-fadeInUp"
|
||||
style={{
|
||||
left: `${previewSubstrateSubmenuMetrics.left}px`,
|
||||
top: `${previewSubstrateSubmenuMetrics.top}px`,
|
||||
width: `${previewSubstrateSubmenuMetrics.width}px`,
|
||||
maxHeight: `${previewSubstrateSubmenuMetrics.maxHeight}px`,
|
||||
zIndex: 221,
|
||||
animationDuration: '180ms',
|
||||
}}
|
||||
data-context-menu-root="true"
|
||||
>
|
||||
<div className="liquid-glass-subtle overflow-hidden rounded-apple-md border border-apple-separator/85 p-1.5 shadow-[0_14px_30px_rgba(15,23,42,0.16)]">
|
||||
<div className="border-b border-apple-separator/80 px-1 pb-1.5">
|
||||
<p className="px-1 pb-1 text-[11px] font-apple-system tracking-apple-wide text-[#5a6062]/75">
|
||||
选择基材
|
||||
</p>
|
||||
<div className="relative">
|
||||
<Search className="pointer-events-none absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-[#5a6062]/45" />
|
||||
<input
|
||||
aria-label="搜索基材"
|
||||
value={previewSubstrateSearch}
|
||||
onChange={(event) => setPreviewSubstrateSearch(event.target.value)}
|
||||
placeholder="搜索名称或编码"
|
||||
className="h-7 w-full rounded-apple-md border border-apple-separator/80 bg-white/80 pl-7 pr-2 text-[12px] text-[#2d3335] outline-hidden transition placeholder:text-[#5a6062]/45 focus:border-black/[0.12] focus:bg-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="overflow-y-auto px-1 py-1"
|
||||
style={{ maxHeight: `${Math.max(150, previewSubstrateSubmenuMetrics.maxHeight - 62)}px` }}
|
||||
>
|
||||
{previewFilteredSubstrateItems.length > 0 ? (
|
||||
previewFilteredSubstrateItems.map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
onClick={() => handlePreviewContextMenuItemClick(item)}
|
||||
className="mb-0.5 flex h-8 w-full items-center justify-between gap-3 rounded-apple-md border border-transparent px-2 text-left text-apple-label-primary transition hover:border-apple-separator/80 hover:bg-white/85 focus-visible:ring-2 focus-visible:ring-black/[0.08]"
|
||||
>
|
||||
<span className="min-w-0 truncate text-[12px] font-apple-system font-apple-medium">
|
||||
{item.label}
|
||||
</span>
|
||||
</button>
|
||||
))
|
||||
) : (
|
||||
<div className="px-2 py-3 text-[12px] text-[#5a6062]/65">
|
||||
没有匹配基材
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<SubstrateSubmenu
|
||||
metrics={previewSubstrateSubmenuMetrics}
|
||||
search={previewSubstrateSearch}
|
||||
onSearchChange={setPreviewSubstrateSearch}
|
||||
filteredItems={previewFilteredSubstrateItems}
|
||||
onSelect={handlePreviewContextMenuItemClick}
|
||||
/>
|
||||
) : null}
|
||||
{activePreviewSubmenu === 'preview-uv' ? (
|
||||
<div
|
||||
className="pointer-events-auto absolute animate-fadeInUp"
|
||||
style={{
|
||||
left: `${previewUvSettingsPanelPosition.left}px`,
|
||||
top: `${previewUvSettingsPanelPosition.top}px`,
|
||||
width: '264px',
|
||||
maxHeight: `${previewUvSettingsPanelPosition.maxHeight}px`,
|
||||
animationDuration: '180ms',
|
||||
}}
|
||||
data-context-menu-root="true"
|
||||
>
|
||||
<div className="liquid-glass-subtle overflow-hidden rounded-apple-md border border-apple-separator/85 p-1.5 shadow-[0_14px_30px_rgba(15,23,42,0.16)]">
|
||||
<div className="flex items-start justify-between gap-2 border-b border-apple-separator/80 px-2 pb-1.5">
|
||||
<div className="min-w-0">
|
||||
<p className="text-[11px] font-apple-system tracking-apple-wide text-[#5a6062]/75">
|
||||
{activeVariantUvNodeLabel}
|
||||
{!selectedFinishMaterialConfig ? ' · 未绑定基材花色' : ''}
|
||||
</p>
|
||||
<p className="truncate text-[13px] font-apple-system font-apple-medium text-[#2d3335]">
|
||||
渲染参数
|
||||
</p>
|
||||
</div>
|
||||
<Badge variant="subtle" size="small" className="shrink-0 border-none bg-white/75 text-[#5a6062]">
|
||||
{variantUvConfigDirty ? '待保存' : '已同步'}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="overflow-y-auto px-1 py-1"
|
||||
style={{ maxHeight: `${Math.max(190, previewUvSettingsPanelPosition.maxHeight - 48)}px` }}
|
||||
>
|
||||
<div className="mb-0.5 flex h-6 w-full items-center justify-between gap-2 rounded-apple-md border border-transparent px-2 text-left text-apple-label-primary">
|
||||
<span className="shrink-0 text-[12px] font-apple-system font-apple-medium">
|
||||
投影轴
|
||||
</span>
|
||||
<div className="grid w-[148px] grid-cols-4 gap-0.5 rounded-apple-sm border border-apple-separator bg-white/70 p-0.5">
|
||||
{UV_PROJECTION_AXIS_OPTIONS.map((option) => {
|
||||
const isSelected = variantUvEditorForm.textureProjectionAxis === option.value
|
||||
return (
|
||||
<button
|
||||
key={option.value || 'auto'}
|
||||
type="button"
|
||||
aria-label={option.label}
|
||||
aria-pressed={isSelected}
|
||||
onClick={() => handleSelectVariantUvProjectionAxis(option.value)}
|
||||
className={cn(
|
||||
'h-5 rounded-[3px] text-[11px] font-apple-system font-apple-medium transition',
|
||||
isSelected
|
||||
? 'bg-[#2d3335] text-white shadow-xs'
|
||||
: 'text-[#5a6062] hover:bg-black/[0.04] hover:text-[#2d3335]',
|
||||
)}
|
||||
>
|
||||
{option.label === '自动' ? '自' : option.label.replace(' 轴', '')}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{[
|
||||
{
|
||||
label: '整体重复',
|
||||
ariaLabel: '整体重复',
|
||||
value: variantUvEditorForm.textureRepeat,
|
||||
placeholder: '1.0',
|
||||
field: 'textureRepeat' as const,
|
||||
},
|
||||
{
|
||||
label: '旋转角度 °',
|
||||
ariaLabel: '旋转角度 °',
|
||||
value: variantUvEditorForm.textureRotation,
|
||||
placeholder: '0°',
|
||||
field: 'textureRotation' as const,
|
||||
},
|
||||
{
|
||||
label: '纹理尺寸 mm',
|
||||
ariaLabel: '纹理尺寸 mm',
|
||||
value: variantUvEditorForm.textureSizeMm,
|
||||
placeholder: '600',
|
||||
field: 'textureSizeMm' as const,
|
||||
},
|
||||
{
|
||||
label: 'U 压缩',
|
||||
ariaLabel: 'U 压缩',
|
||||
value: variantUvEditorForm.textureRepeatU,
|
||||
placeholder: '1.0',
|
||||
field: 'textureRepeatU' as const,
|
||||
},
|
||||
{
|
||||
label: 'V 压缩',
|
||||
ariaLabel: 'V 压缩',
|
||||
value: variantUvEditorForm.textureRepeatV,
|
||||
placeholder: '1.0',
|
||||
field: 'textureRepeatV' as const,
|
||||
},
|
||||
].map((item) => (
|
||||
<div
|
||||
key={item.field}
|
||||
className="mb-0.5 flex h-6 w-full items-center justify-between gap-2 rounded-apple-md border border-transparent px-2 text-left text-apple-label-primary"
|
||||
>
|
||||
<label
|
||||
htmlFor={`variant-uv-${item.field}`}
|
||||
className="shrink-0 text-[12px] font-apple-system font-apple-medium"
|
||||
>
|
||||
{item.label}
|
||||
</label>
|
||||
<input
|
||||
id={`variant-uv-${item.field}`}
|
||||
aria-label={item.ariaLabel}
|
||||
inputMode="decimal"
|
||||
value={item.value}
|
||||
onChange={(event) =>
|
||||
handlePatchVariantUvEditorForm({ [item.field]: event.target.value })
|
||||
}
|
||||
placeholder={item.placeholder}
|
||||
className="h-6 w-[108px] rounded-apple-sm border border-apple-separator bg-white/80 px-2 text-right text-[12px] text-apple-label-primary outline-hidden transition placeholder:text-apple-label-tertiary focus:border-[#2d3335]"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="mx-1 my-0.5 h-px bg-apple-separator/80" />
|
||||
|
||||
<div className="mb-0.5 grid grid-cols-2 gap-1">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleResetVariantUvEditor}
|
||||
disabled={submitting || !variantUvConfigDirty}
|
||||
className="flex h-6 items-center rounded-apple-md border border-transparent px-2 text-left text-[12px] font-apple-system font-apple-medium text-apple-label-primary transition hover:border-apple-separator/80 hover:bg-white/85 disabled:cursor-not-allowed disabled:bg-apple-bg-secondary/25 disabled:text-apple-label-tertiary"
|
||||
>
|
||||
还原
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleClearVariantUvEditor}
|
||||
disabled={submitting}
|
||||
className="flex h-6 items-center rounded-apple-md border border-transparent px-2 text-left text-[12px] font-apple-system font-apple-medium text-apple-label-primary transition hover:border-apple-separator/80 hover:bg-white/85 disabled:cursor-not-allowed disabled:bg-apple-bg-secondary/25 disabled:text-apple-label-tertiary"
|
||||
>
|
||||
清空
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
disabled={submitting || !variantUvConfigDirty}
|
||||
onClick={handleKeepVariantUvDraft}
|
||||
className="mb-0.5 flex h-6 w-full items-center rounded-apple-md border border-transparent px-2 text-left text-[12px] font-apple-system font-apple-medium text-apple-label-primary transition hover:border-apple-separator/80 hover:bg-white/85 disabled:cursor-not-allowed disabled:bg-apple-bg-secondary/25 disabled:text-apple-label-tertiary"
|
||||
>
|
||||
暂存渲染参数
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<UvSettingsSubmenu
|
||||
position={previewUvSettingsPanelPosition}
|
||||
form={variantUvEditorForm}
|
||||
onFormPatch={handlePatchVariantUvEditorForm}
|
||||
onSelectProjectionAxis={handleSelectVariantUvProjectionAxis}
|
||||
onReset={handleResetVariantUvEditor}
|
||||
onClear={handleClearVariantUvEditor}
|
||||
onKeepDraft={handleKeepVariantUvDraft}
|
||||
configDirty={variantUvConfigDirty}
|
||||
submitting={submitting}
|
||||
nodeLabel={activeVariantUvNodeLabel}
|
||||
hasMaterialConfig={!!selectedFinishMaterialConfig}
|
||||
/>
|
||||
) : null}
|
||||
</ContextMenu>
|
||||
)}
|
||||
|
||||
252
furniture-3d-system/src/app/asset-center/PreviewSubmenus.tsx
Normal file
252
furniture-3d-system/src/app/asset-center/PreviewSubmenus.tsx
Normal file
@ -0,0 +1,252 @@
|
||||
'use client'
|
||||
|
||||
import { Search } from 'lucide-react'
|
||||
import { Badge } from '@/components/ui/Badge'
|
||||
import { cn } from '@/lib/utils'
|
||||
import type { AssetVariantUvProjectionAxis } from '@/lib/asset-variant-render-config'
|
||||
import type { VariantUvEditorFormState } from './asset-center-types'
|
||||
import { UV_PROJECTION_AXIS_OPTIONS } from './asset-center-types'
|
||||
|
||||
// ---- 基材选择子菜单 ----
|
||||
|
||||
interface SubstrateSubmenuItem {
|
||||
id: string
|
||||
label: string
|
||||
}
|
||||
|
||||
interface SubstrateSubmenuMetrics {
|
||||
left: number
|
||||
top: number
|
||||
width: number
|
||||
maxHeight: number
|
||||
}
|
||||
|
||||
interface SubstrateSubmenuProps {
|
||||
metrics: SubstrateSubmenuMetrics
|
||||
search: string
|
||||
onSearchChange: (value: string) => void
|
||||
filteredItems: SubstrateSubmenuItem[]
|
||||
onSelect: (item: SubstrateSubmenuItem) => void
|
||||
}
|
||||
|
||||
export function SubstrateSubmenu({
|
||||
metrics,
|
||||
search,
|
||||
onSearchChange,
|
||||
filteredItems,
|
||||
onSelect,
|
||||
}: SubstrateSubmenuProps) {
|
||||
return (
|
||||
<div
|
||||
className="pointer-events-auto absolute animate-fadeInUp"
|
||||
style={{
|
||||
left: `${metrics.left}px`,
|
||||
top: `${metrics.top}px`,
|
||||
width: `${metrics.width}px`,
|
||||
maxHeight: `${metrics.maxHeight}px`,
|
||||
zIndex: 221,
|
||||
animationDuration: '180ms',
|
||||
}}
|
||||
data-context-menu-root="true"
|
||||
>
|
||||
<div className="liquid-glass-subtle overflow-hidden rounded-apple-md border border-apple-separator/85 p-1.5 shadow-[0_14px_30px_rgba(15,23,42,0.16)]">
|
||||
<div className="border-b border-apple-separator/80 px-1 pb-1.5">
|
||||
<p className="px-1 pb-1 text-[11px] font-apple-system tracking-apple-wide text-[#5a6062]/75">
|
||||
选择基材
|
||||
</p>
|
||||
<div className="relative">
|
||||
<Search className="pointer-events-none absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-[#5a6062]/45" />
|
||||
<input
|
||||
aria-label="搜索基材"
|
||||
value={search}
|
||||
onChange={(event) => onSearchChange(event.target.value)}
|
||||
placeholder="搜索名称或编码"
|
||||
className="h-7 w-full rounded-apple-md border border-apple-separator/80 bg-white/80 pl-7 pr-2 text-[12px] text-[#2d3335] outline-hidden transition placeholder:text-[#5a6062]/45 focus:border-black/[0.12] focus:bg-white"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="overflow-y-auto px-1 py-1"
|
||||
style={{ maxHeight: `${Math.max(150, metrics.maxHeight - 62)}px` }}
|
||||
>
|
||||
{filteredItems.length > 0 ? (
|
||||
filteredItems.map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
onClick={() => onSelect(item)}
|
||||
className="mb-0.5 flex h-8 w-full items-center justify-between gap-3 rounded-apple-md border border-transparent px-2 text-left text-apple-label-primary transition hover:border-apple-separator/80 hover:bg-white/85 focus-visible:ring-2 focus-visible:ring-black/[0.08]"
|
||||
>
|
||||
<span className="min-w-0 truncate text-[12px] font-apple-system font-apple-medium">
|
||||
{item.label}
|
||||
</span>
|
||||
</button>
|
||||
))
|
||||
) : (
|
||||
<div className="px-2 py-3 text-[12px] text-[#5a6062]/65">
|
||||
没有匹配基材
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ---- UV 渲染参数子菜单 ----
|
||||
|
||||
interface UvSettingsPanelPosition {
|
||||
left: number
|
||||
top: number
|
||||
maxHeight: number
|
||||
}
|
||||
|
||||
interface UvSubmenuProps {
|
||||
position: UvSettingsPanelPosition
|
||||
form: VariantUvEditorFormState
|
||||
onFormPatch: (patch: Partial<VariantUvEditorFormState>) => void
|
||||
onSelectProjectionAxis: (value: '' | AssetVariantUvProjectionAxis) => void
|
||||
onReset: () => void
|
||||
onClear: () => void
|
||||
onKeepDraft: () => void
|
||||
configDirty: boolean
|
||||
submitting: boolean
|
||||
nodeLabel: string
|
||||
hasMaterialConfig: boolean
|
||||
}
|
||||
|
||||
export function UvSettingsSubmenu({
|
||||
position,
|
||||
form,
|
||||
onFormPatch,
|
||||
onSelectProjectionAxis,
|
||||
onReset,
|
||||
onClear,
|
||||
onKeepDraft,
|
||||
configDirty,
|
||||
submitting,
|
||||
nodeLabel,
|
||||
hasMaterialConfig,
|
||||
}: UvSubmenuProps) {
|
||||
return (
|
||||
<div
|
||||
className="pointer-events-auto absolute animate-fadeInUp"
|
||||
style={{
|
||||
left: `${position.left}px`,
|
||||
top: `${position.top}px`,
|
||||
width: '264px',
|
||||
maxHeight: `${position.maxHeight}px`,
|
||||
animationDuration: '180ms',
|
||||
}}
|
||||
data-context-menu-root="true"
|
||||
>
|
||||
<div className="liquid-glass-subtle overflow-hidden rounded-apple-md border border-apple-separator/85 p-1.5 shadow-[0_14px_30px_rgba(15,23,42,0.16)]">
|
||||
<div className="flex items-start justify-between gap-2 border-b border-apple-separator/80 px-2 pb-1.5">
|
||||
<div className="min-w-0">
|
||||
<p className="text-[11px] font-apple-system tracking-apple-wide text-[#5a6062]/75">
|
||||
{nodeLabel}
|
||||
{!hasMaterialConfig ? ' · 未绑定基材花色' : ''}
|
||||
</p>
|
||||
<p className="truncate text-[13px] font-apple-system font-apple-medium text-[#2d3335]">
|
||||
渲染参数
|
||||
</p>
|
||||
</div>
|
||||
<Badge variant="subtle" size="small" className="shrink-0 border-none bg-white/75 text-[#5a6062]">
|
||||
{configDirty ? '待保存' : '已同步'}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="overflow-y-auto px-1 py-1"
|
||||
style={{ maxHeight: `${Math.max(190, position.maxHeight - 48)}px` }}
|
||||
>
|
||||
<div className="mb-0.5 flex h-6 w-full items-center justify-between gap-2 rounded-apple-md border border-transparent px-2 text-left text-apple-label-primary">
|
||||
<span className="shrink-0 text-[12px] font-apple-system font-apple-medium">
|
||||
投影轴
|
||||
</span>
|
||||
<div className="grid w-[148px] grid-cols-4 gap-0.5 rounded-apple-sm border border-apple-separator bg-white/70 p-0.5">
|
||||
{UV_PROJECTION_AXIS_OPTIONS.map((option) => {
|
||||
const isSelected = form.textureProjectionAxis === option.value
|
||||
return (
|
||||
<button
|
||||
key={option.value || 'auto'}
|
||||
type="button"
|
||||
aria-label={option.label}
|
||||
aria-pressed={isSelected}
|
||||
onClick={() => onSelectProjectionAxis(option.value)}
|
||||
className={cn(
|
||||
'h-5 rounded-[3px] text-[11px] font-apple-system font-apple-medium transition',
|
||||
isSelected
|
||||
? 'bg-[#2d3335] text-white shadow-xs'
|
||||
: 'text-[#5a6062] hover:bg-black/[0.04] hover:text-[#2d3335]',
|
||||
)}
|
||||
>
|
||||
{option.label === '自动' ? '自' : option.label.replace(' 轴', '')}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{[
|
||||
{ label: '整体重复', ariaLabel: '整体重复', value: form.textureRepeat, placeholder: '1.0', field: 'textureRepeat' as const },
|
||||
{ label: '旋转角度 °', ariaLabel: '旋转角度 °', value: form.textureRotation, placeholder: '0°', field: 'textureRotation' as const },
|
||||
{ label: '纹理尺寸 mm', ariaLabel: '纹理尺寸 mm', value: form.textureSizeMm, placeholder: '600', field: 'textureSizeMm' as const },
|
||||
{ label: 'U 压缩', ariaLabel: 'U 压缩', value: form.textureRepeatU, placeholder: '1.0', field: 'textureRepeatU' as const },
|
||||
{ label: 'V 压缩', ariaLabel: 'V 压缩', value: form.textureRepeatV, placeholder: '1.0', field: 'textureRepeatV' as const },
|
||||
].map((item) => (
|
||||
<div
|
||||
key={item.field}
|
||||
className="mb-0.5 flex h-6 w-full items-center justify-between gap-2 rounded-apple-md border border-transparent px-2 text-left text-apple-label-primary"
|
||||
>
|
||||
<label
|
||||
htmlFor={`variant-uv-${item.field}`}
|
||||
className="shrink-0 text-[12px] font-apple-system font-apple-medium"
|
||||
>
|
||||
{item.label}
|
||||
</label>
|
||||
<input
|
||||
id={`variant-uv-${item.field}`}
|
||||
aria-label={item.ariaLabel}
|
||||
inputMode="decimal"
|
||||
value={item.value}
|
||||
onChange={(event) => onFormPatch({ [item.field]: event.target.value })}
|
||||
placeholder={item.placeholder}
|
||||
className="h-6 w-[108px] rounded-apple-sm border border-apple-separator bg-white/80 px-2 text-right text-[12px] text-apple-label-primary outline-hidden transition placeholder:text-apple-label-tertiary focus:border-[#2d3335]"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="mx-1 my-0.5 h-px bg-apple-separator/80" />
|
||||
|
||||
<div className="mb-0.5 grid grid-cols-2 gap-1">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onReset}
|
||||
disabled={submitting || !configDirty}
|
||||
className="flex h-6 items-center rounded-apple-md border border-transparent px-2 text-left text-[12px] font-apple-system font-apple-medium text-apple-label-primary transition hover:border-apple-separator/80 hover:bg-white/85 disabled:cursor-not-allowed disabled:bg-apple-bg-secondary/25 disabled:text-apple-label-tertiary"
|
||||
>
|
||||
还原
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClear}
|
||||
disabled={submitting}
|
||||
className="flex h-6 items-center rounded-apple-md border border-transparent px-2 text-left text-[12px] font-apple-system font-apple-medium text-apple-label-primary transition hover:border-apple-separator/80 hover:bg-white/85 disabled:cursor-not-allowed disabled:bg-apple-bg-secondary/25 disabled:text-apple-label-tertiary"
|
||||
>
|
||||
清空
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
disabled={submitting || !configDirty}
|
||||
onClick={onKeepDraft}
|
||||
className="mb-0.5 flex h-6 w-full items-center rounded-apple-md border border-transparent px-2 text-left text-[12px] font-apple-system font-apple-medium text-apple-label-primary transition hover:border-apple-separator/80 hover:bg-white/85 disabled:cursor-not-allowed disabled:bg-apple-bg-secondary/25 disabled:text-apple-label-tertiary"
|
||||
>
|
||||
暂存渲染参数
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user