diff --git a/.gitignore b/.gitignore
index 20d98978..01612b6a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
+node_modules
/node_modules
package-lock.json
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 46be123d..54cb3f44 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
### [@coreui/react](https://coreui.io/) changelog
+##### `v2.5.5`
+- fix(SidebarNav): perfect scrollbar issue on sidebar minimized / rtl
+- chore: dependencies update and config refactor
+
##### `v2.5.4`
- fix(SidebarNav): allow location object as navConfig item url parameter
diff --git a/css/scrollbar.css b/css/scrollbar.css
new file mode 100644
index 00000000..a9d3bc40
--- /dev/null
+++ b/css/scrollbar.css
@@ -0,0 +1,18 @@
+/* rtl fix */
+.ps__rtl .ps__rail-y {
+ left: 0px !important;
+ right: unset;
+}
+*[dir="rtl"] .ps__rail-y {
+ left: 0px !important;
+ right: unset;
+}
+
+.ps__rtl .ps__thumb-y {
+ left: 2px;
+ right: unset;
+}
+*[dir="rtl"] .ps__thumb-y {
+ left: 2px;
+ right: unset;
+}
diff --git a/nwb.config.js b/nwb.config.js
index 402187db..daf1fac2 100644
--- a/nwb.config.js
+++ b/nwb.config.js
@@ -5,7 +5,8 @@ module.exports = {
umd: {
global: 'CoreUIReact',
externals: {
- react: 'React'
+ react: 'React',
+ 'react-router': 'ReactRouter'
}
}
}
diff --git a/package.json b/package.json
index 899e6377..06e160ca 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@coreui/react",
- "version": "2.5.4",
+ "version": "2.5.5",
"description": "CoreUI React Bootstrap 4 components",
"license": "MIT",
"author": {
@@ -35,32 +35,32 @@
"lint": "eslint src"
},
"dependencies": {
- "@coreui/icons": "0.3.0",
"classnames": "^2.2.6",
- "core-js": "^2.6.9",
+ "core-js": "^2.6.11",
"prop-types": "^15.7.2",
"react-onclickout": "^2.0.8",
- "react-perfect-scrollbar": "^1.5.3",
- "reactstrap": "^8.0.1"
+ "react-perfect-scrollbar": "~1.5.8"
},
"peerDependencies": {
- "@coreui/coreui": "^2.1.12",
- "react": "^16.10.1",
- "react-router-dom": "^5.1.2"
+ "@coreui/coreui": "^2.1.16",
+ "react": "^16.12.0",
+ "react-router-dom": "^5.1.2",
+ "mutationobserver-shim": "^0.3.3"
},
"devDependencies": {
+ "@coreui/icons": "~0.3.0",
"babel-eslint": "^10.0.3",
- "enzyme": "^3.10.0",
- "enzyme-adapter-react-16": "^1.14.0",
+ "enzyme": "^3.11.0",
+ "enzyme-adapter-react-16": "^1.15.2",
"eslint": "^5.16.0",
- "eslint-plugin-import": "^2.18.2",
- "eslint-plugin-react": "^7.15.1",
+ "eslint-plugin-import": "^2.20.1",
+ "eslint-plugin-react": "^7.18.3",
"nwb": "^0.23.0",
- "react": "^16.10.1",
- "react-dom": "^16.10.1",
+ "react": "^16.12.0",
+ "react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
- "sinon": "^5.1.1",
- "webpack-dev-server": "^3.8.1"
+ "reactstrap": "^8.4.1",
+ "sinon": "^5.1.1"
},
"repository": {
"type": "git",
diff --git a/src/Shared/layout/layout.js b/src/Shared/layout/layout.js
index b5772169..48ad2338 100644
--- a/src/Shared/layout/layout.js
+++ b/src/Shared/layout/layout.js
@@ -10,24 +10,58 @@ class LayoutHelper {
}
static sidebarMinimize(force) {
- // return this.elClassList.toggle('sidebar-minimized', force);
return this.toggleClass('sidebar-minimized', force);
}
static brandMinimize(force) {
- // this.elClassList.toggle('brand-minimized', force);
this.toggleClass('brand-minimized', force);
}
- // sidebar perfect scrollbar
+ // sidebar perfect scrollbar ugly hack
static sidebarPSToggle(toggle) {
+
+ if (this.isOnMobile()) {
+ toggle = true
+ } else {
+ const isSidebarMinimized = document.body.classList.contains('sidebar-minimized') || false
+ toggle = !isSidebarMinimized
+ }
+
+ const ps = { y: { rail: {}, thumb: {} } };
+ const isRtl = getComputedStyle(document.documentElement).direction === 'rtl'
const sidebar = document.querySelector('.sidebar-nav');
+ ps.y.rail.on = document.querySelector('.sidebar-nav .ps__rail-y');
+ ps.y.rail.off = document.querySelector('.sidebar-nav .ps__rail-y-off');
+ ps.y.thumb.on = document.querySelector('.sidebar-nav .ps__thumb-y');
+ ps.y.thumb.off = document.querySelector('.sidebar-nav .ps__thumb-y-off');
if (sidebar) {
if (toggle) {
sidebar.classList.add('ps');
sidebar.classList.add('ps-container');
sidebar.classList.add('ps--active-y');
+ if (ps.y.rail.off) {
+ ps.y.rail.off.classList.add('ps__rail-y');
+ ps.y.rail.off.removeAttribute('style');
+ ps.y.rail.off.style.left = isRtl ? '0px' : 'unset';
+ ps.y.rail.off.style.right = isRtl ? 'unset' : '0px';
+ ps.y.rail.off.classList.remove('ps__rail-y-off');
+ }
+ if (ps.y.thumb.off) {
+ ps.y.thumb.off.removeAttribute('style');
+ ps.y.thumb.off.classList.add('ps__thumb-y');
+ ps.y.thumb.off.classList.remove('ps__thumb-y-off');
+ }
} else {
+ if (ps.y.rail.on) {
+ ps.y.rail.on.classList.add('ps__rail-y-off');
+ ps.y.rail.on.removeAttribute('style');
+ ps.y.rail.on.classList.remove('ps__rail-y');
+ }
+ if (ps.y.thumb.on) {
+ ps.y.thumb.on.classList.add('ps__thumb-y-off');
+ ps.y.thumb.on.removeAttribute('style');
+ ps.y.thumb.on.classList.remove('ps__thumb-y');
+ }
sidebar.classList.remove('ps');
sidebar.classList.remove('ps-container');
sidebar.classList.remove('ps--active-y');
@@ -46,6 +80,23 @@ class LayoutHelper {
}
return this.elClassList.contains(className);
}
+
+ static isOnMobile() {
+ let onMobile = false;
+ try {
+ const minimizerElement = document.querySelector('.sidebar-minimizer');
+ if (minimizerElement) {
+ onMobile = getComputedStyle(minimizerElement).getPropertyValue('display') === 'none';
+ } else {
+ const sidebarElement = document.querySelector('.sidebar .sidebar-nav');
+ sidebarElement && (onMobile = getComputedStyle(sidebarElement).getPropertyValue('overflow-y') === 'auto');
+ }
+ } catch (ignore) {
+ // eslint-disable-next-line
+ console.warn('CoreUI isOnMobile failed to getComputedStyle', ignore)
+ }
+ return onMobile
+ }
}
export default LayoutHelper;
diff --git a/src/SidebarNav2.js b/src/SidebarNav2.js
index b839f8d6..9ae699e4 100644
--- a/src/SidebarNav2.js
+++ b/src/SidebarNav2.js
@@ -4,6 +4,9 @@ import classNames from 'classnames';
import PropTypes from 'prop-types';
import PerfectScrollbar from 'react-perfect-scrollbar';
import 'react-perfect-scrollbar/dist/css/styles.css';
+import '../css/scrollbar.css';
+
+import LayoutHelper from './Shared/layout/layout'
const propTypes = {
children: PropTypes.node,
@@ -39,17 +42,26 @@ class AppSidebarNav2 extends Component {
this.handleClick = this.handleClick.bind(this);
this.activeRoute = this.activeRoute.bind(this);
this.hideMobile = this.hideMobile.bind(this);
+
+ this.changes = null;
+ this.state = { sidebarMinimized: false }
}
+ _scrollBarRef = null;
+
handleClick(e) {
e.preventDefault();
e.currentTarget.parentElement.classList.toggle('open');
}
- activeRoute(routeName, props) {
+ isActiveRoute(routeName, props) {
return props.location.pathname.indexOf(routeName) > -1
- ? 'nav-item nav-dropdown open'
- : 'nav-item nav-dropdown';
+ }
+
+ activeRoute(routeName, props) {
+ return this.isActiveRoute(routeName, props) ?
+ 'nav-item nav-dropdown open' :
+ 'nav-item nav-dropdown';
}
hideMobile() {
@@ -148,6 +160,7 @@ class AppSidebarNav2 extends Component {
// nav link
navLink(item, key, classes) {
+ const ref = React.createRef();
const url = item.url || '';
const itemIcon =
const itemBadge = this.navBadge(item.badge)
@@ -171,7 +184,7 @@ class AppSidebarNav2 extends Component {
{itemIcon}{item.name}{itemBadge}
:
-
+ this.hideMobile(ref)} ref={ref} {...attributes}>
{itemIcon}{item.name}{itemBadge}
}
@@ -200,6 +213,45 @@ class AppSidebarNav2 extends Component {
return link.substring(0, 4) === 'http';
}
+ observeDomMutations() {
+ if (window.MutationObserver) {
+
+ // eslint-disable-next-line
+ this.changes = new MutationObserver((mutations) => {
+
+ const isSidebarMinimized = document.body.classList.contains('sidebar-minimized') || false
+ this.setState({ sidebarMinimized: isSidebarMinimized })
+
+ LayoutHelper.sidebarPSToggle(!isSidebarMinimized)
+
+ });
+ const element = document.body;
+ this.changes.observe(element, {
+ attributes: true,
+ attributeFilter: ['class']
+ });
+ }
+ window.addEventListener('resize', this.onResize);
+ }
+
+ onResize() {
+ LayoutHelper.sidebarPSToggle(true)
+ }
+
+ componentDidMount() {
+ this.observeDomMutations()
+ }
+
+ componentWillUnmount() {
+ try {
+ this.changes.disconnect()
+ window.removeEventListener('resize', this.onResize);
+ } catch (ignore) {
+ // eslint-disable-next-line
+ console.warn('CoreUI SidebarNav failed to disconnect from MutationObserver', ignore)
+ }
+ }
+
render() {
const { className, children, navConfig, ...attributes } = this.props;
@@ -208,18 +260,17 @@ class AppSidebarNav2 extends Component {
delete attributes.Tag
delete attributes.router
- const navClasses = classNames(className, 'sidebar-nav');
+ const navClasses = classNames(className, 'sidebar-nav')
- // ToDo: find better rtl fix
- const isRtl = getComputedStyle(document.documentElement).direction === 'rtl'
+ const options = Object.assign({}, { suppressScrollX: true, suppressScrollY: this.state.sidebarMinimized })
// sidebar-nav root
return (
-
-
-
+ { this._scrollBarRef = ref; }} >
+
+
);
}
}