UNPKG

@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
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;