diff --git a/script/generate-entry.js b/script/generate-entry.js index e691cff..4e322d8 100644 --- a/script/generate-entry.js +++ b/script/generate-entry.js @@ -10,7 +10,7 @@ const componentsPath = path.resolve(__dirname, '../src'); const components = fs.readdirSync(componentsPath).filter((name) => { if (['style', 'icon'].includes(name) || name.startsWith('_')) return false; const componentPath = path.resolve(componentsPath, name); - if (fs.statSync(componentPath).isDirectory()) { + if (fs.statSync(componentPath).isDirectory() || /src\/react\.ts|src\/vue\.ts/.test(componentPath)) { return true; } return false; diff --git a/site/docs/getting-started.md b/site/docs/getting-started.md index 50379d8..afddfbd 100644 --- a/site/docs/getting-started.md +++ b/site/docs/getting-started.md @@ -63,6 +63,32 @@ export default defineConfig({ } ``` +### 在React中使用 + +首先引入`renderReact` + +```javascript +import { renderReact } from 'tdesign-web-components'; +``` + +在React项目中使用 + +```javascript +const App: React.FC = () => { + const ref = React.useRef(null); + React.useEffect(() => { + if (ref.current) { + renderReact(BUTTON, ref.current) + } + }, []) + + + return ( +
+ ) +} +``` + ### 更改主题 由于原始样式基于 less 编写,需要自行处理 less 文件的编译(例如安装 less、less-loader) diff --git a/src/index.ts b/src/index.ts index 76811ea..d34d99a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,6 +28,7 @@ export * from './popup'; export * from './progress'; export * from './radio'; export * from './range-input'; +export * from './react.ts'; export * from './select'; export * from './select-input'; export * from './skeleton'; diff --git a/src/menu/MenuItem.tsx b/src/menu/MenuItem.tsx index c3ef307..893b36f 100644 --- a/src/menu/MenuItem.tsx +++ b/src/menu/MenuItem.tsx @@ -1,4 +1,4 @@ -import 'tdesign-web-components/tooltip'; +import '../tooltip'; import { bind, Component, tag } from 'omi'; diff --git a/src/message/const.tsx b/src/message/const.tsx index 174bee9..f5afd98 100644 --- a/src/message/const.tsx +++ b/src/message/const.tsx @@ -1,5 +1,4 @@ -import { getClassPrefix } from 'tdesign-web-components/_util/classname'; - +import { getClassPrefix } from '../_util/classname'; import { MessagePlacementList, MessageThemeList } from './type'; const Distance = '32px'; diff --git a/src/message/message.tsx b/src/message/message.tsx index 45b2c17..cc76f6d 100644 --- a/src/message/message.tsx +++ b/src/message/message.tsx @@ -1,7 +1,7 @@ import { Component, render, tag } from 'omi'; -import { convertToLightDomNode } from 'tdesign-web-components/_util/lightDom'; import classname from '../_util/classname'; +import { convertToLightDomNode } from '../_util/lightDom'; import { AttachNodeReturnValue, Styles, TNode } from '../common'; import { getMessageConfig, globalConfig, setGlobalConfig } from './config'; import { PlacementOffset, tdMessageListClass, tdMessagePlacementClassGenerator } from './const'; diff --git a/src/message/messageClose.tsx b/src/message/messageClose.tsx index 23176e1..c9cc395 100644 --- a/src/message/messageClose.tsx +++ b/src/message/messageClose.tsx @@ -5,9 +5,9 @@ import 'tdesign-icons-web-components/esm/components/close'; import Omi, { classNames, Component, tag } from 'omi'; -import { StyledProps } from 'tdesign-web-components'; -import { parseContentTNode } from 'tdesign-web-components/_util/parseTNode'; +import { parseContentTNode } from '../_util/parseTNode'; +import { StyledProps } from '../common'; import { tdMessageClassGenerator } from './const'; import { TdMessageProps } from './type'; diff --git a/src/message/messageComponent.tsx b/src/message/messageComponent.tsx index 5b54d48..810a43d 100644 --- a/src/message/messageComponent.tsx +++ b/src/message/messageComponent.tsx @@ -2,10 +2,10 @@ import './messageClose'; import classNames from 'classnames'; import Omi, { Component, createRef, signal, tag } from 'omi'; -import MessageIcon from 'tdesign-web-components/message/messageIcon'; import { StyledProps, TNode } from '../common'; import { tdClassIsGenerator, tdMessageClassGenerator, tdMessagePrefix } from './const'; +import MessageIcon from './messageIcon'; // 依赖组件引入 import { TdMessageProps } from './type'; diff --git a/src/message/messageIcon.tsx b/src/message/messageIcon.tsx index e40ec42..c993626 100644 --- a/src/message/messageIcon.tsx +++ b/src/message/messageIcon.tsx @@ -2,7 +2,7 @@ import 'tdesign-icons-web-components/esm/components/check-circle-filled'; import 'tdesign-icons-web-components/esm/components/info-circle-filled'; import 'tdesign-icons-web-components/esm/components/error-circle-filled'; import 'tdesign-icons-web-components/esm/components/help-circle-filled'; -import 'tdesign-web-components/loading'; +import '../loading'; import { classPrefix } from './const'; import { TdMessageProps } from './type'; diff --git a/src/range-input/RangeInput.tsx b/src/range-input/RangeInput.tsx index 53927fb..6fd3ddd 100644 --- a/src/range-input/RangeInput.tsx +++ b/src/range-input/RangeInput.tsx @@ -1,5 +1,5 @@ import 'tdesign-icons-web-components'; -import 'tdesign-web-components/input'; +import '../input'; import './RangeInputInner'; import { bind, classNames, Component, signal, tag } from 'omi'; diff --git a/src/range-input/RangeInputInner.tsx b/src/range-input/RangeInputInner.tsx index 093cc0c..7c93edb 100644 --- a/src/range-input/RangeInputInner.tsx +++ b/src/range-input/RangeInputInner.tsx @@ -1,6 +1,7 @@ import { tag } from 'omi'; -import { getClassPrefix } from 'tdesign-web-components/_util/classname'; -import { Input } from 'tdesign-web-components/input'; + +import { getClassPrefix } from '../_util/classname'; +import { Input } from '../input'; @tag('t-range-input-inner') export default class RangeInput extends Input { diff --git a/src/range-input/type.ts b/src/range-input/type.ts index 9a55cb1..6909e1a 100644 --- a/src/range-input/type.ts +++ b/src/range-input/type.ts @@ -1,6 +1,5 @@ -import { InputFormatType, InputValue } from 'tdesign-web-components/input'; - import { TNode } from '../common'; +import { InputFormatType, InputValue } from '../input'; export interface TdRangeInputProps { /** diff --git a/src/react.ts b/src/react.ts new file mode 100644 index 0000000..bb2ddc2 --- /dev/null +++ b/src/react.ts @@ -0,0 +1,56 @@ +/** + * 在React环境中使用的兼容方法 + */ + +import { render } from 'omi'; + +const convertReactToOmi = (r: any): Omi.ComponentChild => { + if (!r) return r; + if (typeof r === 'string') return r; + const { + type, + key, + ref, + props: { children, ...rest }, + } = r; + const omiVNode = { + nodeName: type, + attributes: { ignoreAttrs: true, ref, ...rest }, + key, + children: [], + }; + + if (!children) { + return omiVNode; + } + + if (Array.isArray(children)) { + return { + ...omiVNode, + children: children.map((c: any) => convertReactToOmi(c)), + }; + } + + if (typeof children === 'object') { + return { + ...omiVNode, + children: [children].map((c: any) => convertReactToOmi(c)), + }; + } + + return { + ...omiVNode, + children, + }; +}; + +/** + * 在react环境中渲染组件 + * @param reactVNode react的vnode结构 + * @param root 需要挂载的html + */ +const renderReact = (reactVNode: T, root: HTMLElement) => { + render(convertReactToOmi(reactVNode), root); +}; + +export { renderReact, convertReactToOmi };