@wix/design-system
Version:
@wix/design-system
141 lines • 5.51 kB
JavaScript
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { st, classes } from './Accordion.st.css.js';
import AccordionItem from './components/AccordionItem';
import { horizontalPaddings, skins } from './constants';
import SectionHeader from '../SectionHeader';
export class Accordion extends PureComponent {
constructor(props) {
super(props);
this._findOpenIndexes = (items = [], initial = false) => {
return items
.map((item, index) => (initial && item.initiallyOpen) || item.open ? index : null)
.filter(index => index !== null)
.flatMap(index => (!!index || index === 0 ? [index] : []));
};
this._compareOpenItems = (currentItems = [], prevItems = []) => {
if (prevItems.length !== currentItems.length) {
return false;
}
for (let i = 0; i < prevItems.length; i++) {
if (prevItems[i].open !== currentItems[i].open) {
return false;
}
}
return true;
};
this.componentDidUpdate = (prevProps) => {
if (!this._compareOpenItems(this.props.items, prevProps.items)) {
this.setState({
openIndexes: this._findOpenIndexes(this.props.items),
});
}
};
this._toggle = (index) => () => this.setState(({ openIndexes }) => ({
openIndexes: openIndexes.includes(index)
? openIndexes.filter(i => i !== index)
: this.props.multiple
? [...openIndexes, index]
: [index],
}));
this.state = {
openIndexes: this._findOpenIndexes(this.props.items, true),
};
}
render() {
const { openIndexes } = this.state;
const { dataHook, items, skin, hideShadow, size, horizontalPadding, contentPadding, transitionSpeed, onAnimationEnter, onAnimationExit, titleSize, } = this.props;
return (React.createElement("div", { "data-hook": dataHook, className: classes.accordion, "data-transition-speed": transitionSpeed, "data-horizontal-padding": horizontalPadding, "data-content-padding": contentPadding, "data-skin": skin }, items?.map((item, index, allItems) => {
const uncontrolledProps = {
onToggle: this._toggle(index),
open: openIndexes.includes(index),
onAnimationEnter,
onAnimationExit,
};
const last = index === allItems.length - 1;
const internalProps = {
className: st(classes.item, { last }),
key: item.key || index,
skin,
hideShadow,
size,
horizontalPadding,
contentPadding,
last,
transitionSpeed,
titleSize,
};
if (typeof item.render === 'function') {
return item.render(uncontrolledProps, internalProps);
}
else {
return (React.createElement(AccordionItem, { ...uncontrolledProps, ...item, ...internalProps }));
}
})));
}
}
Accordion.displayName = 'Accordion';
Accordion.propTypes = {
dataHook: PropTypes.string,
multiple: PropTypes.bool,
skin: PropTypes.oneOf(['standard', 'light', 'neutral']),
hideShadow: PropTypes.bool,
size: PropTypes.oneOf(['tiny', 'small', 'medium', 'large']),
horizontalPadding: PropTypes.oneOf([
'none',
'tiny',
'small',
'medium',
'large',
]),
contentPadding: PropTypes.oneOf(['none']),
titleSize: PropTypes.oneOf(['small', 'medium']),
transitionSpeed: PropTypes.oneOf(['slow', 'medium', 'fast']),
onAnimationEnter: PropTypes.func,
onAnimationExit: PropTypes.func,
items: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.shape({
render: PropTypes.func,
})),
PropTypes.arrayOf(PropTypes.shape({
title: PropTypes.node,
subtitle: PropTypes.node,
icon: PropTypes.node,
children: PropTypes.node,
expandLabel: PropTypes.node,
collapseLabel: PropTypes.node,
showLabel: PropTypes.oneOf(['hover', 'always']),
buttonType: PropTypes.oneOf(['textButton', 'button', 'node']),
disabled: PropTypes.bool,
onToggle: PropTypes.func,
onMouseEnter: PropTypes.func,
onMouseleave: PropTypes.func,
open: PropTypes.bool,
initiallyOpen: PropTypes.bool,
})),
]),
};
Accordion.defaultProps = {
items: [],
multiple: false,
skin: skins.standard,
horizontalPadding: horizontalPaddings.large,
hideShadow: false,
transitionSpeed: 'medium',
size: 'small',
titleSize: 'medium',
};
export const accordionItemBuilder = (item) => {
return {
...item,
render: (uncontrolledProps, internalProps) => React.createElement(AccordionItem, { ...uncontrolledProps, ...item, ...internalProps }),
};
};
export const accordionSectionItemBuilder = (item) => {
return {
...item,
render: (_, internalProps) => (React.createElement(SectionHeader, { title: item.title ?? internalProps.title, skin: "neutral" })),
};
};
export default Accordion;
//# sourceMappingURL=Accordion.js.map