From 69672604dbe297190be75b6700d214305650cde5 Mon Sep 17 00:00:00 2001 From: eternallycyf <969475322@qq.com> Date: Sat, 27 Apr 2024 12:05:21 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(ims-view-pc):=20add=20Portal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Portal/Portal.tsx | 40 +++++++++++++++++++ .../src/components/Portal/demo/index.tsx | 24 +++++++++++ .../src/components/Portal/index.less | 2 + .../src/components/Portal/index.md | 40 +++++++++++++++++++ .../src/components/Portal/index.tsx | 2 + .../src/components/Portal/interface.ts | 4 ++ packages/ims-view-pc/src/index.tsx | 2 + 7 files changed, 114 insertions(+) create mode 100644 packages/ims-view-pc/src/components/Portal/Portal.tsx create mode 100644 packages/ims-view-pc/src/components/Portal/demo/index.tsx create mode 100644 packages/ims-view-pc/src/components/Portal/index.less create mode 100644 packages/ims-view-pc/src/components/Portal/index.md create mode 100644 packages/ims-view-pc/src/components/Portal/index.tsx create mode 100644 packages/ims-view-pc/src/components/Portal/interface.ts diff --git a/packages/ims-view-pc/src/components/Portal/Portal.tsx b/packages/ims-view-pc/src/components/Portal/Portal.tsx new file mode 100644 index 0000000..7ac5684 --- /dev/null +++ b/packages/ims-view-pc/src/components/Portal/Portal.tsx @@ -0,0 +1,40 @@ +import React, { forwardRef, useEffect, useImperativeHandle, useMemo } from 'react'; +import { createPortal } from 'react-dom'; +import './index.less'; +import type { PortalProps } from './interface'; + +const Portal = forwardRef((props: PortalProps, ref) => { + const { attach = document.body, children } = props; + + const container = useMemo(() => { + const el = document.createElement('div'); + el.className = `portal-wrapper`; + return el; + }, []); + + useEffect(() => { + const parentElement = getAttach(attach); + parentElement?.appendChild?.(container); + + return () => { + parentElement?.removeChild?.(container); + }; + }, [container, attach]); + + useImperativeHandle(ref, () => container); + + return createPortal(children, container); +}); + +export default Portal; + +export function getAttach(attach: PortalProps['attach']) { + if (typeof attach === 'string') { + return document.querySelector(attach); + } + if (typeof attach === 'object' && attach instanceof window.HTMLElement) { + return attach; + } + + return document.body; +} diff --git a/packages/ims-view-pc/src/components/Portal/demo/index.tsx b/packages/ims-view-pc/src/components/Portal/demo/index.tsx new file mode 100644 index 0000000..a5dd2c7 --- /dev/null +++ b/packages/ims-view-pc/src/components/Portal/demo/index.tsx @@ -0,0 +1,24 @@ +import { Portal } from 'ims-view-pc'; +import React, { useEffect, useRef } from 'react'; + +export default () => { + const containerRef = useRef(null); + + const content = ( +
+ +
+ ); + + useEffect(() => { + console.log(containerRef); + }, []); + + return ( +
+ + {content} + +
+ ); +}; diff --git a/packages/ims-view-pc/src/components/Portal/index.less b/packages/ims-view-pc/src/components/Portal/index.less new file mode 100644 index 0000000..414b7cb --- /dev/null +++ b/packages/ims-view-pc/src/components/Portal/index.less @@ -0,0 +1,2 @@ +.portal-wrapper { +} diff --git a/packages/ims-view-pc/src/components/Portal/index.md b/packages/ims-view-pc/src/components/Portal/index.md new file mode 100644 index 0000000..6909256 --- /dev/null +++ b/packages/ims-view-pc/src/components/Portal/index.md @@ -0,0 +1,40 @@ +--- +title: Portal +description: Portal +toc: content +group: + title: 其他 +--- + +# Portal + +## 介绍 + +`Portal` 组件可以将内容渲染到指定的节点上,通常用于弹出层、全局提示等场景。 + +## 引入 + +```js +import { Portal } from 'ims-view-pc'; +``` + +## 代码演示 + + + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +| -------- | ------------------------------ | ----------------------- | ------ | +| attach | 挂载的节点,可以是节点或选择器 | _HTMLElement \| string_ | - | +| children | 需要挂载的内容 | _ReactNode_ | - | + +### 类型定义 + +组件导出以下类型定义: + +```ts +import type { PortalProps } from 'ims-view-pc'; +``` diff --git a/packages/ims-view-pc/src/components/Portal/index.tsx b/packages/ims-view-pc/src/components/Portal/index.tsx new file mode 100644 index 0000000..88a8e9e --- /dev/null +++ b/packages/ims-view-pc/src/components/Portal/index.tsx @@ -0,0 +1,2 @@ +import Portal from './Portal'; +export default Portal; diff --git a/packages/ims-view-pc/src/components/Portal/interface.ts b/packages/ims-view-pc/src/components/Portal/interface.ts new file mode 100644 index 0000000..2e3ba20 --- /dev/null +++ b/packages/ims-view-pc/src/components/Portal/interface.ts @@ -0,0 +1,4 @@ +export interface PortalProps { + attach?: HTMLElement | string; + children: React.ReactNode; +} diff --git a/packages/ims-view-pc/src/index.tsx b/packages/ims-view-pc/src/index.tsx index 2189abe..cd9898d 100644 --- a/packages/ims-view-pc/src/index.tsx +++ b/packages/ims-view-pc/src/index.tsx @@ -31,6 +31,8 @@ export * from './components/ExportButton/interface'; export { default as Icon } from './components/Icon'; export { default as Marker } from './components/Marker'; export * from './components/Marker/interface'; +export { default as Portal } from './components/Portal'; +export * from './components/Portal/interface'; export { default as SectionTitle } from './components/SectionTitle'; export * from './components/SectionTitle/interface'; export { default as Sticky } from './components/Sticky';