@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
195 lines (169 loc) • 6.57 kB
JavaScript
/* eslint-disable */
// QUestions to be discussed
//1) mutation.type === 'characterData' needed ???
// 2) debounce Mutation observer and resize observer
import React from 'react';
import PropTypes from 'prop-types';
import ResizeObserver from "./ResizeObserver";
import { getElementSpace, debounce } from "../utils/Common";
export default class ResizeComponent extends React.Component {
constructor(props) {
super(props);
this.noSpaceForChildren = false;
this.childrenCurrentList = [];
this.widthCheck = debounce(this.widthCheck.bind(this), 10); // this.widthCheck = this.widthCheck.bind(this);
this.onResize = this.onResize.bind(this);
this.onResizeMutation = this.onResizeMutation.bind(this);
this.tabsObserver = new ResizeObserver(this.onResize);
this.tabObserver = new MutationObserver(this.onResizeMutation);
this.reset = this.reset.bind(this);
this.constructChildren = this.constructChildren.bind(this);
this.querySelector = this.querySelector.bind(this);
}
querySelector() {
if (this.props.wrapperDivRef && this.props.wrapperDivRef.current) {
return this.props.wrapperDivRef.current.querySelectorAll('[data-responsive="true"]');
} else {
return [];
}
}
onResizeMutation(mutations) {
// console.log(mutations);
let {
childrenList
} = this.props;
for (const mutation of mutations) {
if (mutation.type === 'childList') {
if (mutation.addedNodes.length) {
let newAdded = false;
mutation.addedNodes.forEach(mut => {
// Here we can listen for icon nodes. Confirm with bk
if (mut.attributes && mut.attributes['data-responsive'] && (childrenList.length !== this.querySelector().length || this.childrenCurrentList.length !== this.querySelector().length)) {
newAdded = true;
}
});
if (newAdded) {
//console.log('A child node has been added ', mutation);
this.onResize();
}
} else if (mutation.removedNodes.length) {// ?? removed nodes ku check pannanum ah ??
// console.log('A child node has been removed ', mutation);
}
} else if (mutation.type === 'attributes') {//console.log('The ' + mutation.attributeName + ' attribute was modified.', mutation);
} else if (mutation.type === 'characterData') {// To Call While Changing InnerText, Remove Below line If Required. But It might affect Performance.
// this.onResize();
}
} // mutations.forEach(mutation => {
// if (mutation.target === foo &&
// mutation.attributeName === 'style' &&
// oldWidth !== foo.style.width) {
// foo.textContent = 'Width changed from ' +
// oldWidth + ' to ' + foo.style.width;
// oldWidth = foo.style.width;
// }
// });
}
componentDidMount() {
if (this.props.wrapperDivRef && this.props.wrapperDivRef.current) {
this.tabsObserver.observe(this.props.wrapperDivRef.current);
this.tabObserver.observe(this.props.wrapperDivRef.current, {
characterData: true,
attributes: true,
childList: true,
subtree: true,
attributeFilter: ['data-responsive']
});
}
}
componentWillUnmount() {
this.reset();
}
reset() {
this.childrenCurrentList = [];
this.tabsObserver.disconnect();
this.tabObserver && this.tabObserver.disconnect();
}
componentDidUpdate(prevProps) {
if (this.childrenCurrentList.length === 0) {
this.childrenCurrentList = this.querySelector();
this.widthCheck();
}
if (this.props.resizeId !== prevProps.resizeId) {
// Completely reset the observers and set new observer if id is changed
this.reset();
if (this.props.wrapperDivRef && this.props.wrapperDivRef.current) {
this.tabsObserver.observe(this.props.wrapperDivRef.current);
this.tabObserver.observe(this.props.wrapperDivRef.current, {
characterData: true,
attributes: true,
childList: true,
subtree: true,
attributeFilter: ['data-responsive']
});
}
}
}
onResize() {
// if (this.childrenCurrentList.length !== 0) {
this.childrenCurrentList = [];
this.constructChildren(0, false); //}
} // shouldComponentUpdate() {
// return this.childrenCurrentList.length === 0
// }
widthCheck() {
let wrapperDivRef = this.props.wrapperDivRef.current;
let moreDivRef = this.props.moreDivRef.current;
if (wrapperDivRef && this.childrenCurrentList.length > 0) {
const childrenWidthList = this.childrenCurrentList; // this.childrenCurrentList = childrenWidthList;
const moreWidth = getElementSpace(moreDivRef).neededSpace; //console.log(moreWidth,'moreWidth');
let totalWidth = getElementSpace(wrapperDivRef).availableInsideSpace - moreWidth;
let _childrenTotalWidth = 0;
let dataCount = 0;
this.noSpaceForChildren = false;
if (totalWidth <= moreWidth) {
this.noSpaceForChildren = true;
} else {
for (let i = 0; i < childrenWidthList.length; i++) {
let currentWidth = getElementSpace(childrenWidthList[i]).neededSpace;
_childrenTotalWidth += currentWidth; // console.log(_childrenTotalWidth, currentWidth, totalWidth)
if (i === childrenWidthList.length - 1 && moreWidth >= currentWidth) {
totalWidth += moreWidth;
}
if (totalWidth <= _childrenTotalWidth) {
dataCount = i;
break;
}
}
}
this.constructChildren(dataCount, true);
} else {
this.constructChildren(0, false);
}
}
constructChildren(dataCount = 0, responsive) {
const {
childrenList,
getData
} = this.props; // If the data count is zero we assume that we can render all the items - data count will be zero only when we want to calculate the whole list width
dataCount = dataCount || childrenList && childrenList.length;
getData({
responsiveHook: responsive,
validListCount: this.noSpaceForChildren ? 0 : dataCount
});
}
render() {
return /*#__PURE__*/React.createElement(React.Fragment, null, this.props.children);
}
}
ResizeComponent.propTypes = {
children: PropTypes.node,
getData: PropTypes.func,
resizeId: PropTypes.number,
childrenList: PropTypes.array,
wrapperDivRef: PropTypes.any,
moreDivRef: PropTypes.any
};
ResizeComponent.defaultProps = {
getData: () => {},
resizeId: null
};