import BaseFoundation, { DefaultAdapter } from '../base/foundation'; import { isArray, get } from 'lodash'; import scrollIntoView, { CustomBehaviorOptions } from 'scroll-into-view-if-needed'; import { cssClasses } from './constants'; const prefixCls = cssClasses.PREFIX; export interface AnchorAdapter
, S = Record {
addLink: (link: string) => void;
removeLink: (link: string) => void;
setChildMap: (value: Record , S = Record ) {
super({ ...AnchorFoundation.defaultAdapter, ...adapter });
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
init = () => {};
// eslint-disable-next-line @typescript-eslint/no-empty-function
destroy = () => {};
addLink = (link: string) => {
this._adapter.addLink(link);
};
removeLink = (link: string) => {
this._adapter.removeLink(link);
};
setActiveLink = (link: string, prevLink: string, shouldNotify = true) => {
const activeLink = this._adapter.getState('activeLink');
const onChange = this._adapter.getProp('onChange');
if (activeLink !== link) {
this._adapter.setActiveLink(link, this._setActiveSlide);
if (onChange && shouldNotify) {
this._adapter.notifyChange(link, prevLink);
}
}
};
// Adjust rail height according to text link content height
setScrollHeight = () => {
const anchorWrapper = `.${prefixCls}-link-wrapper`;
const anchorNode = this._adapter.getAnchorNode(anchorWrapper);
if (anchorNode) {
const scrollHeight = `${anchorNode.scrollHeight}px`;
this._adapter.setScrollHeight(scrollHeight);
}
};
updateScrollHeight = (prevState: any, state: any) => {
const prevLinks = prevState.links.join('');
const links = state.links.join('');
if (prevLinks !== links) {
this.setScrollHeight();
}
};
setChildMap = () => {
const children = this._adapter.getProp('children');
const childMap = {};
if (isArray(children)) {
for (const link of children) {
this._getLinkToMap(link, [], childMap);
}
} else {
this._getLinkToMap(children, [], childMap);
}
this._adapter.setChildMap(childMap);
};
updateChildMap = (prevState: any, state: any) => {
const prevLinks = prevState.links.join('');
const links = state.links.join('');
if (prevLinks !== links) {
this.setChildMap();
}
};
getLinksTop = () => this._adapter.getLinksBoundingTop();
handleScroll = () => {
const { clickLink, links, activeLink: prevActiveLink } = this.getStates(); // TODO check this._adapter -> this.
// ActiveLink Determined by the clicked link
if (clickLink) {
return;
}
const elTop = this.getLinksTop();
let lastNegative = -Infinity;
let lastNegativeIndex = -1;
for (let i = 0; i < elTop.length; i++) {
if (elTop[i] < 0 && elTop[i] > lastNegative) {
lastNegative = elTop[i];
lastNegativeIndex = i;
}
}
const activeLink = links[lastNegativeIndex];
this.setActiveLink(activeLink, prevActiveLink);
};
handleClick = (e: any, link: string, shouldNotify = true) => {
const destNode = this._adapter.getContentNode(link);
const prevLink = this._adapter.getState('activeLink');
this.setActiveLink(link, prevLink, shouldNotify);
if (destNode) {
try {
this._adapter.setClickLinkWithCallBack(true, link, this._scrollIntoView);
} catch (error) {}
}
shouldNotify && this._adapter.notifyClick(e, link);
};
handleClickLink = () => {
this._adapter.setClickLink(false);
};
// Get the child nodes of each link
_getLinkToMap = (link: any, parents: string[], linkMap: { [key: string]: Set