返回 oh-my-ppt
ElementInspectorPanel.tsx
根目录 / src / renderer / src / components / session-detail / element-inspector / ElementInspectorPanel.tsx
1 import { X } from 'lucide-react'
2 import type { EditSelectionPayload } from '@arcsin1/presentation-editor-runtime'
3 import { AppearanceInspector } from './AppearanceInspector'
4 import { ArtTextInspector } from './ArtTextInspector'
5 import { ChartInspector } from './ChartInspector'
6 import { FormulaInspector } from './FormulaInspector'
7 import { LayerInspector } from './LayerInspector'
8 import { LayoutInspector } from './LayoutInspector'
9 import { MediaInspector } from './MediaInspector'
10 import { TextInspector } from './TextInspector'
11 import type { ElementEditDraft } from './types'
12 import { getElementKindLabel, hasCapability, isArtTextSelection } from './types'
13 import { useT } from '@renderer/i18n'
14 import { sessionDetailRightPanelContentClass } from '../workspace/right-panel/styles'
15
16 export type { ElementEditDraft } from './types'
17
18 export function ElementInspectorPanel({
19 selection,
20 draft,
21 onDraftChange,
22 onClose
23 }: {
24 selection: EditSelectionPayload | null
25 draft: ElementEditDraft
26 onDraftChange: (
27 draft: ElementEditDraft,
28 options?: { commit?: boolean; fields?: Array<keyof ElementEditDraft> }
29 ) => void
30 onClose: () => void
31 }): React.JSX.Element {
32 const t = useT()
33 const snapshot = selection?.snapshot
34 const isArtText = isArtTextSelection(selection)
35
36 return (
37 <div className={sessionDetailRightPanelContentClass}>
38 <div className="relative mx-2 mt-2 overflow-hidden rounded-[0.85rem] border border-[#e1d6c4]/58 bg-[#fffaf1]/68 px-2.5 py-2 shadow-[0_2px_8px_rgba(77,61,43,0.05)]">
39 <div className="pointer-events-none absolute -right-8 -top-10 h-20 w-20 rounded-[30%_70%_70%_30%/30%_30%_70%_70%] bg-[#c7d9b4]/10" />
40 <div className="relative flex items-center justify-between">
41 <div>
42 <div className="text-[10px] font-semibold uppercase tracking-[0.1em] text-[#7a875f]/90">
43 {t('sessionDetail.elementInspector')}
44 </div>
45 {selection && (
46 <div className="mt-0.5 text-[10px] text-[#a0977e]">
47 {isArtText ? t('editMode.artText') : getElementKindLabel(selection)}
48 </div>
49 )}
50 </div>
51 <button
52 type="button"
53 onClick={onClose}
54 className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-[#667257] transition-colors hover:bg-[#d4e4c1]/70 hover:text-[#34402c]"
55 aria-label={t('sessionDetail.closeInspector')}
56 title={t('sessionDetail.closeInspector')}
57 >
58 <X className="h-3.5 w-3.5" />
59 </button>
60 </div>
61 </div>
62
63 <div className="flex-1 space-y-2.5 overflow-y-auto px-2 py-2">
64 {!selection || !snapshot ? (
65 <div className="rounded-[0.8rem] border border-[#e8c8c6]/62 bg-[#fdf0ef]/76 px-3 py-3 text-center shadow-[0_4px_10px_rgba(74,59,42,0.06)]">
66 <p className="whitespace-pre-line text-[11px] leading-5 text-[#8e5a53]">
67 {t('sessionDetail.inspectorUnavailable')}
68 </p>
69 </div>
70 ) : (
71 <>
72 <LayoutInspector selection={selection} draft={draft} onDraftChange={onDraftChange} />
73 {hasCapability(selection, 'layer') && (
74 <LayerInspector selection={selection} draft={draft} onDraftChange={onDraftChange} />
75 )}
76 {isArtText && (
77 <ArtTextInspector selection={selection} draft={draft} onDraftChange={onDraftChange} />
78 )}
79 {!isArtText && hasCapability(selection, 'text') && (
80 <TextInspector selection={selection} draft={draft} onDraftChange={onDraftChange} />
81 )}
82 {hasCapability(selection, 'formula') && (
83 <FormulaInspector selection={selection} draft={draft} onDraftChange={onDraftChange} />
84 )}
85 {hasCapability(selection, 'chart') && (
86 <ChartInspector selection={selection} draft={draft} onDraftChange={onDraftChange} />
87 )}
88 {hasCapability(selection, 'appearance') && (
89 <AppearanceInspector
90 selection={selection}
91 draft={draft}
92 onDraftChange={onDraftChange}
93 />
94 )}
95 {hasCapability(selection, 'media') && (
96 <MediaInspector selection={selection} draft={draft} onDraftChange={onDraftChange} />
97 )}
98 </>
99 )}
100
101 </div>
102 </div>
103 )
104 }
105
105 lines Plain Text