|
@@ -10,10 +10,12 @@ import '@douyinfe/semi-foundation/anchor/anchor.scss';
|
|
import { noop, debounce, throttle } from 'lodash';
|
|
import { noop, debounce, throttle } from 'lodash';
|
|
import getUuid from '@douyinfe/semi-foundation/utils/uuid';
|
|
import getUuid from '@douyinfe/semi-foundation/utils/uuid';
|
|
import { ArrayElement } from '../_base/base';
|
|
import { ArrayElement } from '../_base/base';
|
|
|
|
+import ConfigContext, { ContextValue } from '../configProvider/context';
|
|
|
|
|
|
const prefixCls = cssClasses.PREFIX;
|
|
const prefixCls = cssClasses.PREFIX;
|
|
|
|
|
|
export { LinkProps } from './link';
|
|
export { LinkProps } from './link';
|
|
|
|
+
|
|
export interface AnchorProps {
|
|
export interface AnchorProps {
|
|
autoCollapse?: boolean;
|
|
autoCollapse?: boolean;
|
|
className?: string;
|
|
className?: string;
|
|
@@ -44,6 +46,7 @@ export interface AnchorState {
|
|
}
|
|
}
|
|
|
|
|
|
class Anchor extends BaseComponent<AnchorProps, AnchorState> {
|
|
class Anchor extends BaseComponent<AnchorProps, AnchorState> {
|
|
|
|
+ static contextType = ConfigContext;
|
|
static Link = Link;
|
|
static Link = Link;
|
|
static PropTypes = {
|
|
static PropTypes = {
|
|
size: PropTypes.oneOf(strings.SIZE),
|
|
size: PropTypes.oneOf(strings.SIZE),
|
|
@@ -88,6 +91,7 @@ class Anchor extends BaseComponent<AnchorProps, AnchorState> {
|
|
childMap: Record<string, Set<string>>;
|
|
childMap: Record<string, Set<string>>;
|
|
handler: () => void;
|
|
handler: () => void;
|
|
clickHandler: () => void;
|
|
clickHandler: () => void;
|
|
|
|
+ context: ContextValue;
|
|
|
|
|
|
constructor(props: AnchorProps) {
|
|
constructor(props: AnchorProps) {
|
|
super(props);
|
|
super(props);
|
|
@@ -96,7 +100,7 @@ class Anchor extends BaseComponent<AnchorProps, AnchorState> {
|
|
links: [],
|
|
links: [],
|
|
clickLink: false,
|
|
clickLink: false,
|
|
scrollHeight: '100%',
|
|
scrollHeight: '100%',
|
|
- slideBarTop: '0'
|
|
|
|
|
|
+ slideBarTop: '0',
|
|
};
|
|
};
|
|
|
|
|
|
this.foundation = new AnchorFoundation(this.adapter);
|
|
this.foundation = new AnchorFoundation(this.adapter);
|
|
@@ -107,9 +111,7 @@ class Anchor extends BaseComponent<AnchorProps, AnchorState> {
|
|
return {
|
|
return {
|
|
...super.adapter,
|
|
...super.adapter,
|
|
addLink: value => {
|
|
addLink: value => {
|
|
- this.setState(prevState => (
|
|
|
|
- { links: [...prevState.links, value] }
|
|
|
|
- ));
|
|
|
|
|
|
+ this.setState(prevState => ({ links: [...prevState.links, value] }));
|
|
},
|
|
},
|
|
removeLink: link => {
|
|
removeLink: link => {
|
|
this.setState(prevState => {
|
|
this.setState(prevState => {
|
|
@@ -218,6 +220,28 @@ class Anchor extends BaseComponent<AnchorProps, AnchorState> {
|
|
this.foundation.updateChildMap(prevState, state);
|
|
this.foundation.updateChildMap(prevState, state);
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ renderChildren = () => {
|
|
|
|
+ const loop = (children, level = 1) => {
|
|
|
|
+ return React.Children.map(children, child => {
|
|
|
|
+ if (React.isValidElement(child)) {
|
|
|
|
+ const childProps = {
|
|
|
|
+ direction: this.context.direction,
|
|
|
|
+ level,
|
|
|
|
+ children: [],
|
|
|
|
+ };
|
|
|
|
+ const { children } = child.props as any;
|
|
|
|
+ const hasChildren = children && React.Children.count(children) > 0;
|
|
|
|
+ if (hasChildren) {
|
|
|
|
+ childProps.children = loop(children, level + 1);
|
|
|
|
+ }
|
|
|
|
+ return React.cloneElement(child, childProps);
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ });
|
|
|
|
+ };
|
|
|
|
+ return loop(this.props.children);
|
|
|
|
+ };
|
|
|
|
+
|
|
componentDidMount() {
|
|
componentDidMount() {
|
|
const { defaultAnchor = '' } = this.props;
|
|
const { defaultAnchor = '' } = this.props;
|
|
this.anchorID = getUuid('semi-anchor').replace('.', '');
|
|
this.anchorID = getUuid('semi-anchor').replace('.', '');
|
|
@@ -286,15 +310,23 @@ class Anchor extends BaseComponent<AnchorProps, AnchorState> {
|
|
removeLink: this.removeLink,
|
|
removeLink: this.removeLink,
|
|
}}
|
|
}}
|
|
>
|
|
>
|
|
- <div role="navigation" aria-label={ ariaLabel || 'Side navigation'} className={wrapperCls} style={wrapperStyle} id={this.anchorID}>
|
|
|
|
|
|
+ <div
|
|
|
|
+ role="navigation"
|
|
|
|
+ aria-label={ariaLabel || 'Side navigation'}
|
|
|
|
+ className={wrapperCls}
|
|
|
|
+ style={wrapperStyle}
|
|
|
|
+ id={this.anchorID}
|
|
|
|
+ >
|
|
<div aria-hidden className={slideCls} style={{ height: scrollHeight }}>
|
|
<div aria-hidden className={slideCls} style={{ height: scrollHeight }}>
|
|
<span className={slideBarCls} style={{ top: slideBarTop }} />
|
|
<span className={slideBarCls} style={{ top: slideBarTop }} />
|
|
</div>
|
|
</div>
|
|
- <div className={anchorWrapper} role="list">{children}</div>
|
|
|
|
|
|
+ <div className={anchorWrapper} role="list">
|
|
|
|
+ {this.renderChildren()}
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
</AnchorContext.Provider>
|
|
</AnchorContext.Provider>
|
|
);
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-export default Anchor;
|
|
|
|
|
|
+export default Anchor;
|