Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(portal-context): Provider 增加 portal 参数,支持配置全局 container (#3060) #3061

Merged
merged 6 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/little-rabbits-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"@hi-ui/core": minor
"@hi-ui/container-context": minor
"@hi-ui/drawer": minor
"@hi-ui/hiui": minor
"@hi-ui/loading": minor
"@hi-ui/modal": minor
"@hi-ui/preview": minor
"@hi-ui/provider": minor
---

feat(portal-context): Provider 增加 portal 参数,支持配置全局 container (#3060)
3 changes: 2 additions & 1 deletion packages/core/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"devDependencies": {},
"dependencies": {
"@hi-ui/core-css": "^4.1.5",
"@hi-ui/locale-context": "^4.0.8"
"@hi-ui/locale-context": "^4.0.8",
"@hi-ui/portal-context": "^4.0.0"
}
}
3 changes: 3 additions & 0 deletions packages/core/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,6 @@ export type HiBaseSizeEnum = ValueOf<typeof HiBaseSizeEnum>
// 将 core 设为 peer:保证 context 实例引用一致性
export { useLocaleContext, LocaleProvider } from '@hi-ui/locale-context'
export type { UseLocaleContext, LocaleProviderProps } from '@hi-ui/locale-context'

export { usePortalContext, PortalProvider } from '@hi-ui/portal-context'
export type { UsePortalContext, PortalProviderProps } from '@hi-ui/portal-context'
6 changes: 4 additions & 2 deletions packages/ui/drawer/src/Drawer.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { forwardRef, useCallback, useEffect } from 'react'
import { cx, getPrefixCls, getPrefixStyleVar } from '@hi-ui/classname'
import { __DEV__ } from '@hi-ui/env'
import { HiBaseHTMLProps } from '@hi-ui/core'
import { HiBaseHTMLProps, usePortalContext } from '@hi-ui/core'
import { CSSTransition } from 'react-transition-group'
import { Portal } from '@hi-ui/portal'
import { useModal, UseModalProps } from '@hi-ui/modal'
Expand Down Expand Up @@ -33,7 +33,7 @@ export const Drawer = forwardRef<HTMLDivElement | null, DrawerProps>(
onExited: onExitedProp,
title,
footer,
container,
container: containerProp,
closeIcon = defaultCloseIcon,
width,
height,
Expand All @@ -51,6 +51,8 @@ export const Drawer = forwardRef<HTMLDivElement | null, DrawerProps>(
) => {
const [transitionVisible, transitionVisibleAction] = useToggle(false)
const [transitionExited, transitionExitedAction] = useToggle(true)
const globalContainer = usePortalContext()?.container
const container = containerProp ?? globalContainer

const { rootProps, getModalProps, getModalWrapperProps } = useModal({
...rest,
Expand Down
7 changes: 5 additions & 2 deletions packages/ui/loading/src/Loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { CSSTransition } from 'react-transition-group'
import { cx, getPrefixCls } from '@hi-ui/classname'
import { __DEV__ } from '@hi-ui/env'
import { Portal } from '@hi-ui/portal'
import { HiBaseHTMLProps, HiBaseSizeEnum } from '@hi-ui/core'
import { HiBaseHTMLProps, HiBaseSizeEnum, usePortalContext } from '@hi-ui/core'
import { useLatestCallback } from '@hi-ui/use-latest'
import Spinner from '@hi-ui/spinner'
import { useLoading } from './use-loading'
Expand All @@ -18,7 +18,7 @@ export const Loading = forwardRef<null, LoadingProps>(
className,
children,
role = _role,
container,
container: containerProp,
content,
visible = true,
full = false,
Expand All @@ -38,6 +38,9 @@ export const Loading = forwardRef<null, LoadingProps>(
) => {
const { internalVisible, setInternalVisible } = useLoading({ visible, delay })

const globalContainer = usePortalContext()?.container
const container = containerProp ?? globalContainer

useImperativeHandle(innerRef, () => ({
close: () => setInternalVisible(false),
}))
Expand Down
7 changes: 5 additions & 2 deletions packages/ui/modal/src/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, forwardRef, useCallback, useImperativeHandle } from 'react'
import { cx, getPrefixCls } from '@hi-ui/classname'
import { HiBaseHTMLProps, HiBaseSizeEnum, useLocaleContext } from '@hi-ui/core'
import { HiBaseHTMLProps, HiBaseSizeEnum, useLocaleContext, usePortalContext } from '@hi-ui/core'
import { __DEV__ } from '@hi-ui/env'
import { CSSTransition } from 'react-transition-group'
import { Portal } from '@hi-ui/portal'
Expand Down Expand Up @@ -57,7 +57,7 @@ export const Modal = forwardRef<HTMLDivElement | null, ModalProps>(
onClose,
onCancel,
onConfirm,
container,
container: containerProp,
closeIcon = defaultCloseIcon,
showMask = true,
showHeaderDivider = true,
Expand All @@ -74,6 +74,9 @@ export const Modal = forwardRef<HTMLDivElement | null, ModalProps>(
) => {
const i18n = useLocaleContext()

const globalContainer = usePortalContext()?.container
const container = containerProp ?? globalContainer

const cancelText = isUndef(cancelTextProp) ? i18n.get('modal.cancelText') : cancelTextProp
const confirmText = isUndef(confirmTextProp) ? i18n.get('modal.confirmText') : confirmTextProp

Expand Down
11 changes: 11 additions & 0 deletions packages/ui/portal-context/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# `@hi-ui/portal-context`

> TODO: description

## Usage

```
const PortalContext = require('@hi-ui/portal-context');

// TODO: DEMONSTRATE API
```
5 changes: 5 additions & 0 deletions packages/ui/portal-context/__tests__/portal-context.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const PortalContext = require('../src')

describe('@hi-ui/portal-context', () => {
it('needs tests', () => {})
})
15 changes: 15 additions & 0 deletions packages/ui/portal-context/hi-docs.config.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# PortalContext 上下文

容器设置上下文。

## 何时使用

组件使用场景中文介绍

## 使用示例

<!-- Inject Stories -->

## Props

<!-- Inject Props -->
1 change: 1 addition & 0 deletions packages/ui/portal-context/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../../../jest.config')
54 changes: 54 additions & 0 deletions packages/ui/portal-context/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "@hi-ui/portal-context",
"version": "4.0.0",
"description": "A sub-package for @hi-ui/hiui.",
"keywords": [],
"author": "HiUI <[email protected]>",
"homepage": "https://github.com/XiaoMi/hiui/tree/master/packages/ui/container-context#readme",
"license": "MIT",
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib"
],
"main": "lib/cjs/index.js",
"module": "lib/esm/index.js",
"types": "lib/types/index.d.ts",
"typings": "lib/types/index.d.ts",
"exports": {
".": {
"require": "./lib/cjs/index.js",
"default": "./lib/esm/index.js"
}
},
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/XiaoMi/hiui.git"
},
"scripts": {
"test": "jest",
"clean": "rimraf lib",
"prebuild": "yarn clean",
"build:esm": "hi-build ./src/index.ts --format esm -d ./lib/esm",
"build:cjs": "hi-build ./src/index.ts --format cjs -d ./lib/cjs",
"build:types": "tsc --emitDeclarationOnly --declaration --declarationDir lib/types",
"build": "concurrently yarn:build:*"
},
"bugs": {
"url": "https://github.com/XiaoMi/hiui/issues"
},
"dependencies": {},
"peerDependencies": {
"react": ">=16.8.6",
"react-dom": ">=16.8.6"
},
"devDependencies": {
"react": "^17.0.1",
"react-dom": "^17.0.1"
}
}
11 changes: 11 additions & 0 deletions packages/ui/portal-context/src/PortalContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createContext, useContext } from 'react'

export const PortalContext = createContext<UsePortalContext>(null)

export const usePortalContext = () => {
const context = useContext(PortalContext)

return context
}

export type UsePortalContext = { container?: HTMLElement | null | undefined } | null | undefined
18 changes: 18 additions & 0 deletions packages/ui/portal-context/src/PortalProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react'
import { PortalContext, UsePortalContext } from './PortalContext'
import { __DEV__ } from '@hi-ui/env'

export const PortalProvider: React.FC<PortalProviderProps> = ({ children, portal }) => {
return <PortalContext.Provider value={portal}>{children}</PortalContext.Provider>
}

export interface PortalProviderProps {
/**
* 指定 portal 的容器
*/
portal?: UsePortalContext
}

if (__DEV__) {
PortalProvider.displayName = 'PortalProvider'
}
4 changes: 4 additions & 0 deletions packages/ui/portal-context/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './PortalContext'
export * from './PortalProvider'

export { PortalProvider as default } from './PortalProvider'
16 changes: 16 additions & 0 deletions packages/ui/portal-context/stories/basic.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React, { useContext } from 'react'
import { PortalContext } from '../src'

/**
* @title 基础用法
*/
export const Basic = () => {
useContext(PortalContext)

return (
<>
<h1>Basic</h1>
<div className="portal-context-basic__wrap"></div>
</>
)
}
8 changes: 8 additions & 0 deletions packages/ui/portal-context/stories/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react'

export * from './basic.stories'

export default {
title: 'Private(暂不对外)/PortalContext',
decorators: [(story: Function) => <div>{story()}</div>],
}
4 changes: 4 additions & 0 deletions packages/ui/portal-context/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../../../tsconfig.json",
"include": ["./src"]
}
17 changes: 15 additions & 2 deletions packages/ui/preview/src/Preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Portal } from '@hi-ui/portal'
import { Watermark, WatermarkProps } from '@hi-ui/watermark'
import { CSSTransition } from 'react-transition-group'
import { useUncontrolledState } from '@hi-ui/use-uncontrolled-state'
import { HiBaseHTMLProps } from '@hi-ui/core'
import { HiBaseHTMLProps, usePortalContext } from '@hi-ui/core'
import { useLatestCallback } from '@hi-ui/use-latest'
import {
ZoomInOutlined,
Expand Down Expand Up @@ -46,11 +46,16 @@ export const Preview = forwardRef<HTMLDivElement | null, PreviewProps>(
src,
watermarkProps,
disabledDownload = false,
container: containerProp,
disabledPortal = false,
},
ref
) => {
const cls = cx(prefixCls, className)

const globalContainer = usePortalContext()?.container
const container = containerProp ?? globalContainer

const [active, setActive] = useUncontrolledState(defaultCurrent || 0, current, onPreviewChange)

const [isMoving, setIsMoving] = useState(false)
Expand Down Expand Up @@ -199,7 +204,7 @@ export const Preview = forwardRef<HTMLDivElement | null, PreviewProps>(
)

return (
<Portal>
<Portal container={container} disabled={disabledPortal}>
<div ref={ref} role={role} className={cls} style={{ ...style, display: 'none' }}>
<CSSTransition
classNames={`${prefixCls}__mask--transition`}
Expand Down Expand Up @@ -352,6 +357,14 @@ export interface PreviewProps extends Omit<HiBaseHTMLProps<'div'>, 'onError'> {
* 当前预览图片索引(受控)
*/
onPreviewChange?: (current: number) => void
/**
* 指定 portal 的容器
*/
container?: HTMLElement | null
/**
* 是否禁用 portal
*/
disabledPortal?: boolean
}

if (__DEV__) {
Expand Down
21 changes: 16 additions & 5 deletions packages/ui/provider/src/Provider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import React, { useEffect } from 'react'
import { __DEV__ } from '@hi-ui/env'
import { LocaleProvider, LocaleProviderProps } from '@hi-ui/core'
import {
LocaleProvider,
LocaleProviderProps,
PortalProvider,
PortalProviderProps,
} from '@hi-ui/core'
import { DesignSystemAccentColorEnum, DesignSystemProps } from './types'
import { createSystem, extendsTheme } from './theme'
import { getAccentColorTheme } from './accent-color'
Expand All @@ -13,6 +18,7 @@ export const Provider: React.FC<ProviderProps> & { extends: ProviderExtendsFunc
languages,
accentColor,
theme,
portal,
}) => {
/**
* global css var config
Expand All @@ -31,13 +37,18 @@ export const Provider: React.FC<ProviderProps> & { extends: ProviderExtendsFunc
}, [accentColor, theme])

return (
<LocaleProvider locale={locale} languages={languages}>
{children}
</LocaleProvider>
<PortalProvider portal={portal}>
<LocaleProvider locale={locale} languages={languages}>
{children}
</LocaleProvider>
</PortalProvider>
)
}

export interface ProviderProps extends LocaleProviderProps, ThemeProviderProps {}
export interface ProviderProps
extends LocaleProviderProps,
PortalProviderProps,
ThemeProviderProps {}

interface ThemeProviderProps {
/**
Expand Down
Loading