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.

88 lines
2.7KB

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