trigger
const Popup = React.forwardRef<PopupInnerRef, PopupProps>(
({ visible, mobile, ...props }, ref) => {
const [innerVisible, serInnerVisible] = useState(visible);
const [inMobile, setInMobile] = useState(false);
const cloneProps = { ...props, visible: innerVisible };
useEffect(() => {
serInnerVisible(visible);
if (visible && mobile) {
setInMobile(isMobile());
}
}, [visible, mobile]);
const popupNode: React.ReactNode = inMobile ? (
<MobilePopupInner {...cloneProps} mobile={mobile} ref={ref} />
) : (
<PopupInner {...cloneProps} ref={ref} />
);
return (
<div>
<Mask {...cloneProps} />
{popupNode}
</div>
);
},
);
getComponent =<Popup
prefixCls={prefixCls}
destroyPopupOnHide={destroyPopupOnHide}
visible={popupVisible}
point={alignPoint && point}
className={popupClassName}
align={align}
onAlign={onPopupAlign}
animation={popupAnimation}
getClassNameFromAlign={this.getPopupClassNameFromAlign}
{...mouseProps}
stretch={stretch}
getRootDomNode={this.getRootDomNode}
style={popupStyle}
mask={mask}
zIndex={zIndex}
transitionName={popupTransitionName}
maskAnimation={maskAnimation}
maskTransitionName={maskTransitionName}
maskMotion={maskMotion}
ref={this.popupRef}
motion={popupMotion}
mobile={mobile}
forceRender={forceRender}
>
{typeof popup === 'function' ? popup() : popup}
</Popup>
if (popupVisible || this.popupRef.current || forceRender) {
portal = (
<PortalComponent
key="portal"
getContainer={this.getContainer}
didUpdate={this.handlePortalUpdate}
>
{this.getComponent()}
</PortalComponent>
);
}
if (!popupVisible && autoDestroy) {
portal = null;
}
return (
<TriggerContext.Provider value={this.triggerContextValue}>
{trigger}
{portal}
</TriggerContext.Provider>
);
Tooltip
const Content = (props: ContentProps) => {
const { overlay, prefixCls, id, overlayInnerStyle } = props;
return (
<div className={`${prefixCls}-inner`} id={id} role="tooltip" style={overlayInnerStyle}>
{typeof overlay === 'function' ? overlay() : overlay}
</div>
);
};
const getPopupElement = () => {
const { showArrow = true, arrowContent = null, overlay, id } = props;
return [
showArrow && (
<div className={`${prefixCls}-arrow`} key="arrow">
{arrowContent}
</div>
),
<Content
key="content"
prefixCls={prefixCls}
id={id}
overlay={overlay}
overlayInnerStyle={overlayInnerStyle}
/>,
];
};
return (
<Trigger
popupClassName={overlayClassName}
prefixCls={prefixCls}
popup={getPopupElement}
action={trigger}
builtinPlacements={placements}
popupPlacement={placement}
ref={domRef}
popupAlign={align}
getPopupContainer={getTooltipContainer}
onPopupVisibleChange={onVisibleChange}
afterPopupVisibleChange={afterVisibleChange}
popupTransitionName={transitionName}
popupAnimation={animation}
popupMotion={motion}
defaultPopupVisible={defaultVisible}
destroyPopupOnHide={destroyTooltip}
autoDestroy={autoDestroy}
mouseLeaveDelay={mouseLeaveDelay}
popupStyle={overlayStyle}
mouseEnterDelay={mouseEnterDelay}
{...extraProps}
>
{children}
</Trigger>
);
Dropdown
const getOverlayElement = (): React.ReactElement => {
const { overlay } = props;
let overlayElement: React.ReactElement;
if (typeof overlay === 'function') {
overlayElement = overlay();
} else {
overlayElement = overlay;
}
return overlayElement;
};
const getMenuElement = () => {
const overlayElement = getOverlayElement();
const extraOverlayProps = {
prefixCls: `${prefixCls}-menu`,
onClick,
};
if (typeof overlayElement.type === 'string') {
delete extraOverlayProps.prefixCls;
}
return (
<>
{arrow && <div className={`${prefixCls}-arrow`} />}
{React.cloneElement(overlayElement, extraOverlayProps)}
</>
);
};
const getMenuElementOrLambda = () => {
const { overlay } = props;
if (typeof overlay === 'function') {
return getMenuElement;
}
return getMenuElement();
};
const renderChildren = () => {
const { children } = props;
const childrenProps = children.props ? children.props : {};
const childClassName = classNames(childrenProps.className, getOpenClassName());
return triggerVisible && children
? React.cloneElement(children, {
className: childClassName,
})
: children;
};
return (
<Trigger
builtinPlacements={placements}
{...otherProps}
prefixCls={prefixCls}
ref={triggerRef}
popupClassName={classNames(overlayClassName, {
[`${prefixCls}-show-arrow`]: arrow,
})}
popupStyle={overlayStyle}
action={trigger}
showAction={showAction}
hideAction={triggerHideAction || []}
popupPlacement={placement}
popupAlign={align}
popupTransitionName={transitionName}
popupAnimation={animation}
popupVisible={mergedVisible}
stretch={getMinOverlayWidthMatchTrigger() ? 'minWidth' : ''}
popup={getMenuElementOrLambda()}
onPopupVisibleChange={onVisibleChange}
getPopupContainer={getPopupContainer}
>
{renderChildren()}
</Trigger>
);
Select
return (
<SelectContext.Provider value={selectContext}>
<BaseSelect
{...restProps}
// >>> MISC
id={mergedId}
prefixCls={prefixCls}
ref={ref}
omitDomProps={OMIT_DOM_PROPS}
mode={mode}
// >>> Values
displayValues={displayValues}
onDisplayValuesChange={onDisplayValuesChange}
// >>> Search
searchValue={mergedSearchValue}
onSearch={onInternalSearch}
onSearchSplit={onInternalSearchSplit}
dropdownMatchSelectWidth={dropdownMatchSelectWidth}
// >>> OptionList
OptionList={OptionList}
emptyOptions={!displayOptions.length}
// >>> Accessibility
activeValue={activeValue}
activeDescendantId={`${mergedId}_list_${accessibilityIndex}`}
/>
</SelectContext.Provider>
);
const selectorNode = (
<SelectTrigger
ref={triggerRef}
disabled={disabled}
prefixCls={prefixCls}
visible={triggerOpen}
popupElement={optionList}
containerWidth={containerWidth}
animation={animation}
transitionName={transitionName}
dropdownStyle={dropdownStyle}
dropdownClassName={dropdownClassName}
direction={direction}
dropdownMatchSelectWidth={dropdownMatchSelectWidth}
dropdownRender={dropdownRender}
dropdownAlign={dropdownAlign}
placement={placement}
getPopupContainer={getPopupContainer}
empty={emptyOptions}
getTriggerDOMNode={() => selectorDomRef.current}
onPopupVisibleChange={onTriggerVisibleChange}
onPopupMouseEnter={onPopupMouseEnter}
>
{customizeRawInputElement ? (
React.cloneElement(customizeRawInputElement, {
ref: customizeRawInputRef,
})
) : (
<Selector
{...props}
domRef={selectorDomRef}
prefixCls={prefixCls}
inputElement={customizeInputElement}
ref={selectorRef}
id={id}
showSearch={mergedShowSearch}
mode={mode}
activeDescendantId={activeDescendantId}
tagRender={tagRender}
values={displayValues}
open={mergedOpen}
onToggleOpen={onToggleOpen}
activeValue={activeValue}
searchValue={mergedSearchValue}
onSearch={onInternalSearch}
onSearchSubmit={onInternalSearchSubmit}
onRemove={onSelectorRemove}
tokenWithEnter={tokenWithEnter}
/>
)}
</SelectTrigger>
);
let renderNode: React.ReactNode;
// Render raw
if (customizeRawInputElement) {
renderNode = selectorNode;
} else {
renderNode = (
<div
className={mergedClassName}
{...domProps}
ref={containerRef}
onMouseDown={onInternalMouseDown}
onKeyDown={onInternalKeyDown}
onKeyUp={onInternalKeyUp}
onFocus={onContainerFocus}
onBlur={onContainerBlur}
>
{selectorNode}
{arrowNode}
{clearNode}
</div>
);
}
return (
<BaseSelectContext.Provider value={baseSelectContext}>{renderNode}</BaseSelectContext.Provider>
);
});
return (
<Trigger
{...restProps}
showAction={onPopupVisibleChange ? ['click'] : []}
hideAction={onPopupVisibleChange ? ['click'] : []}
popupPlacement={placement || (direction === 'rtl' ? 'bottomRight' : 'bottomLeft')}
builtinPlacements={builtInPlacements}
prefixCls={dropdownPrefixCls}
popupTransitionName={mergedTransitionName}
popup={
<div ref={popupRef} onMouseEnter={onPopupMouseEnter}>
{popupNode}
</div>
}
popupAlign={dropdownAlign}
popupVisible={visible}
getPopupContainer={getPopupContainer}
popupClassName={classNames(dropdownClassName, {
[`${dropdownPrefixCls}-empty`]: empty,
})}
popupStyle={popupStyle}
getTriggerDOMNode={getTriggerDOMNode}
onPopupVisibleChange={onPopupVisibleChange}
>
{children}
</Trigger>
);
};
TreeSelect
return (
<TreeSelectContext.Provider value={treeSelectContext}>
<LegacyContext.Provider value={legacyContext}>
<BaseSelect
ref={ref}
{...restProps}
// >>> MISC
id={mergedId}
prefixCls={prefixCls}
mode={mergedMultiple ? 'multiple' : undefined}
// >>> Display Value
displayValues={cachedDisplayValues}
onDisplayValuesChange={onDisplayValuesChange}
// >>> Search
searchValue={mergedSearchValue}
onSearch={onInternalSearch}
// >>> Options
OptionList={OptionList}
emptyOptions={!mergedTreeData.length}
onDropdownVisibleChange={onInternalDropdownVisibleChange}
/>
</LegacyContext.Provider>
</TreeSelectContext.Provider>
);
});
OptionList
return (
<div onMouseDown={onListMouseDown}>
{activeEntity && open && (
<span style={HIDDEN_STYLE} aria-live="assertive">
{activeEntity.node.value}
</span>
)}
<Tree
ref={treeRef}
focusable={false}
prefixCls={`${prefixCls}-tree`}
treeData={memoTreeData as TreeDataNode[]}
height={listHeight}
itemHeight={listItemHeight}
virtual={virtual}
multiple={multiple}
icon={treeIcon}
showIcon={showTreeIcon}
switcherIcon={switcherIcon}
showLine={treeLine}
loadData={searchValue ? null : (loadData as any)}
motion={treeMotion}
// We handle keys by out instead tree self
checkable={checkable}
checkStrictly
checkedKeys={mergedCheckedKeys}
selectedKeys={!checkable ? checkedKeys : []}
defaultExpandAll={treeDefaultExpandAll}
{...treeProps}
// Proxy event out
onActiveChange={setActiveKey}
onSelect={onInternalSelect}
onCheck={onInternalSelect}
onExpand={onInternalExpand}
onLoad={onTreeLoad}
filterTreeNode={filterTreeNode}
/>
</div>
);
};
Cascader
import generate from 'rc-tree-select/lib/generate';
const RefCascader = generate({
prefixCls: 'rc-cascader',
optionList: OptionList,
});
OptionList
const columnNodes: React.ReactElement[] = mergedOptionColumns.map((col, index) => (
<Column
key={index}
index={index}
{...columnProps}
isEmpty={isEmpty}
prefixCls={mergedPrefixCls}
options={col.options}
openKey={mergedOpenPath[index]}
/>
));
return (
<>
<div
className={classNames(`${mergedPrefixCls}-menus`, {
[`${mergedPrefixCls}-menu-empty`]: isEmpty,
[`${mergedPrefixCls}-rtl`]: rtl,
})}
ref={containerRef}
>
{columnNodes}
</div>
</>
);
Column
return (
<ul className={menuPrefixCls} role="menu">
{options.map(option => {
const { disabled, value, node } = option;
const isMergedLeaf = isLeaf(option);
const isLoading = loadingKeys.includes(value);
// >>>>> checked
const checked = checkedSet.has(value);
// >>>>> Open
const triggerOpenPath = () => {
if (!disabled && (!hoverOpen || !isMergedLeaf)) {
onOpen(index, value);
}
};
// >>>>> Selection
const triggerSelect = () => {
if (!disabled && (isMergedLeaf || changeOnSelect || multiple)) {
onSelect(value, isMergedLeaf);
}
};
// >>>>> Title
let title: string;
if (typeof node?.title === 'string') {
title = node.title;
} else if (typeof option.title === 'string') {
title = option.title;
}
// >>>>> Render
return (
<li
key={value}
className={classNames(menuItemPrefixCls, {
[`${menuItemPrefixCls}-expand`]: !isMergedLeaf,
[`${menuItemPrefixCls}-active`]: openKey === value,
[`${menuItemPrefixCls}-disabled`]: disabled,
[`${menuItemPrefixCls}-loading`]: isLoading,
})}
style={dropdownMenuColumnStyle}
role="menuitemcheckbox"
title={title}
aria-checked={checked}
data-value={value}
onClick={() => {
triggerOpenPath();
if (!multiple || isMergedLeaf) {
triggerSelect();
}
}}
onDoubleClick={() => {
if (changeOnSelect) {
onToggleOpen(false);
}
}}
onMouseEnter={() => {
if (hoverOpen) {
triggerOpenPath();
}
}}
>
{multiple && !isEmpty && (
<Checkbox
prefixCls={`${prefixCls}-checkbox`}
checked={checked}
halfChecked={halfCheckedSet.has(value)}
disabled={disabled}
onClick={(e: React.MouseEvent<HTMLSpanElement>) => {
e.stopPropagation();
triggerSelect();
}}
/>
)}
<div className={`${menuItemPrefixCls}-content`}>{option.title}</div>
{!isLoading && expandIcon && !isMergedLeaf && (
<div className={`${menuItemPrefixCls}-expand-icon`}>{expandIcon}</div>
)}
{isLoading && loadingIcon && (
<div className={`${menuItemPrefixCls}-loading-icon`}>{loadingIcon}</div>
)}
</li>
);
})}
</ul>
);
return (
<CascaderContext.Provider value={context}>
<RefCascader
ref={cascaderRef}
{...restProps}
fieldNames={mergedFieldNames}
value={checkable ? internalValue : internalValue[0]}
placement={mergedPlacement}
dropdownMatchSelectWidth={false}
dropdownStyle={dropdownStyle}
dropdownClassName={mergedDropdownClassName}
treeData={mergedOptions}
treeCheckable={checkable}
treeNodeFilterProp="label"
onChange={onInternalChange}
showCheckedStrategy={RefCascader.SHOW_PARENT}
open={mergedOpen}
onDropdownVisibleChange={onInternalDropdownVisibleChange}
searchValue={mergedSearch}
// Customize filter logic in OptionList
filterTreeNode={() => true}
showSearch={mergedShowSearch}
onSearch={setMergedSearch}
labelRender={labelRender}
getRawInputElement={() => children}
/>
</CascaderContext.Provider>
);
Dialog
<Portal visible={visible} forceRender={forceRender} getContainer={getContainer}>
{(childProps: IDialogChildProps) => (
<Dialog
{...props}
destroyOnClose={destroyOnClose}
afterClose={() => {
afterClose?.();
setAnimatedVisible(false);
}}
{...childProps}
/>
)}
</Portal>
Dialog
return (
<div className={`${prefixCls}-root`} {...pickAttrs(props, { data: true })}>
<Mask
prefixCls={prefixCls}
visible={mask && visible}
motionName={getMotionName(prefixCls, maskTransitionName, maskAnimation)}
style={{
zIndex,
...maskStyle,
}}
maskProps={maskProps}
/>
<div
tabIndex={-1}
onKeyDown={onWrapperKeyDown}
className={classNames(`${prefixCls}-wrap`, wrapClassName)}
ref={wrapperRef}
onClick={onWrapperClick}
role="dialog"
aria-labelledby={title ? ariaIdRef.current : null}
style={{ zIndex, ...wrapStyle, display: !animatedVisible ? 'none' : null }}
{...wrapProps}
>
<Content
{...props}
onMouseDown={onContentMouseDown}
onMouseUp={onContentMouseUp}
ref={contentRef}
closable={closable}
ariaId={ariaIdRef.current}
prefixCls={prefixCls}
visible={visible}
onClose={onInternalClose}
onVisibleChanged={onDialogVisibleChanged}
motionName={getMotionName(prefixCls, transitionName, animation)}
/>
</div>
</div>
);
Content
return (
<CSSMotion
visible={visible}
onVisibleChanged={onVisibleChanged}
onAppearPrepare={onPrepare}
onEnterPrepare={onPrepare}
forceRender={forceRender}
motionName={motionName}
removeOnLeave={destroyOnClose}
ref={dialogRef}
>
{({ className: motionClassName, style: motionStyle }, motionRef) => (
<div
key="dialog-element"
role="document"
ref={motionRef}
style={{ ...motionStyle, ...style, ...contentStyle }}
className={classNames(prefixCls, className, motionClassName)}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
>
<div tabIndex={0} ref={sentinelStartRef} style={sentinelStyle} aria-hidden="true" />
<MemoChildren shouldUpdate={visible || forceRender}>
{modalRender ? modalRender(content) : content}
</MemoChildren>
<div tabIndex={0} ref={sentinelEndRef} style={sentinelStyle} aria-hidden="true" />
</div>
)}
</CSSMotion>
);
});
Drawer
return (
<Portal
visible={open}
forceRender={$forceRender}
getContainer={getContainer}
wrapperClassName={wrapperClassName}
>
{({ visible, afterClose, ...rest }: IChildProps) => (
// react 15,componentWillUnmount 时 Portal 返回 afterClose, visible.
<Child
{...props}
{...rest}
open={visible !== undefined ? visible : open}
afterVisibleChange={
afterClose !== undefined ? afterClose : props.afterVisibleChange
}
handler={handler}
onClose={this.onClose}
onHandleClick={this.onHandleClick}
/>
)}
</Portal>
);
const handlerChildren =
handler &&
React.cloneElement(handler, {
onClick: (e: React.MouseEvent) => {
if (handler.props.onClick) {
handler.props.onClick();
}
if (onHandleClick) {
onHandleClick(e);
}
},
ref: (c: HTMLElement) => {
this.handlerDom = c;
},
});
return (
<div
{...omit(props, ['switchScrollingEffect', 'autoFocus'])}
tabIndex={-1}
className={wrapperClassName}
style={style}
ref={(c: HTMLElement | null) => {
this.dom = c as HTMLElement;
}}
onKeyDown={open && keyboard ? this.onKeyDown : undefined}
onTransitionEnd={this.onWrapperTransitionEnd}
>
{showMask && (
<div
className={`${prefixCls}-mask`}
onClick={maskClosable ? onClose : undefined}
style={maskStyle}
ref={c => {
this.maskDom = c as HTMLElement;
}}
/>
)}
<div
className={`${prefixCls}-content-wrapper`}
style={{
transform,
msTransform: transform,
width: isNumeric(width) ? `${width}px` : width,
height: isNumeric(height) ? `${height}px` : height,
...contentWrapperStyle,
}}
ref={c => {
this.contentWrapper = c as HTMLElement;
}}
>
<div
className={`${prefixCls}-content`}
ref={c => {
this.contentDom = c as HTMLElement;
}}
>
{children}
</div>
{handlerChildren}
</div>
</div>
);
}
Checkbox
const { checked } = this.state;
const classString = classNames(prefixCls, className, {
[`${prefixCls}-checked`]: checked,
[`${prefixCls}-disabled`]: disabled,
});
return (
<span className={classString} style={style}>
<input
name={name}
id={id}
type={type}
required={required}
readOnly={readOnly}
disabled={disabled}
tabIndex={tabIndex}
className={`${prefixCls}-input`}
checked={!!checked}
onClick={onClick}
onFocus={onFocus}
onBlur={onBlur}
onKeyUp={onKeyUp}
onKeyDown={onKeyDown}
onKeyPress={onKeyPress}
onChange={this.handleChange}
autoFocus={autoFocus}
ref={this.saveInput}
value={value}
{...globalProps}
/>
<span className={`${prefixCls}-inner`} />
</span>
);
Radio
export default class Radio extends React.Component {
static defaultProps = {
prefixCls: 'rc-radio',
type: 'radio',
};
render() {
return <Checkbox {...this.props} ref="checkbox"/>;
}
}
slider
return (
<div
ref={this.saveSlider}
className={sliderClassName}
onTouchStart={disabled ? noop : this.onTouchStart}
onMouseDown={disabled ? noop : this.onMouseDown}
onMouseUp={disabled ? noop : this.onMouseUp}
onKeyDown={disabled ? noop : this.onKeyDown}
onFocus={disabled ? noop : this.onFocus}
onBlur={disabled ? noop : this.onBlur}
style={style}
>
<div
className={`${prefixCls}-rail`}
style={{
...maximumTrackStyle,
...railStyle,
}}
/>
{tracks}
<Steps
prefixCls={prefixCls}
vertical={vertical}
reverse={reverse}
marks={marks}
dots={dots}
step={step}
included={included}
lowerBound={this.getLowerBound()}
upperBound={this.getUpperBound()}
max={max}
min={min}
dotStyle={dotStyle}
activeDotStyle={activeDotStyle}
/>
{handles}
<Marks
className={`${prefixCls}-mark`}
onClickLabel={disabled ? noop : this.onClickMarkLabel}
vertical={vertical}
marks={marks}
included={included}
lowerBound={this.getLowerBound()}
upperBound={this.getUpperBound()}
max={max}
min={min}
reverse={reverse}
/>
{children}
</div>
);
Steps
const Steps = ({
prefixCls,
vertical,
reverse,
marks,
dots,
step,
included,
lowerBound,
upperBound,
max,
min,
dotStyle,
activeDotStyle,
}) => {
const range = max - min;
const elements = calcPoints(vertical, marks, dots, step, min, max).map(point => {
const offset = `${(Math.abs(point - min) / range) * 100}%`;
const isActived =
(!included && point === upperBound) ||
(included && point <= upperBound && point >= lowerBound);
let style = vertical
? { ...dotStyle, [reverse ? 'top' : 'bottom']: offset }
: { ...dotStyle, [reverse ? 'right' : 'left']: offset };
if (isActived) {
style = { ...style, ...activeDotStyle };
}
const pointClassName = classNames({
[`${prefixCls}-dot`]: true,
[`${prefixCls}-dot-active`]: isActived,
[`${prefixCls}-dot-reverse`]: reverse,
});
return <span className={pointClassName} style={style} key={point} />;
});
return <div className={`${prefixCls}-step`}>{elements}</div>;
};
Marks
const elements = marksKeys
.map(parseFloat)
.sort((a, b) => a - b)
.map(point => {
const markPoint = marks[point];
const markPointIsObject = typeof markPoint === 'object' && !React.isValidElement(markPoint);
const markLabel = markPointIsObject ? markPoint.label : markPoint;
if (!markLabel && markLabel !== 0) {
return null;
}
const isActive =
(!included && point === upperBound) ||
(included && point <= upperBound && point >= lowerBound);
const markClassName = classNames({
[`${className}-text`]: true,
[`${className}-text-active`]: isActive,
});
const bottomStyle = {
marginBottom: '-50%',
[reverse ? 'top' : 'bottom']: `${((point - min) / range) * 100}%`,
};
const leftStyle = {
transform: `translateX(${reverse ? `50%` : `-50%`})`,
msTransform: `translateX(${reverse ? `50%` : `-50%`})`,
[reverse ? 'right' : 'left']: `${((point - min) / range) * 100}%`,
};
const style = vertical ? bottomStyle : leftStyle;
const markStyle = markPointIsObject ? { ...style, ...markPoint.style } : style;
return (
<span
className={markClassName}
style={markStyle}
key={point}
onMouseDown={e => onClickLabel(e, point)}
onTouchStart={e => onClickLabel(e, point)}
>
{markLabel}
</span>
);
});
return <div className={className}>{elements}</div>;
Track
const Track = props => {
const { className, included, vertical, style } = props;
let { length, offset, reverse } = props;
if (length < 0) {
reverse = !reverse;
length = Math.abs(length);
offset = 100 - offset;
}
const positonStyle = vertical
? {
[reverse ? 'top' : 'bottom']: `${offset}%`,
[reverse ? 'bottom' : 'top']: 'auto',
height: `${length}%`,
}
: {
[reverse ? 'right' : 'left']: `${offset}%`,
[reverse ? 'left' : 'right']: 'auto',
width: `${length}%`,
};
const elStyle = {
...style,
...positonStyle,
};
return included ? <div className={className} style={elStyle} /> : null;
};
const { tracks, handles } = super.render() as any;
const handle = handleGenerator({
className: `${prefixCls}-handle`,
prefixCls,
vertical,
offset,
value,
dragging,
disabled,
min,
max,
reverse,
index: 0,
tabIndex,
ariaLabel: ariaLabelForHandle,
ariaLabelledBy: ariaLabelledByForHandle,
ariaValueTextFormatter: ariaValueTextFormatterForHandle,
style: handleStyle[0] || handleStyle,
ref: (h) => this.saveHandle(0, h),
});
const trackOffset = startPoint !== undefined ? this.calcOffset(startPoint) : 0;
const mergedTrackStyle = trackStyle[0] || trackStyle;
const track = (
<Track
className={`${prefixCls}-track`}
vertical={vertical}
included={included}
offset={trackOffset}
reverse={reverse}
length={offset - trackOffset}
style={{
...minimumTrackStyle,
...mergedTrackStyle,
}}
/>
);
Tree
<div
role="tree"
className={classNames(prefixCls, className, {
[`${prefixCls}-show-line`]: showLine,
[`${prefixCls}-focused`]: focused,
[`${prefixCls}-active-focused`]: activeKey !== null,
})}
>
<NodeList
ref={this.listRef}
prefixCls={prefixCls}
style={style}
data={flattenNodes}
disabled={disabled}
selectable={selectable}
checkable={!!checkable}
motion={motion}
dragging={draggingNodeKey !== null}
height={height}
itemHeight={itemHeight}
virtual={virtual}
focusable={focusable}
focused={focused}
tabIndex={tabIndex}
activeItem={this.getActiveItem()}
onFocus={this.onFocus}
onBlur={this.onBlur}
onKeyDown={this.onKeyDown}
onActiveChange={this.onActiveChange}
onListChangeStart={this.onListChangeStart}
onListChangeEnd={this.onListChangeEnd}
onContextMenu={onContextMenu}
onScroll={onScroll}
{...this.getTreeNodeRequiredProps()}
{...domProps}
/>
</div>
NodeList
return (
<>
{focused && activeItem && (
<span style={HIDDEN_STYLE} aria-live="assertive">
{getAccessibilityPath(activeItem)}
</span>
)}
<div>
<input
style={HIDDEN_STYLE}
disabled={focusable === false || disabled}
tabIndex={focusable !== false ? tabIndex : null}
onKeyDown={onKeyDown}
onFocus={onFocus}
onBlur={onBlur}
value=""
onChange={noop}
aria-label="for screen reader"
/>
</div>
<div
className={`${prefixCls}-treenode`}
aria-hidden
style={{
position: 'absolute',
pointerEvents: 'none',
visibility: 'hidden',
height: 0,
overflow: 'hidden',
}}
>
<div className={`${prefixCls}-indent`}>
<div ref={indentMeasurerRef} className={`${prefixCls}-indent-unit`} />
</div>
</div>
<VirtualList<FlattenNode>
{...domProps}
data={mergedData}
itemKey={itemKey}
height={height}
fullHeight={false}
virtual={virtual}
itemHeight={itemHeight}
prefixCls={`${prefixCls}-list`}
ref={listRef}
onVisibleChange={(originList, fullList) => {
const originSet = new Set(originList);
const restList = fullList.filter(item => !originSet.has(item));
// Motion node is not render. Skip motion
if (restList.some(item => itemKey(item) === MOTION_KEY)) {
onMotionEnd();
}
}}
>
{(treeNode: FlattenNode) => {
const {
pos,
data: { ...restProps },
title,
key,
isStart,
isEnd,
} = treeNode;
const mergedKey = getKey(key, pos);
delete restProps.key;
delete restProps.children;
const treeNodeProps = getTreeNodeProps(mergedKey, treeNodeRequiredProps);
return (
<MotionTreeNode
{...restProps}
{...treeNodeProps}
title={title}
active={!!activeItem && key === activeItem.data.key}
pos={pos}
data={treeNode.data}
isStart={isStart}
isEnd={isEnd}
motion={motion}
motionNodes={key === MOTION_KEY ? transitionRange : null}
motionType={motionType}
onMotionStart={onListChangeStart}
onMotionEnd={onMotionEnd}
treeNodeRequiredProps={treeNodeRequiredProps}
onMouseMove={() => {
onActiveChange(null);
}}
/>
);
}}
</VirtualList>
</>
);
MotionTreeNode
return (
<div
ref={domRef}
className={classNames(className, `${prefixCls}-treenode`, {
[`${prefixCls}-treenode-disabled`]: disabled,
[`${prefixCls}-treenode-switcher-${expanded ? 'open' : 'close'}`]: !isLeaf,
[`${prefixCls}-treenode-checkbox-checked`]: checked,
[`${prefixCls}-treenode-checkbox-indeterminate`]: halfChecked,
[`${prefixCls}-treenode-selected`]: selected,
[`${prefixCls}-treenode-loading`]: loading,
[`${prefixCls}-treenode-active`]: active,
[`${prefixCls}-treenode-leaf-last`]: isEndNode,
[`${prefixCls}-treenode-draggable`]: draggableWithoutDisabled,
dragging,
'drop-target': dropTargetKey === eventKey,
'drop-container': dropContainerKey === eventKey,
'drag-over': !disabled && dragOver,
'drag-over-gap-top': !disabled && dragOverGapTop,
'drag-over-gap-bottom': !disabled && dragOverGapBottom,
'filter-node': filterTreeNode && filterTreeNode(convertNodePropsToEventData(this.props)),
})}
style={style}
// Draggable config
draggable={draggableWithoutDisabled}
aria-grabbed={dragging}
onDragStart={draggableWithoutDisabled ? this.onDragStart : undefined}
// Drop config
onDragEnter={mergedDraggable ? this.onDragEnter : undefined}
onDragOver={mergedDraggable ? this.onDragOver : undefined}
onDragLeave={mergedDraggable ? this.onDragLeave : undefined}
onDrop={mergedDraggable ? this.onDrop : undefined}
onDragEnd={mergedDraggable ? this.onDragEnd : undefined}
onMouseMove={onMouseMove}
{...dataOrAriaAttributeProps}
>
<Indent prefixCls={prefixCls} level={level} isStart={isStart} isEnd={isEnd} />
{this.renderDragHandler()}
{this.renderSwitcher()}
{this.renderCheckbox()}
{this.renderSelector()}
</div>
);
Steps
return (
<div className={classString} style={style} {...restProps}>
{toArray(children).map((child, index) => {
const stepNumber = initial + index;
const childProps = {
stepNumber: `${stepNumber + 1}`,
stepIndex: stepNumber,
key: stepNumber,
prefixCls,
iconPrefix,
wrapperStyle: style,
progressDot,
stepIcon,
icons,
onStepClick: onChange && this.onStepClick,
...child.props,
};
// fix tail color
if (status === 'error' && index === current - 1) {
childProps.className = `${prefixCls}-next-error`;
}
if (!child.props.status) {
if (stepNumber === current) {
childProps.status = status;
} else if (stepNumber < current) {
childProps.status = 'finish';
} else {
childProps.status = 'wait';
}
}
childProps.active = stepNumber === current;
return cloneElement(child, childProps);
})}
</div>
);
Step
return (
<div {...restProps} className={classString} style={stepItemStyle}>
<div onClick={onClick} {...accessibilityProps} className={`${prefixCls}-item-container`}>
<div className={`${prefixCls}-item-tail`}>{tailContent}</div>
<div className={`${prefixCls}-item-icon`}>{this.renderIconNode()}</div>
<div className={`${prefixCls}-item-content`}>
<div className={`${prefixCls}-item-title`}>
{title}
{subTitle && (
<div
title={typeof subTitle === 'string' ? subTitle : undefined}
className={`${prefixCls}-item-subtitle`}
>
{subTitle}
</div>
)}
</div>
{description && <div className={`${prefixCls}-item-description`}>{description}</div>}
</div>
</div>
</div>
);
Tabs
<TabContext.Provider value={{ tabs, prefixCls }}>
<div
ref={ref}
id={id}
className={classNames(
prefixCls,
`${prefixCls}-${mergedTabPosition}`,
{
[`${prefixCls}-mobile`]: mobile,
[`${prefixCls}-editable`]: editable,
[`${prefixCls}-rtl`]: rtl,
},
className,
)}
{...restProps}
>
{tabNavBar}
<TabPanelList
destroyInactiveTabPane={destroyInactiveTabPane}
{...sharedProps}
animated={mergedAnimated}
/>
</div>
</TabContext.Provider>
if (renderTabBar) {
tabNavBar = renderTabBar(tabNavBarProps, TabNavList);
} else {
tabNavBar = <TabNavList {...tabNavBarProps} />;
}
TabNavList
return (
<div
ref={ref}
role="tablist"
className={classNames(`${prefixCls}-nav`, className)}
style={style}
onKeyDown={() => {
// No need animation when use keyboard
doLockAnimation();
}}
>
<ExtraContent position="left" extra={extra} prefixCls={prefixCls} />
<ResizeObserver onResize={onListHolderResize}>
<div
className={classNames(wrapPrefix, {
[`${wrapPrefix}-ping-left`]: pingLeft,
[`${wrapPrefix}-ping-right`]: pingRight,
[`${wrapPrefix}-ping-top`]: pingTop,
[`${wrapPrefix}-ping-bottom`]: pingBottom,
})}
ref={tabsWrapperRef}
>
<ResizeObserver onResize={onListHolderResize}>
<div
ref={tabListRef}
className={`${prefixCls}-nav-list`}
style={{
transform: `translate(${transformLeft}px, ${transformTop}px)`,
transition: lockAnimation ? 'none' : undefined,
}}
>
{tabNodes}
<AddButton
ref={innerAddButtonRef}
prefixCls={prefixCls}
locale={locale}
editable={editable}
style={{
...(tabNodes.length === 0 ? undefined : tabNodeStyle),
visibility: hasDropdown ? 'hidden' : null,
}}
/>
<div
className={classNames(`${prefixCls}-ink-bar`, {
[`${prefixCls}-ink-bar-animated`]: animated.inkBar,
})}
style={inkStyle}
/>
</div>
</ResizeObserver>
</div>
</ResizeObserver>
<OperationNode
{...props}
removeAriaLabel={locale?.removeAriaLabel}
ref={operationsRef}
prefixCls={prefixCls}
tabs={hiddenTabs}
className={!hasDropdown && operationsHiddenClassName}
tabMoving={!!lockAnimation}
/>
<ExtraContent position="right" extra={extra} prefixCls={prefixCls} />
</div>
);
TabPanelList
const activeIndex = tabs.findIndex(tab => tab.key === activeKey);
return (
<div className={classNames(`${prefixCls}-content-holder`)}>
<div
className={classNames(`${prefixCls}-content`, `${prefixCls}-content-${tabPosition}`, {
[`${prefixCls}-content-animated`]: tabPaneAnimated,
})}
style={
activeIndex && tabPaneAnimated
? { [rtl ? 'marginRight' : 'marginLeft']: `-${activeIndex}00%` }
: null
}
>
{tabs.map(tab => {
return React.cloneElement(tab.node, {
key: tab.key,
prefixCls,
tabKey: tab.key,
id,
animated: tabPaneAnimated,
active: tab.key === activeKey,
destroyInactiveTabPane,
});
})}
</div>
</div>
);