1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/open-hand-choerodon-ui

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Popup.tsx 7.6 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
heqiwei Отправлено год назад 15d383a
import React, { CSSProperties, Key } from 'react';
import { createPortal } from 'react-dom';
import { observer } from 'mobx-react';
import omit from 'lodash/omit';
import shallowEqual from 'shallowequal';
import noop from 'lodash/noop';
import isElement from 'lodash/isElement';
import { PopupManager } from 'choerodon-ui/shared';
import ViewComponent, { ViewComponentProps } from 'choerodon-ui/pro/lib/core/ViewComponent';
import autobind from 'choerodon-ui/pro/lib/_util/autobind';
import { findFocusableElements } from 'choerodon-ui/pro/lib/_util/focusable';
import { getDocument } from 'choerodon-ui/pro/lib/_util/DocumentUtils';
import Align from '../align';
import { getProPrefixCls } from '../configure/utils';
import Animate from '../animate';
import PopupInner from './PopupInner';
const childrenProps = { hidden: 'hidden' };
export interface PopupProps extends ViewComponentProps {
align: object;
onAlign?: (source: Node, align: object, target: HTMLElement, translate: { x: number; y: number }) => void;
getRootDomNode?: () => Element | Text | null;
getPopupContainer?: (triggerNode: Element) => HTMLElement | undefined | null;
transitionName?: string;
onAnimateAppear?: (key: Key | null) => void;
onAnimateEnter?: (key: Key | null) => void;
onAnimateLeave?: (key: Key | null) => void;
onAnimateEnd?: (key: Key | null, exists: boolean) => void;
getStyleFromAlign?: (target: HTMLElement, align: object) => object | undefined;
getClassNameFromAlign?: (align: object) => string | undefined;
getFocusableElements?: (elements: HTMLElement[]) => void;
forceRender?: boolean;
}
function newPopupContainer() {
const doc = getDocument(window);
const popupContainer = doc.createElement('div');
popupContainer.className = getProPrefixCls('popup-container');
return popupContainer;
}
@observer
export default class Popup extends ViewComponent<PopupProps> {
static displayName = 'Popup';
static defaultProps = {
suffixCls: 'popup',
transitionName: 'zoom',
};
popupContainer?: HTMLDivElement;
currentAlignClassName?: string;
currentAlignStyle?: CSSProperties;
align: Align | null;
target?: HTMLElement;
contentRendered = false;
popupKey: string = PopupManager.getKey();
size?: {
width?: number;
height?: number;
};
saveRef = align => (this.align = align);
getOmitPropsKeys(): string[] {
return super.getOmitPropsKeys().concat([
'align',
'transitionName',
'getRootDomNode',
'getPopupContainer',
'getClassNameFromAlign',
'getStyleFromAlign',
'onAlign',
'onAnimateAppear',
'onAnimateEnter',
'onAnimateLeave',
'onAnimateEnd',
'getFocusableElements',
'forceRender',
]);
}
componentWillUnmount() {
const { popupContainer } = this;
if (popupContainer && popupContainer !== PopupManager.container && popupContainer.parentNode) {
popupContainer.parentNode.removeChild(popupContainer);
}
}
componentDidUpdate(): void {
this.findFocusableElements();
}
componentDidMount(): void {
super.componentDidMount();
this.findFocusableElements();
}
findFocusableElements() {
const { element } = this;
const { getFocusableElements } = this.props;
if (element && getFocusableElements) {
const elements = findFocusableElements(element);
getFocusableElements(elements && elements.filter(item => item.tabIndex !== -1).sort((e1, e2) => e1.tabIndex - e2.tabIndex));
}
}
@autobind
renderInner(innerRef) {
const { children, getClassNameFromAlign = noop, align } = this.props;
const className = this.getMergedClassNames(this.currentAlignClassName ||
getClassNameFromAlign(align));
return (
<PopupInner
{...omit(this.getMergedProps(), ['ref', 'className'])}
className={className}
innerRef={innerRef}
onResize={this.handlePopupResize}
>
{children}
</PopupInner>
);
}
render() {
const {
hidden,
align,
transitionName,
getRootDomNode,
forceRender,
onAnimateAppear = noop,
onAnimateEnter = noop,
onAnimateLeave = noop,
onAnimateEnd = noop,
} = this.props;
if (!hidden || forceRender) {
this.contentRendered = true;
}
const container = this.getContainer();
return container && this.contentRendered ? createPortal(
<Animate
component=""
exclusive
transitionAppear
transitionName={transitionName}
hiddenProp="hidden"
onAppear={onAnimateAppear}
onEnter={onAnimateEnter}
onLeave={onAnimateLeave}
onEnd={onAnimateEnd}
>
<Align
ref={this.saveRef}
childrenRef={this.elementReference}
key="align"
childrenProps={childrenProps}
align={align}
onAlign={this.onAlign}
target={getRootDomNode}
hidden={hidden}
monitorWindowResize
>
{this.renderInner}
</Align>
</Animate>,
container,
this.popupKey,
) : null;
}
getContainer(): HTMLDivElement | undefined {
if (typeof window === 'undefined') {
return undefined;
}
const { getPopupContainer, getRootDomNode = noop } = this.props;
const globalContainer = PopupManager.container;
if (getPopupContainer) {
const container = this.popupContainer;
if (container) {
return container;
}
} else if (globalContainer) {
return globalContainer;
}
if (getPopupContainer) {
const mountNode = getPopupContainer(getRootDomNode());
const popupContainer = newPopupContainer();
const root = window.document.body;
if (window === window.top && mountNode === root) {
if (globalContainer) {
this.popupContainer = globalContainer;
return globalContainer;
}
PopupManager.container = popupContainer;
}
(mountNode && isElement(mountNode) ? mountNode : root).appendChild(popupContainer);
this.popupContainer = popupContainer;
return popupContainer;
}
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return getGlobalPopupContainer();
}
@autobind
onAlign(source, align, target, translate) {
const { getClassNameFromAlign = noop, getStyleFromAlign = noop, onAlign = noop } = this.props;
const currentAlignClassName = getClassNameFromAlign(align);
const differentTarget = target !== this.target;
if (differentTarget || this.currentAlignClassName !== currentAlignClassName) {
this.currentAlignClassName = currentAlignClassName;
source.className = this.getMergedClassNames(currentAlignClassName);
}
const currentAlignStyle = getStyleFromAlign(target, align);
if (differentTarget || !shallowEqual(this.currentAlignStyle, currentAlignStyle)) {
this.currentAlignStyle = currentAlignStyle;
Object.assign(source.style, currentAlignStyle);
}
onAlign(source, align, target, translate);
this.target = source;
}
@autobind
handlePopupResize(width, height) {
if (width !== 0 && height !== 0) {
const { width: oldWidth, height: oldHeight } = this.size || {};
if (width !== oldWidth || height !== oldHeight) {
this.size = { width, height };
this.forceAlign();
}
}
}
forceAlign() {
if (this.align) {
this.align.forceAlign();
}
}
}
export function getGlobalPopupContainer() {
if (PopupManager.container) {
return PopupManager.container;
}
const popupContainer = newPopupContainer();
const root = getDocument(window).body;
root.appendChild(popupContainer);
PopupManager.container = popupContainer;
return popupContainer;
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/open-hand-choerodon-ui.git
git@gitlife.ru:oschina-mirror/open-hand-choerodon-ui.git
oschina-mirror
open-hand-choerodon-ui
open-hand-choerodon-ui
master