IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.5KB

  1. import { h, Component } from 'preact';
  2. class WBAccordion extends Component {
  3. constructor(...args) {
  4. super(...args);
  5. this.setupIds();
  6. }
  7. setupIds() {
  8. this.state.domId = 'accordion-' + uuid.v4();
  9. const { names } = this.props;
  10. const { state } = this;
  11. state.headerDomIds = names.map(() => ('accordion-' + uuid.v4()));
  12. state.collapseDomIds = names.map(() => ('accordion-' + uuid.v4()));
  13. state.collapseClass = Array(names.length).fill('collapse');
  14. state.ariaExpanded = Array(names.length).fill(false);
  15. state.buttonClass = Array(names.length).fill('btn btn-link collapsed');
  16. state.collapseElements = null;
  17. }
  18. componentWillReceiveProps(nextProps) {
  19. if (JSON.stringify(nextProps.names) === JSON.stringify(this.props.names))
  20. return;
  21. this.props = nextProps;
  22. this.setupIds();
  23. }
  24. toggle(idx) {
  25. const { ariaExpanded, collapseClass, buttonClass } = this.state;
  26. const isOpen = ariaExpanded[idx];
  27. for (let i = 0; i < ariaExpanded.length; i++) {
  28. ariaExpanded[i] = false;
  29. collapseClass[i] = 'collapse';
  30. buttonClass[i] = 'btn btn-link collapsed';
  31. }
  32. if (!isOpen) {
  33. ariaExpanded[idx] = true;
  34. collapseClass[idx] = 'collapse show';
  35. buttonClass[idx] = 'btn btn-link';
  36. }
  37. this.setState({ ariaExpanded, collapseClass, buttonClass });
  38. }
  39. render({ children, names, extraHeaderUi, cardHeaderClass }, { domId, headerDomIds,
  40. collapseDomIds, collapseClass, ariaExpanded, buttonClass }) {
  41. return (
  42. <div class="accordion" id={ domId }>
  43. { children.map((_, i) => (
  44. <div class="card">
  45. <div class={ cardHeaderClass } id={ headerDomIds[i] }>
  46. <h2 class="mb-0">
  47. <button class={ buttonClass[i] } type="button"
  48. aria-expanded={ ariaExpanded[i] } aria-controls={ collapseDomIds[i] }
  49. onclick={ () => this.toggle(i) }>
  50. { names[i] }
  51. </button>
  52. { extraHeaderUi[i] }
  53. </h2>
  54. </div>
  55. <div id={ collapseDomIds[i] } class={ collapseClass[i] }
  56. aria-labelledby={ headerDomIds[i] }>
  57. <div class="card-body">
  58. { children[i] }
  59. </div>
  60. </div>
  61. </div>
  62. )) }
  63. </div>
  64. );
  65. }
  66. };
  67. WBAccordion.defaultProps = {
  68. cardHeaderClass: 'card-header',
  69. extraHeaderUi: []
  70. };
  71. export default WBAccordion;