GrowiSubNavigationSwitcher.jsx 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import React, { useState, useEffect, useCallback } from 'react';
  2. // import PropTypes from 'prop-types';
  3. import loggerFactory from '@alias/logger';
  4. import StickyEvents from 'sticky-events';
  5. import { debounce } from 'throttle-debounce';
  6. import GrowiSubNavigation from './GrowiSubNavigation';
  7. const logger = loggerFactory('growi:cli:GrowiSubNavigationSticky');
  8. /**
  9. * Subnavigation
  10. *
  11. * needs:
  12. * #grw-subnav-fixed-container element
  13. * #grw-subnav-sticky-trigger element
  14. *
  15. * @param {object} props
  16. */
  17. const GrowiSubNavigationSwitcher = (props) => {
  18. const [isVisible, setVisible] = useState(false);
  19. const resetWidth = useCallback(() => {
  20. const elem = document.getElementById('grw-subnav-fixed-container');
  21. if (elem == null || elem.parentNode == null) {
  22. return;
  23. }
  24. // get parent width
  25. const { clientWidth: width } = elem.parentNode;
  26. // update style
  27. elem.style.width = `${width}px`;
  28. }, []);
  29. // setup effect by resizing event
  30. useEffect(() => {
  31. const resizeHandler = debounce(100, resetWidth);
  32. window.addEventListener('resize', resizeHandler);
  33. // return clean up handler
  34. return () => {
  35. window.removeEventListener('resize', resizeHandler);
  36. };
  37. }, []);
  38. const stickyChangeHandler = useCallback((event) => {
  39. logger.debug('StickyEvents.CHANGE detected');
  40. setVisible(event.detail.isSticky);
  41. }, []);
  42. // setup effect by sticky event
  43. useEffect(() => {
  44. // sticky
  45. // See: https://github.com/ryanwalters/sticky-events
  46. const stickyEvents = new StickyEvents({ stickySelector: '#grw-subnav-sticky-trigger' });
  47. const { stickySelector } = stickyEvents;
  48. const elem = document.querySelector(stickySelector);
  49. elem.addEventListener(StickyEvents.CHANGE, stickyChangeHandler);
  50. // return clean up handler
  51. return () => {
  52. elem.removeEventListener(StickyEvents.CHANGE, stickyChangeHandler);
  53. };
  54. }, [stickyChangeHandler]);
  55. // update width
  56. useEffect(() => {
  57. resetWidth();
  58. });
  59. return (
  60. <div className={`grw-subnav-switcher ${isVisible ? '' : 'grw-subnav-switcher-hidden'}`}>
  61. <div id="grw-subnav-fixed-container" className="grw-subnav-fixed-container position-fixed">
  62. <GrowiSubNavigation isCompactMode />
  63. </div>
  64. </div>
  65. );
  66. };
  67. GrowiSubNavigationSwitcher.propTypes = {
  68. };
  69. export default GrowiSubNavigationSwitcher;