@zohodesk/components
Version:
Dot UI is a customizable React component library built to deliver a clean, accessible, and developer-friendly UI experience. It offers a growing set of reusable components designed to align with modern design systems and streamline application development
305 lines (275 loc) • 8.68 kB
JavaScript
import React, { Component } from 'react';
import { CardHeader_propTypes, CardContent_propTypes, Card_propTypes, CardFooter_propTypes } from "./props/propTypes";
import { Card_defaultProps, CardHeader_defaultProps, CardContent_defaultProps, CardFooter_defaultProps } from "./props/defaultProps";
import { Container, Box } from "../Layout";
import { getLibraryConfig } from "../Provider/Config";
import style from "./Card.module.css";
/* eslint-disable react/forbid-component-props */
/*
isscroll header border change use ref
scroll logic remove from here
scroll logic move to virtualizer list
*/
/* performance handling pending in card component moving to ref instead of setState */
export class CardHeader extends Component {
constructor(props) {
super(props);
this.getCardHeaderDom = this.getCardHeaderDom.bind(this);
this.cardHeader = null;
}
getCardHeaderDom(ele) {
this.cardHeader = ele;
}
setScrollClassName() {
if (!this.cardHeader) {
return null;
}
}
render() {
let {
isScroll,
children,
dataId,
dataSelectorId,
customClass
} = this.props;
return /*#__PURE__*/React.createElement(Box, {
className: `${isScroll ? style.scroll : style.notScroll} ${customClass}`,
eleRef: this.getCardHeaderDom,
dataId: dataId,
dataSelectorId: dataSelectorId
}, children);
}
}
CardHeader.propTypes = CardHeader_propTypes;
CardHeader.defaultProps = CardHeader_defaultProps;
export class CardContent extends Component {
render() {
let {
onScroll,
eleRef,
children,
scroll,
isScrollAttribute,
dataId,
dataSelectorId,
shrink,
customClass,
preventParentScroll
} = this.props;
return /*#__PURE__*/React.createElement(Box, {
flexible: true,
onScroll: onScroll,
eleRef: eleRef,
scroll: scroll,
preventParentScroll: preventParentScroll,
isScrollAttribute: isScrollAttribute,
dataId: dataId,
shrink: shrink,
className: customClass,
dataSelectorId: dataSelectorId
}, children);
}
}
CardContent.propTypes = CardContent_propTypes;
CardContent.defaultProps = CardContent_defaultProps;
export default class Card extends Component {
constructor(props) {
super(props);
this.state = {
isScroll: false
};
let {
from,
limit
} = props;
this.from = from;
this.limit = limit;
this.to = from + 3 * limit;
this.isFetching = false;
this.lastScrollTop = 0;
this.onScroll = this.onScroll.bind(this);
this.setScrollRef = this.setScrollRef.bind(this);
this.childEleRef = null; //this.onSetScroll = debounce(this.setScroll.bind(this, true), 10, true);
//this.onClearScroll = debounce(this.setScroll.bind(this, false), 500);
}
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.from !== nextProps.from) {
this.from = nextProps.from;
}
}
onScroll(e) {
let scrollContainerObj = e.currentTarget;
let {
scrollHeight
} = scrollContainerObj;
let {
scrollTop
} = scrollContainerObj;
let {
offsetHeight
} = scrollContainerObj;
let {
onScroll
} = this.props;
onScroll && onScroll(e);
let {
fetchData,
noMoreData,
scrollAt,
noNeedUpScroll,
// isScrollShadow,
isPercentageScroll,
scrollDirection
} = this.props;
const scrollLimitHeight = scrollHeight - scrollAt;
const currentVisibleBottom = scrollTop + offsetHeight;
if (scrollTop > this.lastScrollTop) {
this.scrollingDirection = 'down';
} else {
this.scrollingDirection = 'up';
}
this.lastScrollTop = scrollTop;
if (fetchData && !this.isFetching) {
const fetchDirection = scrollDirection === 'bottomToTop' ? 'up' : 'down';
if (this.scrollingDirection === fetchDirection && !noMoreData) {
let prefetch = false;
if (isPercentageScroll) {
const scrollingPercentage = scrollDirection === 'bottomToTop' ? (scrollHeight - scrollTop) / scrollLimitHeight * 100 : currentVisibleBottom / scrollLimitHeight * 100;
prefetch = scrollingPercentage >= getLibraryConfig('scrollFetchLimit');
} else {
prefetch = scrollDirection === 'bottomToTop' ? scrollTop <= scrollAt : scrollLimitHeight <= currentVisibleBottom;
}
if (prefetch) {
this.isFetching = true;
fetchData(this.from + this.limit, this.limit + this.to, this.scrollingDirection).then(() => {
this.to = this.limit + this.to;
this.isFetching = false;
}, () => {
this.isFetching = false;
});
}
} else {
const prefetch = scrollDirection === 'bottomToTop' ? scrollLimitHeight <= currentVisibleBottom : 0 >= scrollTop - scrollAt;
if (prefetch && this.from !== 0 && !noNeedUpScroll) {
this.isFetching = true;
fetchData(this.from - this.limit, this.to - this.limit, this.scrollingDirection).then(() => {
this.to = this.to - this.limit;
this.isFetching = false;
}, () => {
this.isFetching = false;
});
}
}
}
if (fetchData && !noNeedUpScroll) {
const topFetch = scrollDirection === 'bottomToTop' ? !noMoreData : !noNeedUpScroll && this.from !== 0;
const bottomFetch = scrollDirection === 'bottomToTop' ? !noNeedUpScroll && this.from !== 0 : !noMoreData;
if (scrollTop === 0 && topFetch) {
scrollContainerObj.scrollTop = scrollTop + offsetHeight / 3;
} else if (scrollHeight === currentVisibleBottom && bottomFetch) {
scrollContainerObj.scrollTop = scrollTop - offsetHeight / 2;
}
} // if (isScrollShadow) {
// this.onSetScroll();
// }
} // setScroll(isScroll) {
// let { isScroll: stateIsScroll } = this.state;
// if (isScroll && !stateIsScroll) {
// this.setState({ isScroll: true }, () => {
// this.onClearScroll();
// });
// } else if (!isScroll && stateIsScroll) {
// this.setState({ isScroll: false });
// }
// }
setScrollRef(el) {
const {
scrollAt,
scrollDirection
} = this.props;
if (el && scrollDirection === 'bottomToTop') {
requestAnimationFrame(() => {
el.scrollTop = el.scrollHeight + Number(scrollAt);
});
}
this.childEleRef && this.childEleRef(el);
}
render() {
let {
onClick,
children,
isScrollAttribute,
dataId,
eleRef,
customClass = '',
htmlId,
a11y
} = this.props;
let {
isScroll
} = this.state;
let {
role
} = a11y;
return /*#__PURE__*/React.createElement(Container, {
className: `${customClass}`,
isScrollAttribute: isScrollAttribute,
onClick: onClick,
dataId: dataId,
eleRef: eleRef
}, React.Children.map(children, child => {
if (!child) {
return child;
}
if (child.type === CardHeader || this.props.childTypes && child.type === this.props.childTypes.cardHeader) {
return /*#__PURE__*/React.cloneElement(child, {
isScroll
});
} else if (child.type === CardContent || this.props.childTypes && child.type === this.props.childTypes.cardContent) {
this.childEleRef = child.props.eleRef;
return /*#__PURE__*/React.createElement(Box, {
id: htmlId,
role: role,
flexible: true,
scroll: child.props.scroll,
preventParentScroll: child.props.preventParentScroll,
onScroll: this.onScroll,
eleRef: this.setScrollRef,
isScrollAttribute: child.props.isScrollAttribute,
dataId: child.props.dataId,
shrink: child.props.shrink,
className: child.props.customClass,
dataSelectorId: child.props.dataSelectorId
}, child.props.children);
}
return child;
}));
}
}
Card.propTypes = Card_propTypes;
Card.defaultProps = Card_defaultProps; // if (__DOCS__) {
// Card.docs = {
// componentGroup: 'Template',
// folderName: 'Style Guide',
// external: true,
// description: ' '
// };
// }
export class CardFooter extends Component {
render() {
let {
children,
dataId,
customClass,
dataSelectorId
} = this.props;
return /*#__PURE__*/React.createElement(Box, {
className: `${customClass}`,
dataId: dataId,
dataSelectorId: dataSelectorId
}, children);
}
}
CardFooter.propTypes = CardFooter_propTypes;
CardFooter.defaultProps = CardFooter_defaultProps;