From 48c5de8df254af52099b3763c96a0def39b09853 Mon Sep 17 00:00:00 2001
From: joshwooding <12938082+joshwooding@users.noreply.github.com>
Date: Fri, 26 Jun 2020 01:19:35 +0100
Subject: [PATCH] Use #20147 and modify slightly
---
.../material-ui-lab/src/TreeItem/TreeItem.js | 3 +-
.../src/TreeItem/TreeItem.test.js | 35 ++++++++++---------
.../material-ui-lab/src/TreeView/TreeView.js | 8 +++--
.../src/TreeView/descendants.js | 4 +++
4 files changed, 30 insertions(+), 20 deletions(-)
diff --git a/packages/material-ui-lab/src/TreeItem/TreeItem.js b/packages/material-ui-lab/src/TreeItem/TreeItem.js
index ea966ae11996b1..b857b6551d7e63 100644
--- a/packages/material-ui-lab/src/TreeItem/TreeItem.js
+++ b/packages/material-ui-lab/src/TreeItem/TreeItem.js
@@ -347,6 +347,7 @@ const TreeItem = React.forwardRef(function TreeItem(props, ref) {
id: nodeId,
index,
parentId,
+ expandable,
});
return () => {
@@ -355,7 +356,7 @@ const TreeItem = React.forwardRef(function TreeItem(props, ref) {
}
return undefined;
- }, [registerNode, unregisterNode, parentId, index, nodeId]);
+ }, [registerNode, unregisterNode, parentId, index, nodeId, expandable]);
React.useEffect(() => {
if (mapFirstChar && label) {
diff --git a/packages/material-ui-lab/src/TreeItem/TreeItem.test.js b/packages/material-ui-lab/src/TreeItem/TreeItem.test.js
index 04b2a712c666cd..347c24231fb0f2 100644
--- a/packages/material-ui-lab/src/TreeItem/TreeItem.test.js
+++ b/packages/material-ui-lab/src/TreeItem/TreeItem.test.js
@@ -837,8 +837,9 @@ describe('', () => {
describe('asterisk key interaction', () => {
it('expands all siblings that are at the same level as the current node', () => {
+ const toggleSpy = spy();
const { getByTestId } = render(
-
+
@@ -862,6 +863,8 @@ describe('', () => {
fireEvent.keyDown(getByTestId('one'), { key: '*' });
+ expect(toggleSpy.args[0][1]).to.have.length(3);
+
expect(getByTestId('one')).to.have.attribute('aria-expanded', 'true');
expect(getByTestId('three')).to.have.attribute('aria-expanded', 'true');
expect(getByTestId('five')).to.have.attribute('aria-expanded', 'true');
@@ -989,27 +992,27 @@ describe('', () => {
fireEvent.keyDown(getByTestId('three'), { key: 'ArrowDown', shiftKey: true });
expect(getByTestId('four')).toHaveFocus();
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(2);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(2);
fireEvent.keyDown(getByTestId('four'), { key: 'ArrowDown', shiftKey: true });
expect(getByTestId('three')).to.have.attribute('aria-selected', 'true');
expect(getByTestId('four')).to.have.attribute('aria-selected', 'true');
expect(getByTestId('five')).to.have.attribute('aria-selected', 'true');
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(3);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(3);
fireEvent.keyDown(getByTestId('five'), { key: 'ArrowUp', shiftKey: true });
expect(getByTestId('four')).toHaveFocus();
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(2);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(2);
fireEvent.keyDown(getByTestId('four'), { key: 'ArrowUp', shiftKey: true });
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(1);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(1);
fireEvent.keyDown(getByTestId('three'), { key: 'ArrowUp', shiftKey: true });
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(2);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(2);
fireEvent.keyDown(getByTestId('two'), { key: 'ArrowUp', shiftKey: true });
@@ -1018,7 +1021,7 @@ describe('', () => {
expect(getByTestId('three')).to.have.attribute('aria-selected', 'true');
expect(getByTestId('four')).to.have.attribute('aria-selected', 'false');
expect(getByTestId('five')).to.have.attribute('aria-selected', 'false');
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(3);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(3);
});
specify('keyboard arrow does not select when selectionDisabled', () => {
@@ -1036,11 +1039,11 @@ describe('', () => {
fireEvent.keyDown(getByTestId('three'), { key: 'ArrowDown', shiftKey: true });
expect(getByTestId('four')).toHaveFocus();
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0);
fireEvent.keyDown(getByTestId('four'), { key: 'ArrowUp', shiftKey: true });
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0);
});
specify('keyboard arrow merge', () => {
@@ -1066,12 +1069,12 @@ describe('', () => {
fireEvent.keyDown(getByTestId('four'), { key: 'ArrowUp', shiftKey: true });
fireEvent.keyDown(getByTestId('three'), { key: 'ArrowUp', shiftKey: true });
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(5);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(5);
fireEvent.keyDown(getByTestId('two'), { key: 'ArrowDown', shiftKey: true });
fireEvent.keyDown(getByTestId('three'), { key: 'ArrowDown', shiftKey: true });
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(3);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(3);
});
specify('keyboard space', () => {
@@ -1178,11 +1181,11 @@ describe('', () => {
getByTestId('five').focus();
fireEvent.keyDown(getByTestId('five'), { key: 'End', shiftKey: true, ctrlKey: true });
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0);
fireEvent.keyDown(getByTestId('nine'), { key: 'Home', shiftKey: true, ctrlKey: true });
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0);
});
specify('mouse', () => {
@@ -1236,7 +1239,7 @@ describe('', () => {
fireEvent.click(getByText('five'));
fireEvent.click(getByText('nine'), { shiftKey: true });
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0);
});
});
@@ -1317,7 +1320,7 @@ describe('', () => {
getByTestId('one').focus();
fireEvent.keyDown(getByTestId('one'), { key: 'a', ctrlKey: true });
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(5);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(5);
});
specify('ctrl + a does not select all when disableSelection', () => {
@@ -1334,7 +1337,7 @@ describe('', () => {
getByTestId('one').focus();
fireEvent.keyDown(getByTestId('one'), { key: 'a', ctrlKey: true });
- expect(container.querySelectorAll('[aria-selected=true]').length).to.equal(0);
+ expect(container.querySelectorAll('[aria-selected=true]')).to.have.length(0);
});
});
});
diff --git a/packages/material-ui-lab/src/TreeView/TreeView.js b/packages/material-ui-lab/src/TreeView/TreeView.js
index 99773af868b86d..f0a72c2e7d3ff7 100644
--- a/packages/material-ui-lab/src/TreeView/TreeView.js
+++ b/packages/material-ui-lab/src/TreeView/TreeView.js
@@ -94,6 +94,8 @@ const TreeView = React.forwardRef(function TreeView(props, ref) {
[expanded],
);
+ const isExpandable = React.useCallback((id) => nodeMap.current[id]?.expandable, []);
+
const isSelected = React.useCallback(
(id) => (Array.isArray(selected) ? selected.indexOf(id) !== -1 : selected === id),
[selected],
@@ -315,7 +317,7 @@ const TreeView = React.forwardRef(function TreeView(props, ref) {
const map = nodeMap.current[id];
const siblings = getChildren(map.parentId);
- const diff = siblings.filter((child) => !isExpanded(child));
+ const diff = siblings.filter((child) => isExpandable(child) && !isExpanded(child));
const newExpanded = expanded.concat(diff);
@@ -495,9 +497,9 @@ const TreeView = React.forwardRef(function TreeView(props, ref) {
* Mapping Helpers
*/
const registerNode = React.useCallback((node) => {
- const { id, index, parentId } = node;
+ const { id, index, parentId, expandable } = node;
- nodeMap.current[id] = { id, index, parentId };
+ nodeMap.current[id] = { id, index, parentId, expandable };
}, []);
const getNodesToRemove = React.useCallback((id) => {
diff --git a/packages/material-ui-lab/src/TreeView/descendants.js b/packages/material-ui-lab/src/TreeView/descendants.js
index 1b106335abeeb7..872cfb123c170a 100644
--- a/packages/material-ui-lab/src/TreeView/descendants.js
+++ b/packages/material-ui-lab/src/TreeView/descendants.js
@@ -1,6 +1,10 @@
import * as React from 'react';
import PropTypes from 'prop-types';
+/** Credit: https://github.com/reach/reach-ui/blob/86a046f54d53b6420e392b3fa56dd991d9d4e458/packages/descendants/README.md
+ * Modified slightly to suit our purposes.
+ */
+
// To replace with .findIndex() once we stop IE 11 support.
function findIndex(array, comp) {
for (let i = 0; i < array.length; i += 1) {