Skip to content

Commit d3762e8

Browse files
lukasbachlukasbachbot
andauthored
feat: call onFocusItem with first item if focused item is missing (#363) (#426)
* feat: call onFocusItem with first item if focused item is missing (#363) * v2.5.1-alpha.0 * chore: tidy up after prerelease * feat: fix invalid droptarget at bottom of tree (#363) --------- Co-authored-by: lukasbachbot <[email protected]>
1 parent 39572cb commit d3762e8

File tree

13 files changed

+111
-58
lines changed

13 files changed

+111
-58
lines changed

lerna-publish-summary.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[{"packageName":"react-complex-tree-autodemo","version":"2.5.0"},{"packageName":"react-complex-tree-blueprintjs-renderers","version":"2.5.0"},{"packageName":"react-complex-tree","version":"2.5.0"}]
1+
[{"packageName":"react-complex-tree-autodemo","version":"2.5.1-alpha.0"},{"packageName":"react-complex-tree-blueprintjs-renderers","version":"2.5.1-alpha.0"},{"packageName":"react-complex-tree","version":"2.5.1-alpha.0"}]

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"packages": ["packages/*"],
33
"npmClient": "yarn",
44
"useWorkspaces": true,
5-
"version": "2.5.0"
5+
"version": "2.5.1-alpha.0"
66
}

next-release-notes.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
<!--
2-
### Breaking Changes
3-
4-
### Features
5-
61
### Bug Fixes and Improvements
7-
8-
### Other Changes
9-
-->
2+
- If a tree environment renders without an item defined as focused in its `viewState` parameter, it will invoke the `onFocusItem`
3+
prop with the first item in the tree during its render. In the past, this was implicitly and silently set in the `viewState` prop,
4+
now this assignment is triggered explicitly with the handler call (#363)
5+
- Fixed a bug where an additional invalid drop target would be available at the bottom-most location when dragging via keyboard interactions (#363)

packages/autodemo/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-complex-tree-autodemo",
3-
"version": "2.5.0",
3+
"version": "2.5.1-alpha.0",
44
"main": "lib/index.js",
55
"types": "lib/index.d.ts",
66
"repository": {
@@ -23,10 +23,10 @@
2323
"@types/react-dom": "^18.0.7",
2424
"babel-jest": "^27.5.1",
2525
"babel-loader": "^9.1.0",
26-
"demodata": "^2.5.0",
26+
"demodata": "^2.5.1-alpha.0",
2727
"jest": "^26.6.3",
2828
"react": "^18.2.0",
29-
"react-complex-tree": "^2.5.0",
29+
"react-complex-tree": "^2.5.1-alpha.0",
3030
"react-dom": "^18.2.0",
3131
"react-test-renderer": "^18.2.0",
3232
"ts-node": "^10.7.0",

packages/blueprintjs-renderers/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-complex-tree-blueprintjs-renderers",
3-
"version": "2.5.0",
3+
"version": "2.5.1-alpha.0",
44
"main": "lib/index.js",
55
"types": "lib/index.d.ts",
66
"repository": {
@@ -26,10 +26,10 @@
2626
"@types/react-dom": "^18.0.7",
2727
"babel-jest": "^27.5.1",
2828
"babel-loader": "^9.1.0",
29-
"demodata": "^2.5.0",
29+
"demodata": "^2.5.1-alpha.0",
3030
"jest": "^26.6.3",
3131
"react": "^18.2.0",
32-
"react-complex-tree": "^2.5.0",
32+
"react-complex-tree": "^2.5.1-alpha.0",
3333
"react-dom": "^18.2.0",
3434
"react-test-renderer": "^18.2.0",
3535
"ts-node": "^10.7.0",

packages/core/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-complex-tree",
3-
"version": "2.5.0",
3+
"version": "2.5.1-alpha.0",
44
"main": "lib/cjs/index.js",
55
"module": "lib/esm/index.js",
66
"esnext": "lib/esnext/index.js",
@@ -35,7 +35,7 @@
3535
"babel-jest": "^27.5.1",
3636
"babel-loader": "^9.1.0",
3737
"cpy-cli": "^3.1.1",
38-
"demodata": "^2.5.0",
38+
"demodata": "^2.5.1-alpha.0",
3939
"jest": "^29.2.2",
4040
"jest-dom": "^4.0.0",
4141
"jest-environment-jsdom": "^29.2.2",

packages/core/src/controlledEnvironment/ControlledTreeEnvironment.tsx

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import { useContext } from 'react';
2+
import { useContext, useEffect } from 'react';
33
import {
44
ControlledTreeEnvironmentProps,
55
TreeEnvironmentContextProps,
@@ -21,26 +21,24 @@ export const ControlledTreeEnvironment = React.forwardRef<
2121
>((props, ref) => {
2222
const environmentContextProps = useControlledTreeEnvironmentProps(props);
2323

24-
const { viewState } = props;
24+
const { viewState, onFocusItem } = props;
2525

2626
// Make sure that every tree view state has a focused item
27-
for (const treeId of Object.keys(environmentContextProps.trees)) {
28-
// TODO if the focus item is dragged out of the tree and is not within the expanded items
29-
// TODO of that tree, the tree does not show any focus item anymore.
30-
// Fix: use linear items to see if focus item is visible, and reset if not. Only refresh that
31-
// information when the viewstate changes
32-
if (
33-
!viewState[treeId]?.focusedItem &&
34-
environmentContextProps.trees[treeId]
35-
) {
36-
viewState[treeId] = {
37-
...viewState[treeId],
38-
focusedItem:
39-
props.items[environmentContextProps.trees[treeId].rootItem]
40-
?.children?.[0],
41-
};
27+
useEffect(() => {
28+
for (const treeId of Object.keys(environmentContextProps.trees)) {
29+
const firstItemIndex =
30+
props.items[environmentContextProps.trees[treeId].rootItem]
31+
?.children?.[0];
32+
const firstItem = firstItemIndex && props.items[firstItemIndex];
33+
if (
34+
!viewState[treeId]?.focusedItem &&
35+
environmentContextProps.trees[treeId] &&
36+
firstItem
37+
) {
38+
onFocusItem?.(firstItem, treeId, false);
39+
}
4240
}
43-
}
41+
}, [environmentContextProps.trees, onFocusItem, props.items, viewState]);
4442

4543
return (
4644
<TreeEnvironmentContext.Provider value={environmentContextProps}>

packages/core/src/drag/DragAndDropProvider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ export const DragAndDropProvider: React.FC<React.PropsWithChildren> = ({
282282
if (environment.activeTreeId) {
283283
setProgrammaticDragIndex(oldIndex =>
284284
Math.min(
285-
viableDragPositions[environment.activeTreeId!].length,
285+
viableDragPositions[environment.activeTreeId!].length - 1,
286286
oldIndex + 1
287287
)
288288
);
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Meta } from '@storybook/react';
2+
import React, { useState } from 'react';
3+
import { longTree } from 'demodata';
4+
import { Tree } from '../tree/Tree';
5+
import { ControlledTreeEnvironment } from '../controlledEnvironment/ControlledTreeEnvironment';
6+
import { TreeItemIndex } from '../types';
7+
8+
export default {
9+
title: 'Core/Issue Report Reproduction',
10+
} as Meta;
11+
12+
export const Issue363 = () => {
13+
const [focusedItem, setFocusedItem] = useState<TreeItemIndex>();
14+
const [expandedItems, setExpandedItems] = useState<TreeItemIndex[]>([]);
15+
const [selectedItems, setSelectedItems] = useState<TreeItemIndex[]>([]);
16+
return (
17+
<ControlledTreeEnvironment<string>
18+
canDragAndDrop
19+
canDropOnFolder
20+
canReorderItems
21+
items={longTree.items}
22+
getItemTitle={item => item.data}
23+
onFocusItem={item => {
24+
setFocusedItem(item.index);
25+
console.log(`Focused item: ${item.index}`);
26+
}}
27+
onSelectItems={items => {
28+
setSelectedItems(items);
29+
}}
30+
onExpandItem={item => {
31+
setExpandedItems([...expandedItems, item.index]);
32+
}}
33+
onCollapseItem={item => {
34+
setExpandedItems(expandedItems.filter(i => i !== item.index));
35+
}}
36+
viewState={{
37+
'tree-1': {
38+
focusedItem,
39+
expandedItems,
40+
selectedItems,
41+
},
42+
}}
43+
>
44+
<button type="button">Focusable element</button>
45+
<Tree treeId="tree-1" rootItem="root" treeLabel="Tree Example" />
46+
<pre>
47+
{JSON.stringify(
48+
{
49+
focusedItem,
50+
expandedItems,
51+
selectedItems,
52+
},
53+
null,
54+
2
55+
)}
56+
</pre>
57+
</ControlledTreeEnvironment>
58+
);
59+
};

packages/core/test/dnd-restrictions.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ describe('dnd restrictions', () => {
118118

119119
describe('canDrag', () => {
120120
it('respects disabled value', async () => {
121-
const canDrag = jest.fn(items => items[0].data !== 'aab');
121+
const canDrag = jest.fn(items => items[0]?.data !== 'aab');
122122
const test = await new TestUtil().renderOpenTree({
123123
canDrag,
124124
});
@@ -131,7 +131,7 @@ describe('dnd restrictions', () => {
131131
});
132132

133133
it('works for other item', async () => {
134-
const canDrag = jest.fn(items => items[0].data !== 'aab');
134+
const canDrag = jest.fn(items => items[0]?.data !== 'aab');
135135
const test = await new TestUtil().renderOpenTree({
136136
canDrag,
137137
});

0 commit comments

Comments
 (0)