Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions packages/components/config-provider/ConfigContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createContext } from 'react';
import { merge } from 'lodash-es';
import defaultConfig from '@tdesign/common-js/global-config/default-config';
import defaultLocale from '../locale/zh_CN';
import { GlobalConfigProvider } from './type';
import type { GlobalConfigProvider } from './type';

export enum EAnimationType {
ripple = 'ripple',
Expand All @@ -22,15 +22,33 @@ export const defaultGlobalConfig: GlobalConfigProvider = {
classPrefix: defaultClassPrefix,
...merge({}, defaultLocale, defaultConfig),
};

export type Locale = typeof defaultLocale;

export const defaultContext = {
export interface Config {
globalConfig?: GlobalConfigProvider;
autoZIndex?: boolean;
onZIndexChange?: (zIndex: number) => void;
}

export interface InternalConfig {
globalZIndex?: number;
autoZIndex?: boolean;
setGlobalZIndex?: (zIndex: number) => void;
}

export const defaultContext: Config = {
globalConfig: defaultGlobalConfig,
};

export type Config = typeof defaultContext;
export const defaultInternalContext: InternalConfig = {
globalZIndex: 0,
setGlobalZIndex: undefined,
};

// 供用户使用
const ConfigContext = createContext<Config>(defaultContext);

const ConfigContext = createContext(defaultContext);
// 供内部全局变量使用
export const InternalConfigContext = createContext<InternalConfig>(defaultInternalContext);

export default ConfigContext;
56 changes: 41 additions & 15 deletions packages/components/config-provider/ConfigProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { useEffect } from 'react';
import { mergeWith as _mergeWith, cloneDeep } from 'lodash-es';
import ConfigContext, { defaultGlobalConfig, Config } from './ConfigContext';
import { GlobalConfigProvider } from './type';
import React, { useEffect, useState } from 'react';
import ConfigContext, { Config, defaultGlobalConfig, InternalConfigContext } from './ConfigContext';
import type { GlobalConfigProvider } from './type';

export interface ConfigProviderProps extends Config {
children: React.ReactNode;
/**
* 不需要设置全局上下文信息
* 不需要设置全局上下文信息
* 不传或者false:表示全局上下文变动,需要更新全局上下文的信息放入到变量中
* true:表示全局上下文信息不需要重新设置,
* 解决问题:当plugin调用的时候,单独包裹的Provider 也会传全局变量,仅自身可用,多次调用时相互之间不会冲突。
Expand All @@ -27,25 +27,51 @@ export const merge = (src: GlobalConfigProvider, config: GlobalConfigProvider) =
// 存放全局的上下文配置
let globalConfig = defaultGlobalConfig;

export const getGlobalConfig = (configInfo?: GlobalConfigProvider): GlobalConfigProvider=> merge({ ...globalConfig }, configInfo)

export const setGlobalConfig = (configInfo?: GlobalConfigProvider)=>{
globalConfig = configInfo
}
export const getGlobalConfig = (configInfo?: GlobalConfigProvider): GlobalConfigProvider =>
merge({ ...globalConfig }, configInfo);

export const setGlobalConfig = (configInfo?: GlobalConfigProvider) => {
globalConfig = configInfo;
};

export default function ConfigProvider({ children, globalConfig, notSet }: ConfigProviderProps) {
export default function ConfigProvider({
children,
globalConfig,
notSet,
autoZIndex,
onZIndexChange,
}: ConfigProviderProps) {
const defaultData = cloneDeep(defaultGlobalConfig);
const mergedGlobalConfig = merge(defaultData, globalConfig);

useEffect(()=>{
if(!notSet){
const [globalZIndex, setGlobalZIndex] = useState<number>(0);

useEffect(() => {
if (!notSet) {
// 需要设置的情况下,当配置信息变化时更新变量中的配置信息,方便plugin调用时获取
setGlobalConfig(mergedGlobalConfig)
setGlobalConfig(mergedGlobalConfig);
}
},[mergedGlobalConfig, notSet]);
}, [mergedGlobalConfig, notSet]);

useEffect(() => {
onZIndexChange?.(globalZIndex);
}, [globalZIndex, onZIndexChange]);

const externalContextValue = {
globalConfig: mergedGlobalConfig,
};

const internalContextValue = {
autoZIndex,
globalZIndex,
setGlobalZIndex,
};

return <ConfigContext.Provider value={{ globalConfig: mergedGlobalConfig }}>{children}</ConfigContext.Provider>;
return (
<ConfigContext.Provider value={externalContextValue}>
<InternalConfigContext.Provider value={internalContextValue}>{children}</InternalConfigContext.Provider>
</ConfigContext.Provider>
);
}

ConfigProvider.getGlobalConfig = getGlobalConfig;
Expand Down
75 changes: 75 additions & 0 deletions packages/components/config-provider/_example/z-index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React, { useState } from 'react';

import { Button, Card, ConfigProvider, Dialog, Drawer, Space, Tooltip } from 'tdesign-react';

export default function BasicUsage() {
const [dialogVisible1, setDialogVisible1] = useState(false);
const [drawerVisible1, setDrawerVisible1] = useState(false);

const [dialogVisible2, setDialogVisible2] = useState(false);
const [drawerVisible2, setDrawerVisible2] = useState(false);

return (
<Space size={100}>
<Card
header={
<strong>
启用全局 z-index 管理
<br />
后面打开的组件层级更高
</strong>
}
>
<ConfigProvider autoZIndex onZIndexChange={(zIndex) => console.log('ZIndex changed:', zIndex)}>
<Space>
<Button theme="success" onClick={() => setDialogVisible1(true)}>
Open Modal
</Button>
<Tooltip content="文字提示" visible={true} placement="right">
<Button variant="outline">Tooltip</Button>
</Tooltip>
<Dialog visible={dialogVisible1} onClose={() => setDialogVisible1(false)}>
我的层级比 Tooltip 高
<br />
<Button onClick={() => setDrawerVisible1(true)} style={{ marginTop: '8px' }}>
Open Drawer
</Button>
<Drawer visible={drawerVisible1} onClose={() => setDrawerVisible1(false)}>
我的层级比 Dialog 高
</Drawer>
</Dialog>
</Space>
</ConfigProvider>
</Card>

<Card
header={
<strong>
关闭全局 z-index 管理
<br />
组件层级固定,需要手动设置 zIndex
</strong>
}
>
<Space>
<Button theme="warning" onClick={() => setDialogVisible2(true)}>
Open Modal
</Button>
<Tooltip content="文字提示" visible={true} placement="right">
<Button variant="outline">Tooltip</Button>
</Tooltip>
<Dialog visible={dialogVisible2} onClose={() => setDialogVisible2(false)}>
我的层级比 Tooltip 低
<br />
<Button onClick={() => setDrawerVisible2(true)} style={{ marginTop: '8px' }}>
Open Drawer
</Button>
<Drawer visible={drawerVisible2} onClose={() => setDrawerVisible2(false)}>
我的层级比 Dialog 低
</Drawer>
</Dialog>
</Space>
</Card>
</Space>
);
}
3 changes: 3 additions & 0 deletions packages/components/config-provider/config-provider.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
:: BASE_DOC ::

### z-index
{{ z-index }}

### 全局组件前缀

TDesign 的组件前缀统一为`t`,在一些业务场景中,有需要改变组件前缀来满足业务的使用场景。
Expand Down
31 changes: 21 additions & 10 deletions packages/components/dialog/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react';
import { CSSTransition } from 'react-transition-group';

import classNames from 'classnames';
import { isUndefined } from 'lodash-es';

import log from '@tdesign/common-js/log/index';
import Portal from '../common/Portal';
import useAttach from '../hooks/useAttach';
import useConfig from '../hooks/useConfig';
import useDeepEffect from '../hooks/useDeepEffect';
import useDefaultProps from '../hooks/useDefaultProps';
import useSetState from '../hooks/useSetState';
import useZIndex from '../hooks/useZIndex';
import { useLocaleReceiver } from '../locale/LocalReceiver';
import { dialogDefaultProps } from './defaultProps';
import DialogCard from './DialogCard';
Expand All @@ -17,6 +20,7 @@ import useDialogEsc from './hooks/useDialogEsc';
import useDialogPosition from './hooks/useDialogPosition';
import useLockStyle from './hooks/useLockStyle';
import { parseValueToPx } from './utils';

import type { StyledProps } from '../common';
import type { DialogInstance, TdDialogProps } from './type';

Expand All @@ -27,15 +31,19 @@ export interface DialogProps extends TdDialogProps, StyledProps {
const Dialog = forwardRef<DialogInstance, DialogProps>((originalProps, ref) => {
const props = useDefaultProps<DialogProps>(originalProps, dialogDefaultProps);
const { children, ...restProps } = props;
const { classPrefix } = useConfig();

const { classPrefix } = useConfig();
const componentCls = `${classPrefix}-dialog`;

const wrapRef = useRef<HTMLDivElement>(null);
const maskRef = useRef<HTMLDivElement>(null);
const contentClickRef = useRef(false);
const dialogCardRef = useRef<HTMLDivElement>(null);
const dialogPosition = useRef(null);
const portalRef = useRef(null);

const [portalMounted, setPortalMounted] = useState(false);

const [state, setState] = useSetState<DialogProps>({ isPlugin: false, ...restProps });
const [local] = useLocaleReceiver('dialog');

Expand All @@ -45,7 +53,6 @@ const Dialog = forwardRef<DialogInstance, DialogProps>((originalProps, ref) => {
style,
width,
mode,
zIndex,
visible,
attach,
onBeforeOpen,
Expand All @@ -72,6 +79,8 @@ const Dialog = forwardRef<DialogInstance, DialogProps>((originalProps, ref) => {
...restState
} = state;

const { displayZIndex } = useZIndex('dialog', portalMounted);

const dialogAttach = useAttach('dialog', attach);

useLockStyle({ preventScrollThrough, visible, mode, showInAttachedElement });
Expand All @@ -89,6 +98,7 @@ const Dialog = forwardRef<DialogInstance, DialogProps>((originalProps, ref) => {
}, [props, setState]);

useImperativeHandle(ref, () => ({
// latestZIndex,
show() {
setState({ visible: true });
},
Expand Down Expand Up @@ -149,19 +159,20 @@ const Dialog = forwardRef<DialogInstance, DialogProps>((originalProps, ref) => {
}
};

const onAnimateStart = () => {
if (!wrapRef.current) return;
onBeforeOpen?.();
wrapRef.current.style.display = 'block';
setPortalMounted(true);
};

const onAnimateLeave = () => {
onClosed?.();

if (!wrapRef.current) return;
wrapRef.current.style.display = 'none';
};

const onAnimateStart = () => {
if (!wrapRef.current) return;
onBeforeOpen?.();
wrapRef.current.style.display = 'block';
};

const onInnerAnimateStart = () => {
if (!dialogCardRef.current) return;
dialogCardRef.current.style.display = 'block';
Expand Down Expand Up @@ -209,7 +220,7 @@ const Dialog = forwardRef<DialogInstance, DialogProps>((originalProps, ref) => {
[`${componentCls}__ctx--fixed`]: !showInAttachedElement,
[`${componentCls}__ctx--absolute`]: showInAttachedElement,
})}
style={{ zIndex, display: 'none' }}
style={{ zIndex: displayZIndex, display: 'none' }}
onKeyDown={handleKeyDown}
tabIndex={0}
>
Expand Down
4 changes: 3 additions & 1 deletion packages/components/dialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { withZIndexProvider } from '../hooks/useZIndex';

import _Dialog from './Dialog';
import _DialogCard from './DialogCard';
import { DialogPlugin as _DialogPlugin } from './plugin';
Expand All @@ -7,7 +9,7 @@ import './style/index.js';
export type { DialogProps } from './Dialog';
export * from './type';

export const Dialog = _Dialog;
export const Dialog = withZIndexProvider(_Dialog, 'dialog');
export const DialogCard = _DialogCard;

export const dialog = _DialogPlugin;
Expand Down
1 change: 1 addition & 0 deletions packages/components/dialog/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ export interface DialogOptions extends Omit<TdDialogProps, 'attach'> {
}

export interface DialogInstance {
// latestZIndex: number;
/**
* 销毁弹框
*/
Expand Down
Loading
Loading