@the-control-group/ui
Advanced tools
Comparing version 1.5.0 to 1.6.0
@@ -9,20 +9,70 @@ /** | ||
import Div from '../Div/Div'; | ||
import Grid from '../Grid/Grid'; | ||
import FlexRow from '../FlexRow/FlexRow'; | ||
import Flex from '../Flex/Flex'; | ||
import Button from '../Button/Button'; | ||
import { isMobile } from '../../util/helpers'; | ||
const AccordionCaret = ({ white, up }) => ( | ||
<object className={classNames('ui-accordion-caret', { white, up })}> | ||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 26 26" preserveAspectRatio="xMaxYMax meet"> | ||
<defs> | ||
<style> | ||
{` | ||
.caret-cls-1 { fill: #000; } | ||
.caret-border { stroke: #000; } | ||
`} | ||
</style> | ||
</defs> | ||
<circle className="caret-border" cx="8" cy="8" r="12" strokeWidth="2" fill="none"/> | ||
<path className="caret-cls-1" d="M14.133,0,16,1.79,8,9.459,0,1.79,1.867,0,8,5.88Z" transform="translate(0 4) rotate(0)"/> | ||
</svg> | ||
</object> | ||
); | ||
AccordionCaret.propTypes = { | ||
white: PropTypes.bool, | ||
up: PropTypes.bool | ||
}; | ||
class Accordion extends Component { | ||
static propTypes = { | ||
children: PropTypes.node.isRequired, | ||
title: PropTypes.node.isRequired, | ||
title: (props, propName, componentName, ...args) => { | ||
if(!props.title && !props.header) { | ||
return new Error(`One of props 'title' or 'header' was not specified in '${componentName}'`); | ||
} | ||
if(props.title) return new Error('`title` is deprecated; use `header` instead'); | ||
return PropTypes.node(props, propName, componentName, ...args); | ||
}, | ||
header: (props, propName, componentName, ...args) => { | ||
if(!props.title && !props.header) { | ||
return new Error(`One of props 'title' or 'header' was not specified in '${componentName}'`); | ||
} | ||
return PropTypes.node(props, propName, componentName, ...args); | ||
}, | ||
className: PropTypes.string, | ||
notificationStyle: PropTypes.bool, | ||
defaultExpanded: PropTypes.bool, | ||
notificationStyle: PropTypes.bool // this is used to style accordion as a notification | ||
toggleTextShow: PropTypes.string, | ||
toggleTextHide: PropTypes.string, | ||
buttonStyleToggle: PropTypes.bool | ||
}; | ||
static defaultProps = { | ||
toggleTextShow: 'Show', | ||
toggleTextHide: 'Hide' | ||
} | ||
constructor(props) { | ||
super(props); | ||
this.accordionContent = React.createRef(); | ||
this.disableToggle = false; | ||
this.state = { | ||
showContent: this.props.defaultExpanded | ||
showContent: this.props.defaultExpanded, | ||
toggle: this.props.defaultExpanded ? 'hide' : 'show' | ||
}; | ||
@@ -34,44 +84,82 @@ | ||
toggleAccordion() { | ||
this.setState({ | ||
showContent: !this.state.showContent | ||
}); | ||
if(this.disableToggle) return; | ||
this.disableToggle = true; | ||
if(!this.state.showContent) { | ||
this.setState({ | ||
showContent: true, | ||
toggle: 'hide' | ||
}, () => { | ||
window.requestAnimationFrame(() => { | ||
const transitionDuration = Math.max(this.accordionContent.current.clientHeight * 2, 300); | ||
// Set fixed height (based on height of content) and set transition-duration for .ui-accordion-content-wrapper. | ||
// We need fixed height for CSS Transition to work and to animate slide down of accordion. | ||
this.accordionContent.current.parentNode.style.transitionDuration = `${transitionDuration}ms`; | ||
this.accordionContent.current.parentNode.style.height = `${this.accordionContent.current.clientHeight}px`; | ||
// Set auto height for .ui-accordion-content-wrapper after animation is complete. | ||
// We can't keep fixed height here because accordion may have other accordions inside of it and height of content may change. | ||
setTimeout(() => { | ||
this.disableToggle = false; | ||
this.accordionContent.current.parentNode.style.height = 'auto'; | ||
}, transitionDuration); | ||
}); | ||
}); | ||
} else { | ||
this.setState({ | ||
toggle: 'show' | ||
}); | ||
// Set height back to fixed for .ui-accordion-content-wrapper so we can animate slide up. | ||
this.accordionContent.current.parentNode.style.height = `${this.accordionContent.current.clientHeight}px`; | ||
// Set height and transition-duration for slide up animation. | ||
window.requestAnimationFrame(() => { | ||
this.accordionContent.current.parentNode.style.height = 0; | ||
// Remove content from DOM after animation is complete | ||
setTimeout(() => { | ||
this.setState({ | ||
showContent: false | ||
}); | ||
this.disableToggle = false; | ||
}, this.accordionContent.current.clientHeight * 2); | ||
}); | ||
} | ||
} | ||
render() { | ||
const { title, children, className, notificationStyle } = this.props, | ||
{ showContent } = this.state, | ||
itemWidths = showContent && !isMobile() && notificationStyle ? [3, 7, 2] : [10, 2], | ||
toggleText = showContent ? 'hide' : 'show', | ||
toggleIconClass = showContent ? 'arrow arrow-up' : 'arrow arrow-down'; | ||
const { title, header, children, className, notificationStyle, toggleTextShow, toggleTextHide, buttonStyleToggle } = this.props, | ||
{ showContent, toggle } = this.state, | ||
toggleText = toggle === 'show' ? toggleTextShow : toggleTextHide; | ||
const combinedClasses = classNames( | ||
'ui-accordion', | ||
className, | ||
{ | ||
'notification-style': this.props.notificationStyle | ||
} | ||
); | ||
return ( | ||
<div className={classNames('ui-accordion', className, {'notification-style': notificationStyle})}> | ||
<div className="ui-accordion-header"> | ||
<FlexRow breakMedium={buttonStyleToggle}> | ||
<Flex> | ||
{header || <div className="title">{title}</div>} | ||
</Flex> | ||
<Flex right={!buttonStyleToggle || !isMobile()} max="200"> | ||
{buttonStyleToggle | ||
? <Button className="ui-accordion-toggle button-toggle" onClick={this.toggleAccordion} mini ref={this.accordionToggle}> | ||
<span>{toggleText}</span> | ||
<AccordionCaret white up={toggle === 'hide'} /> | ||
</Button> | ||
return ( | ||
<div className={combinedClasses}> | ||
<Grid | ||
gutter="xx-small" | ||
itemWidths={itemWidths} | ||
> | ||
<Div className="title"> | ||
{title} | ||
</Div> | ||
{showContent && !isMobile() && notificationStyle && | ||
<Div>{children}</Div> | ||
} | ||
<Div onClick={this.toggleAccordion} right className="ui-accordion-toggle"> | ||
<Grid gutter="xx-small" itemWidths={[10, 2]}> | ||
<Div>{toggleText}</Div> | ||
<Div><Div className={toggleIconClass}>^</Div></Div> | ||
</Grid> | ||
</Div> | ||
</Grid> | ||
{showContent && (isMobile() || !notificationStyle) && | ||
<div className="accordion-content">{children}</div> | ||
} | ||
: <div className="ui-accordion-toggle" onClick={this.toggleAccordion} ref={this.accordionToggle}> | ||
<span>{toggleText}</span> | ||
<AccordionCaret up={toggle === 'hide'} /> | ||
</div> | ||
} | ||
</Flex> | ||
</FlexRow> | ||
</div> | ||
<div className="ui-accordion-content-wrapper"> | ||
<div className="ui-accordion-content" ref={this.accordionContent}> | ||
{showContent && children} | ||
</div> | ||
</div> | ||
</div> | ||
@@ -78,0 +166,0 @@ ); |
@@ -98,4 +98,4 @@ /** | ||
attributeValues.forEach(v => { | ||
// If the "value" attribute is present, it should be added regardless of truthiness | ||
if(other[v] || (v === 'value' && other.hasOwnProperty('value'))) { | ||
// If the "value" or "checked" attribute is present, it should be added regardless of truthiness | ||
if(other[v] || (v === 'value' && other.hasOwnProperty('value')) || (v === 'checked' && other.hasOwnProperty('checked'))) { | ||
attributes[v] = other[v]; | ||
@@ -102,0 +102,0 @@ } |
@@ -43,5 +43,6 @@ import React from 'react'; | ||
max: numberLikeProp, | ||
fixed: numberLikeProp | ||
fixed: numberLikeProp, | ||
centerY: PropTypes.bool | ||
}; | ||
export default Flex; |
@@ -6,2 +6,3 @@ export { default as Grid } from './elements/Grid/Grid'; | ||
export { default as Button } from './elements/Button/Button'; | ||
export { default as Toggle } from './elements/Toggle/Toggle'; | ||
export { default as Input } from './elements/Input/Input'; | ||
@@ -8,0 +9,0 @@ export { default as Text } from './elements/Text/Text'; |
{ | ||
"name": "@the-control-group/ui", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"description": "UI kit based on ReactJS for TCG projects", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
70233
43
1455