Files
mai-bot/dashboard/src/components/component-css-editor.tsx
DrSmoothl 0811213db0 feat: enhance background layer handling and uploader functionality
- Introduced automatic overlay opacity and gradient based on layer ID in BackgroundLayer component.
- Added disabled state to BackgroundUploader, preventing actions when disabled.
- Updated component CSS editor to handle disabled state, preventing changes when disabled.
- Modified Header and Layout components to manage background inheritance from the page layer.
- Improved Sidebar and Card components to respect background inheritance and layering.
- Refactored theme management to include default accent color and normalization functions.
- Enhanced AppearanceTab to manage accent color changes with debouncing and validation.
- Added UI feedback for inherited background layers in AppearanceTab.
2026-03-16 22:19:05 +08:00

84 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { AlertTriangle, Trash2 } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { CodeEditor } from '@/components/CodeEditor'
import { Label } from '@/components/ui/label'
import { sanitizeCSS } from '@/lib/theme/sanitizer'
export type ComponentCSSEditorProps = {
/** 组件唯一标识符 */
componentId: string
/** 当前 CSS 内容 */
value: string
/** CSS 内容变更回调 */
onChange: (css: string) => void
/** 编辑器标签文字 */
label?: string
/** 编辑器高度,默认 200px */
height?: string
disabled?: boolean
}
/**
* 组件级 CSS 编辑器
* 提供 CSS 代码编辑、语法高亮和安全过滤警告功能
*/
export function ComponentCSSEditor({
componentId,
value,
onChange,
label,
height = '200px',
disabled = false,
}: ComponentCSSEditorProps) {
// 实时计算 CSS 警告
const { warnings } = sanitizeCSS(value)
return (
<div className={disabled ? 'space-y-2 opacity-50' : 'space-y-2'}>
<div className="flex items-center justify-between">
<Label className="text-sm font-medium">
{label || '自定义 CSS'}
</Label>
<Button
variant="ghost"
size="sm"
onClick={() => onChange('')}
disabled={disabled || !value}
className="h-7 px-2 text-xs text-muted-foreground hover:text-destructive"
title="清除所有 CSS"
>
<Trash2 className="mr-1.5 h-3.5 w-3.5" />
</Button>
</div>
<div className="rounded-md border bg-card overflow-hidden">
<CodeEditor
value={value}
onChange={disabled ? undefined : onChange}
language="css"
readOnly={disabled}
height={height}
placeholder={`/* 为 ${componentId} 组件编写自定义 CSS */\n\n/* 示例: */\n/* .custom-class { background: red; } */`}
/>
{warnings.length > 0 && (
<div className="border-t border-yellow-200 dark:border-yellow-800 bg-yellow-50 dark:bg-yellow-950/30 p-3">
<div className="flex items-center gap-2 text-yellow-800 dark:text-yellow-200 text-xs font-medium mb-1">
<AlertTriangle className="h-3.5 w-3.5" />
CSS
</div>
<ul className="text-[10px] sm:text-xs text-yellow-700 dark:text-yellow-300 space-y-0.5 ml-5 list-disc">
{warnings.map((w, i) => (
<li key={i}>{w}</li>
))}
</ul>
</div>
)}
</div>
</div>
)
}