diff --git a/package.json b/package.json index be7ced7..85e3f7a 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "@ant-design/graphs": "^2.0.2", "@ant-design/icons": "^5.5.2", "@ant-design/plots": "^2.3.2", + "@antv/event-emitter": "^0.1.3", "@antv/l7": "^2.22.3", "@antv/larkmap": "^1.5.1", "@babel/runtime": "^7.26.0", diff --git a/src/GPTVis/Lite.tsx b/src/GPTVis/Lite.tsx index e44ed85..87c2309 100644 --- a/src/GPTVis/Lite.tsx +++ b/src/GPTVis/Lite.tsx @@ -1,9 +1,11 @@ -import React, { memo } from 'react'; +import EventEmitter from '@antv/event-emitter'; +import React, { memo, useEffect, useMemo } from 'react'; import type { Options } from 'react-markdown'; import Markdown from 'react-markdown'; import rehypeRaw from 'rehype-raw'; import remarkGfm from 'remark-gfm'; -import { GPTVisContext, useGPTVisContext } from './useContext'; +import { GPTVisContext } from './hooks/useContext'; +import { useEventPublish } from './hooks/useEvent'; export interface GPTVisLiteProps extends Options { /** @@ -15,34 +17,51 @@ export interface GPTVisLiteProps extends Options { [key: string]: (props: any) => React.ReactNode; }; /** - * 🧪 组件上下文数据,实验性属性 + * 🧪 订阅组件事件,实验性属性 * 用于子组件与容器组件通信 */ - context?: Record; + eventSubscribe?: Record void>; } const GPTVisLite: React.FC = ({ - context, children, components, rehypePlugins, remarkPlugins, + eventSubscribe: onEvent, ...rest }) => { - const renderer = ( - - {children} - - ); + const eventBus = useMemo(() => new EventEmitter(), []); + const contextValue = useMemo(() => ({ eventBus }), [eventBus]); + + useEffect(() => { + if (onEvent) { + const events = Object.keys(onEvent); + for (const eventName of events) { + eventBus.on(eventName, onEvent[eventName]); + } + return () => { + for (const eventName of events) { + eventBus.off(eventName, onEvent[eventName]); + } + }; + } + }, [eventBus, onEvent]); - return context ? : renderer; + return ( + + + {children} + + + ); }; -export { GPTVisContext, useGPTVisContext }; +export { useEventPublish }; export default memo(GPTVisLite); diff --git a/src/GPTVis/demos/context-provider.tsx b/src/GPTVis/demos/context-provider.tsx index c811be1..b4e5738 100644 --- a/src/GPTVis/demos/context-provider.tsx +++ b/src/GPTVis/demos/context-provider.tsx @@ -1,12 +1,23 @@ import type { CodeBlockComponent } from '@antv/gpt-vis'; -import { GPTVisContext, GPTVisLite, useGPTVisContext, withChartCode } from '@antv/gpt-vis'; +import { GPTVisLite, withChartCode } from '@antv/gpt-vis'; import React, { useCallback, useMemo, useState } from 'react'; +export const MyContext = React.createContext(null as any); + +export function useMyContext() { + const context = React.useContext(MyContext); + if (context === undefined || Object.keys(context).length === 0) { + throw new Error(`useMyContext must be used within a MyContext.Provider`); + } + + return context; +} + /** * 自定义代码块渲染器 */ const MyUIRenderer: CodeBlockComponent = ({ children }) => { - const context = useGPTVisContext(); + const context = useMyContext(); console.log('context: ', context); return (
@@ -29,6 +40,7 @@ const content = ` my ui data ... \`\`\` `; + export default () => { const [count, setCount] = useState(0); const handleClick = useCallback(() => { @@ -41,7 +53,7 @@ export default () => { return ( <>

count: {count}

- +
{/* other component ... */}
@@ -49,7 +61,7 @@ export default () => { {content}
-
+ ); }; diff --git a/src/GPTVis/demos/context.tsx b/src/GPTVis/demos/event.tsx similarity index 50% rename from src/GPTVis/demos/context.tsx rename to src/GPTVis/demos/event.tsx index 20385cd..fed75f3 100644 --- a/src/GPTVis/demos/context.tsx +++ b/src/GPTVis/demos/event.tsx @@ -1,17 +1,22 @@ import type { CodeBlockComponent } from '@antv/gpt-vis'; -import { GPTVisLite, useGPTVisContext, withChartCode } from '@antv/gpt-vis'; -import React, { useCallback, useMemo, useState } from 'react'; +import { GPTVisLite, useEventPublish, withChartCode } from '@antv/gpt-vis'; +import React from 'react'; /** * 自定义代码块渲染器 */ const MyUIRenderer: CodeBlockComponent = ({ children }) => { - const context = useGPTVisContext(); - console.log('context: ', context); + const dispatch = useEventPublish(); + console.log('dispatch: ', dispatch); return (

{children}

-
@@ -30,20 +35,15 @@ my ui data ... \`\`\` `; export default () => { - const [count, setCount] = useState(0); - const handleClick = useCallback(() => { + const onClick = (data: any) => { + console.log('data: ', data); console.log('handleClick'); - setCount((pre) => pre + 1); // do something - }, []); - const context = useMemo(() => ({ count: count, onClick: handleClick }), [count]); + }; return ( - <> -

count: {count}

- - {content} - - + + {content} + ); }; diff --git a/src/GPTVis/useContext.ts b/src/GPTVis/hooks/useContext.ts similarity index 65% rename from src/GPTVis/useContext.ts rename to src/GPTVis/hooks/useContext.ts index a1c1165..1f15281 100644 --- a/src/GPTVis/useContext.ts +++ b/src/GPTVis/hooks/useContext.ts @@ -1,12 +1,15 @@ +import type EventEmitter from '@antv/event-emitter'; import React from 'react'; -type GPTVisContextValue = Record; +type GPTVisContextValue = { + eventBus: EventEmitter; +}; export const GPTVisContext = React.createContext(null as any); export function useGPTVisContext() { const context = React.useContext(GPTVisContext); - if (context === null) { + if (context === undefined || Object.keys(context).length === 0) { throw new Error(`useGPTVisContext must be used within a GPTVisContext.Provider`); } diff --git a/src/GPTVis/hooks/useEvent.ts b/src/GPTVis/hooks/useEvent.ts new file mode 100644 index 0000000..0bd956c --- /dev/null +++ b/src/GPTVis/hooks/useEvent.ts @@ -0,0 +1,7 @@ +import { useGPTVisContext } from './useContext'; + +export const useEventPublish = () => { + const { eventBus } = useGPTVisContext(); + + return eventBus.emit.bind(eventBus); +}; diff --git a/src/GPTVis/index.md b/src/GPTVis/index.md index 20bd327..1da7715 100644 --- a/src/GPTVis/index.md +++ b/src/GPTVis/index.md @@ -26,12 +26,12 @@ GPTVis 协议的 Markdown 渲染器,基于 Markdown 语法扩展 `vis-chart` - + + ## API diff --git a/src/index.ts b/src/index.ts index 3790fb4..36366a4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,11 +9,6 @@ export { withChartCode, withDefaultChartCode } from './ChartCodeRender'; export type { CodeBlockComponent, WithChartCodeOptions } from './ChartCodeRender/type'; export { default as ConfigProvider, type ConfigProviderProps } from './ConfigProvider'; export { default as GPTVis, type GPTVisProps } from './GPTVis'; -export { - GPTVisContext, - default as GPTVisLite, - useGPTVisContext, - type GPTVisLiteProps, -} from './GPTVis/Lite'; +export { default as GPTVisLite, useEventPublish, type GPTVisLiteProps } from './GPTVis/Lite'; export { default as version } from './version';