From 56782b83fcc1e96b66e31d463ba95f45acf0f5a2 Mon Sep 17 00:00:00 2001 From: cfngc4594 Date: Sun, 13 Apr 2025 11:35:29 +0800 Subject: [PATCH] refactor(components): migrate DockView to dynamic panel/tab components with store-based API exposure and autoAdd flag --- src/components/dockview.tsx | 90 +++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/src/components/dockview.tsx b/src/components/dockview.tsx index 72dfa30..2c63cd1 100644 --- a/src/components/dockview.tsx +++ b/src/components/dockview.tsx @@ -8,51 +8,64 @@ import type { IDockviewPanelProps, } from "dockview"; import "@/styles/dockview.css"; -import * as Icons from "lucide-react"; -import { useEffect, useState } from "react"; import type { LucideIcon } from "lucide-react"; +import { useDockviewStore } from "@/stores/dockview"; +import { useEffect, useMemo, useState } from "react"; import { DockviewReact, themeAbyssSpaced } from "dockview"; +interface PanelContent { + icon?: LucideIcon; + content?: React.ReactNode; + autoAdd?: boolean; +} + interface DockviewProps { storageKey: string; - options: AddPanelOptions[]; - components: Record>; - tabComponents?: Record>; - onApiReady?: (api: DockviewApi) => void; + options: AddPanelOptions[]; } -const DefaultTab = ( - props: IDockviewPanelHeaderProps<{ icon?: string }> -) => { - const { icon } = props.params; - const Icon = - icon && icon in Icons - ? (Icons[icon as keyof typeof Icons] as LucideIcon) - : null; - - return ( -
- {Icon && ( -
- ); -}; - -export default function DockView({ - storageKey, - options, - components, - tabComponents, - onApiReady, -}: DockviewProps) { +export default function DockView({ storageKey, options }: DockviewProps) { + const { setApi: _setApi } = useDockviewStore(); const [api, setApi] = useState(); + const { components, tabComponents } = useMemo(() => { + const components: Record< + string, + React.FunctionComponent> + > = {}; + const tabComponents: Record< + string, + React.FunctionComponent> + > = {}; + + options.forEach((option) => { + const { id, params } = option; + + components[id] = () => { + const content = params?.content; + return <>{content}; + }; + + tabComponents[id] = (props) => { + const Icon = params?.icon; + return ( +
+ {Icon && ( +
+ ); + }; + }); + + return { components, tabComponents }; + }, [options]); + useEffect(() => { if (!api) return; @@ -66,7 +79,7 @@ export default function DockView({ const onReady = (event: DockviewReadyEvent) => { setApi(event.api); - onApiReady?.(event.api); + _setApi(event.api); let success = false; const serializedLayout = localStorage.getItem(storageKey); @@ -84,6 +97,8 @@ export default function DockView({ if (!success) { options.forEach((option) => { + const autoAdd = option.params?.autoAdd ?? true; + if (!autoAdd) return; event.api.addPanel({ ...option }); }); } @@ -94,7 +109,6 @@ export default function DockView({ theme={themeAbyssSpaced} onReady={onReady} components={components} - defaultTabComponent={DefaultTab} tabComponents={tabComponents} /> );