diff --git a/CHANGELOG.md b/CHANGELOG.md index dcd2772..acff383 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - use direction:rtl instead of row-reverse +- fix submenu positioning on sidebar collapsed using popperjs and resize-observer-polyfill for resize event listener ## [0.3.0] - 2020-05-11 diff --git a/package.json b/package.json index e381947..bd49fb1 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,9 @@ ] }, "dependencies": { + "@popperjs/core": "^2.4.0", "classnames": "^2.2.6", - "react-slidedown": "^2.4.5" + "react-slidedown": "^2.4.5", + "resize-observer-polyfill": "^1.5.1" } } diff --git a/rollup.config.js b/rollup.config.js index 59a9b7d..8d54be9 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -39,4 +39,5 @@ export default { ], }), ], + external: ['react', 'react-dom', 'prop-types'], }; diff --git a/src/ProSidebar/Menu/Menu.tsx b/src/ProSidebar/Menu/Menu.tsx index 4fc8cbf..9c5f52f 100644 --- a/src/ProSidebar/Menu/Menu.tsx +++ b/src/ProSidebar/Menu/Menu.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react/no-array-index-key */ import React, { forwardRef, LegacyRef } from 'react'; import classNames from 'classnames'; @@ -5,7 +6,7 @@ export type IconShapeType = 'square' | 'round' | 'circle'; export interface Props { className?: string; - children?: React.ReactNode; + children?: any; iconShape?: IconShapeType; } @@ -23,7 +24,9 @@ const Menu: React.ForwardRefRenderFunction = ( [`shaped ${iconShape}`]: ['square', 'round', 'circle'].indexOf(iconShape) >= 0, })} > - + ); }; diff --git a/src/ProSidebar/Menu/SubMenu.tsx b/src/ProSidebar/Menu/SubMenu.tsx index 3517674..ee3a43c 100644 --- a/src/ProSidebar/Menu/SubMenu.tsx +++ b/src/ProSidebar/Menu/SubMenu.tsx @@ -1,6 +1,9 @@ -import React, { useState, forwardRef, LegacyRef } from 'react'; +import React, { useState, forwardRef, LegacyRef, useRef, useEffect, useContext } from 'react'; import classNames from 'classnames'; import SlideDown from 'react-slidedown'; +import { createPopper } from '@popperjs/core'; +import ResizeObserver from 'resize-observer-polyfill'; +import { SidebarContext } from '../ProSidebar'; export interface Props { className?: string; @@ -10,18 +13,67 @@ export interface Props { open?: boolean; prefix?: React.ReactNode; suffix?: React.ReactNode; + firstchild?: boolean; } const SubMenu: React.ForwardRefRenderFunction = ( - { children, icon, className, title, defaultOpen = false, open, prefix, suffix, ...rest }, + { + children, + icon, + className, + title, + defaultOpen = false, + open, + prefix, + suffix, + firstchild, + ...rest + }, ref, ) => { + let popperInstance; + const { collapsed, rtl } = useContext(SidebarContext); const [closed, setClosed] = useState(!defaultOpen); + const popperElRef = useRef(); + const referenceElement = useRef(); + const popperElement = useRef(); const handleToggleSubMenu = () => { setClosed(!closed); }; + useEffect(() => { + if (firstchild) { + if (popperInstance) popperInstance.destroy(); + + if (referenceElement.current && popperElement.current) { + popperInstance = createPopper(referenceElement.current, popperElement.current, { + placement: 'right', + strategy: 'fixed', + modifiers: [ + { + name: 'computeStyles', + options: { + adaptive: false, + }, + }, + ], + }); + } + + if (popperElRef.current) { + const ro = new ResizeObserver(() => { + if (popperInstance) { + popperInstance.update(); + } + }); + + ro.observe(popperElRef.current); + ro.observe(referenceElement.current); + } + } + }, [collapsed, rtl]); + const subMenuRef: LegacyRef = (ref as any) || React.createRef(); return ( @@ -33,6 +85,7 @@ const SubMenu: React.ForwardRefRenderFunction = ( >
= (
- -
    {children}
-
+ + {firstchild && collapsed ? ( +
+
+
    {children}
+
+
+ ) : ( + +
+
    {children}
+
+
+ )} ); }; diff --git a/src/ProSidebar/ProSidebar.tsx b/src/ProSidebar/ProSidebar.tsx index 08cda78..05248a3 100644 --- a/src/ProSidebar/ProSidebar.tsx +++ b/src/ProSidebar/ProSidebar.tsx @@ -1,4 +1,4 @@ -import React, { forwardRef, LegacyRef } from 'react'; +import React, { forwardRef, LegacyRef, createContext, useEffect, useState } from 'react'; import '../scss/styles.scss'; import classNames from 'classnames'; @@ -11,21 +11,44 @@ export interface Props { children?: React.ReactNode; } +export interface SidebarContextProps { + collapsed: boolean; + rtl: boolean; +} + +export const SidebarContext = createContext({ + collapsed: false, + rtl: false, +}); + const ProSidebar: React.ForwardRefRenderFunction = ( { children, className, width, collapsed, rtl, image, ...rest }, ref, ) => { + const [sidebarState, setSidebarState] = useState({ collapsed: false, rtl: false }); + const sidebarRef: LegacyRef = (ref as any) || React.createRef(); + + useEffect(() => { + setSidebarState({ ...sidebarState, collapsed }); + }, [collapsed]); + + useEffect(() => { + setSidebarState({ ...sidebarState, rtl }); + }, [rtl]); + return ( -
- {image ? sidebar background : null} -
{children}
-
+ +
+ {image ? sidebar background : null} +
{children}
+
+
); }; diff --git a/src/scss/partials/_menu.scss b/src/scss/partials/_menu.scss index 2af0a07..c03f4bc 100644 --- a/src/scss/partials/_menu.scss +++ b/src/scss/partials/_menu.scss @@ -254,12 +254,15 @@ position: fixed; left: $sidebar-collapsed-width; transform: translateY(-50px); - display: none !important; + visibility: hidden; width: 270px; + max-height: 100%; + overflow-y: auto; } &:hover { > .pro-inner-list-item { - display: block !important; + transition: transform 0.3s; + visibility: visible; } .pro-icon-wrapper { .pro-icon { diff --git a/yarn.lock b/yarn.lock index d41d255..112db78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -59,6 +59,11 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" +"@popperjs/core@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.4.0.tgz#0e1bdf8d021e7ea58affade33d9d607e11365915" + integrity sha512-NMrDy6EWh9TPdSRiHmHH2ye1v5U0gBD7pRYwSwJvomx7Bm4GG04vu63dYiVzebLOx2obPpJugew06xVP0Nk7hA== + "@rollup/plugin-commonjs@^11.1.0": version "11.1.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-11.1.0.tgz#60636c7a722f54b41e419e1709df05c7234557ef" @@ -3504,6 +3509,11 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== +resize-observer-polyfill@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"