@headless-tree/react 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/index.js +7 -22
- package/dist/index.mjs +8 -23
- package/package.json +21 -5
- package/readme.md +6 -6
- package/src/use-tree.tsx +9 -33
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @headless-tree/react
|
|
2
2
|
|
|
3
|
+
## 1.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- cbeaba6: all state updates (like setSelectedItems) will not propagate while the component is unmounted. This happened before for `tree.setState()` calls directly, but not individual state atoms like `setSelectedItems`. When calling `createTree()` directly (instead of `useTree()`), `tree.setMounted(true)` needs to be called once after mount. No changes are necessary when using the React-based `useTree()` integration. (#158)
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 72e714b: all NPM deployments will now publish with provenance
|
|
12
|
+
- 7a7424f: fixed incorrect exports definition in package.json for require/cjs imports (#161)
|
|
13
|
+
|
|
3
14
|
## 1.4.0
|
|
4
15
|
|
|
5
16
|
## 1.3.0
|
package/dist/index.js
CHANGED
|
@@ -123,39 +123,24 @@ var AssistiveTreeDescription = (_a) => {
|
|
|
123
123
|
// src/use-tree.tsx
|
|
124
124
|
var import_react2 = require("react");
|
|
125
125
|
var import_core2 = require("@headless-tree/core");
|
|
126
|
-
var useApplyAfterMount = () => {
|
|
127
|
-
const isMounted = (0, import_react2.useRef)(false);
|
|
128
|
-
const callbacks = (0, import_react2.useRef)([]);
|
|
129
|
-
(0, import_react2.useEffect)(() => {
|
|
130
|
-
isMounted.current = true;
|
|
131
|
-
callbacks.current.forEach((callback) => callback());
|
|
132
|
-
}, []);
|
|
133
|
-
const apply = (callback) => {
|
|
134
|
-
if (isMounted.current) {
|
|
135
|
-
callback();
|
|
136
|
-
} else {
|
|
137
|
-
callbacks.current.push(callback);
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
return apply;
|
|
141
|
-
};
|
|
142
126
|
var useTree = (config) => {
|
|
143
|
-
const apply = useApplyAfterMount();
|
|
144
127
|
const [tree] = (0, import_react2.useState)(() => ({ current: (0, import_core2.createTree)(config) }));
|
|
145
128
|
const [state, setState] = (0, import_react2.useState)(
|
|
146
129
|
() => tree.current.getState()
|
|
147
130
|
);
|
|
148
131
|
(0, import_react2.useEffect)(() => {
|
|
132
|
+
tree.current.setMounted(true);
|
|
149
133
|
tree.current.rebuildTree();
|
|
134
|
+
return () => {
|
|
135
|
+
tree.current.setMounted(false);
|
|
136
|
+
};
|
|
150
137
|
}, [tree]);
|
|
151
138
|
tree.current.setConfig((prev) => __spreadProps(__spreadValues(__spreadValues({}, prev), config), {
|
|
152
139
|
state: __spreadValues(__spreadValues({}, state), config.state),
|
|
153
140
|
setState: (state2) => {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
(_a = config.setState) == null ? void 0 : _a.call(config, state2);
|
|
158
|
-
});
|
|
141
|
+
var _a;
|
|
142
|
+
setState(state2);
|
|
143
|
+
(_a = config.setState) == null ? void 0 : _a.call(config, state2);
|
|
159
144
|
}
|
|
160
145
|
}));
|
|
161
146
|
return tree.current;
|
package/dist/index.mjs
CHANGED
|
@@ -63,41 +63,26 @@ var AssistiveTreeDescription = (_a) => {
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
// src/use-tree.tsx
|
|
66
|
-
import { useEffect,
|
|
66
|
+
import { useEffect, useState } from "react";
|
|
67
67
|
import { createTree } from "@headless-tree/core";
|
|
68
|
-
var useApplyAfterMount = () => {
|
|
69
|
-
const isMounted = useRef(false);
|
|
70
|
-
const callbacks = useRef([]);
|
|
71
|
-
useEffect(() => {
|
|
72
|
-
isMounted.current = true;
|
|
73
|
-
callbacks.current.forEach((callback) => callback());
|
|
74
|
-
}, []);
|
|
75
|
-
const apply = (callback) => {
|
|
76
|
-
if (isMounted.current) {
|
|
77
|
-
callback();
|
|
78
|
-
} else {
|
|
79
|
-
callbacks.current.push(callback);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
return apply;
|
|
83
|
-
};
|
|
84
68
|
var useTree = (config) => {
|
|
85
|
-
const apply = useApplyAfterMount();
|
|
86
69
|
const [tree] = useState(() => ({ current: createTree(config) }));
|
|
87
70
|
const [state, setState] = useState(
|
|
88
71
|
() => tree.current.getState()
|
|
89
72
|
);
|
|
90
73
|
useEffect(() => {
|
|
74
|
+
tree.current.setMounted(true);
|
|
91
75
|
tree.current.rebuildTree();
|
|
76
|
+
return () => {
|
|
77
|
+
tree.current.setMounted(false);
|
|
78
|
+
};
|
|
92
79
|
}, [tree]);
|
|
93
80
|
tree.current.setConfig((prev) => __spreadProps(__spreadValues(__spreadValues({}, prev), config), {
|
|
94
81
|
state: __spreadValues(__spreadValues({}, state), config.state),
|
|
95
82
|
setState: (state2) => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
(_a = config.setState) == null ? void 0 : _a.call(config, state2);
|
|
100
|
-
});
|
|
83
|
+
var _a;
|
|
84
|
+
setState(state2);
|
|
85
|
+
(_a = config.setState) == null ? void 0 : _a.call(config, state2);
|
|
101
86
|
}
|
|
102
87
|
}));
|
|
103
88
|
return tree.current;
|
package/package.json
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@headless-tree/react",
|
|
3
|
-
"
|
|
3
|
+
"description": "The definitive tree component for the Web",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"tree",
|
|
6
|
+
"component",
|
|
7
|
+
"web",
|
|
8
|
+
"headless",
|
|
9
|
+
"ui",
|
|
10
|
+
"react",
|
|
11
|
+
"nested",
|
|
12
|
+
"async",
|
|
13
|
+
"checkbox",
|
|
14
|
+
"hook"
|
|
15
|
+
],
|
|
16
|
+
"version": "1.5.0",
|
|
4
17
|
"main": "dist/index.d.ts",
|
|
5
18
|
"module": "dist/index.mjs",
|
|
6
19
|
"types": "dist/index.d.mts",
|
|
@@ -11,8 +24,8 @@
|
|
|
11
24
|
"default": "./dist/index.mjs"
|
|
12
25
|
},
|
|
13
26
|
"require": {
|
|
14
|
-
"types": "./dist/index.
|
|
15
|
-
"default": "./dist/index.
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"default": "./dist/index.js"
|
|
16
29
|
}
|
|
17
30
|
},
|
|
18
31
|
"./react17": {
|
|
@@ -21,13 +34,16 @@
|
|
|
21
34
|
"default": "./dist/react17/index.mjs"
|
|
22
35
|
},
|
|
23
36
|
"require": {
|
|
24
|
-
"types": "./dist/react17/index.
|
|
25
|
-
"default": "./dist/react17/index.
|
|
37
|
+
"types": "./dist/react17/index.d.ts",
|
|
38
|
+
"default": "./dist/react17/index.js"
|
|
26
39
|
}
|
|
27
40
|
},
|
|
28
41
|
"./package.json": "./package.json"
|
|
29
42
|
},
|
|
30
43
|
"sideEffects": false,
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"provenance": true
|
|
46
|
+
},
|
|
31
47
|
"scripts": {
|
|
32
48
|
"build": "tsup ./src/index.ts ./src/react17/index.tsx --format esm,cjs --dts",
|
|
33
49
|
"start": "tsup ./src/index.ts --format esm,cjs --dts --watch"
|
package/readme.md
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://headless-tree.lukasbach.com/)
|
|
4
4
|
[](https://discord.gg/KuZ6EezzVw)
|
|
5
|
-
[](https://bsky.app/profile/lukasbach.bsky.social)
|
|
6
|
+
[](https://x.com/lukasmbach)
|
|
6
7
|
[](https://github.com/sponsors/lukasbach)
|
|
7
8
|
[](https://github.com/lukasbach)
|
|
8
9
|
[](https://www.npmjs.com/package/@headless-tree/core)
|
|
9
10
|
[](https://www.npmjs.com/package/@headless-tree/react)
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
Super-easy integration of complex tree components into React. Supports ordered
|
|
12
|
+
Super-easy integration of complex tree components into React. Supports ordered
|
|
13
13
|
and unordered drag-and-drop, extensive keybindings, search, renaming and more.
|
|
14
14
|
Fully customizable and accessible. Headless Tree is the official successor for
|
|
15
15
|
[react-complex-tree](https://github.com/lukasbach/react-complex-tree).
|
|
@@ -18,7 +18,7 @@ It aims to bring the many features of complex tree views, like multi-select,
|
|
|
18
18
|
drag-and-drop, keyboard navigation, tree search, renaming and more, while
|
|
19
19
|
being unopinionated about the styling and rendering of the tree itself.
|
|
20
20
|
Accessibility is ensured by default, and the integration is extremely
|
|
21
|
-
simple and flexible.
|
|
21
|
+
simple and flexible.
|
|
22
22
|
|
|
23
23
|
The interface gives you a flat list of tree nodes
|
|
24
24
|
that you can easily render yourself, which keeps the complexity of the
|
|
@@ -39,7 +39,7 @@ to get an idea of what you can do with it.
|
|
|
39
39
|
> I have collected feedback and fixed any bugs that might arise. I've written
|
|
40
40
|
> [a blog post](https://medium.com/@lukasbach/headless-tree-and-the-future-of-react-complex-tree-fc920700e82a)
|
|
41
41
|
> about the details of the change, and the future of the library.
|
|
42
|
-
>
|
|
42
|
+
>
|
|
43
43
|
> Join
|
|
44
44
|
> [the Discord](https://discord.gg/KuZ6EezzVw) to get involved, and
|
|
45
45
|
> [follow on Bluesky](https://bsky.app/profile/lukasbach.bsky.social) to
|
|
@@ -154,4 +154,4 @@ Then, render your tree based on the tree instance returned from the hook:
|
|
|
154
154
|
```
|
|
155
155
|
|
|
156
156
|
Read on in the [get started guide](https://headless-tree.lukasbach.com/getstarted) to learn more about
|
|
157
|
-
how to use Headless Tree, and how to customize it to your needs.
|
|
157
|
+
how to use Headless Tree, and how to customize it to your needs.
|
package/src/use-tree.tsx
CHANGED
|
@@ -1,42 +1,20 @@
|
|
|
1
|
-
import { useEffect,
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
2
|
import { TreeConfig, TreeState, createTree } from "@headless-tree/core";
|
|
3
3
|
|
|
4
|
-
/* A bug with NextJS was reported in the past where very quick state updates (i.e. data
|
|
5
|
-
* loader returning withing milliseconds) will cause the state update to occur before
|
|
6
|
-
* mount, resulting in a console warning. This alleviates this.
|
|
7
|
-
* We should monitor if this remains a problem in the future, maybe we can eventually
|
|
8
|
-
* remove this workaround...
|
|
9
|
-
*/
|
|
10
|
-
const useApplyAfterMount = () => {
|
|
11
|
-
const isMounted = useRef(false);
|
|
12
|
-
const callbacks = useRef<(() => void)[]>([]);
|
|
13
|
-
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
isMounted.current = true;
|
|
16
|
-
callbacks.current.forEach((callback) => callback());
|
|
17
|
-
}, []);
|
|
18
|
-
|
|
19
|
-
const apply = (callback: () => void) => {
|
|
20
|
-
if (isMounted.current) {
|
|
21
|
-
callback();
|
|
22
|
-
} else {
|
|
23
|
-
callbacks.current.push(callback);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
return apply;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
4
|
export const useTree = <T,>(config: TreeConfig<T>) => {
|
|
31
|
-
const apply = useApplyAfterMount();
|
|
32
5
|
const [tree] = useState(() => ({ current: createTree(config) }));
|
|
33
6
|
const [state, setState] = useState<Partial<TreeState<T>>>(() =>
|
|
34
7
|
tree.current.getState(),
|
|
35
8
|
);
|
|
36
9
|
|
|
37
10
|
useEffect(() => {
|
|
11
|
+
(tree.current as any).setMounted(true);
|
|
38
12
|
tree.current.rebuildTree();
|
|
39
|
-
|
|
13
|
+
return () => {
|
|
14
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
15
|
+
(tree.current as any).setMounted(false);
|
|
16
|
+
};
|
|
17
|
+
}, [tree]);
|
|
40
18
|
|
|
41
19
|
tree.current.setConfig((prev) => ({
|
|
42
20
|
...prev,
|
|
@@ -46,10 +24,8 @@ export const useTree = <T,>(config: TreeConfig<T>) => {
|
|
|
46
24
|
...config.state,
|
|
47
25
|
},
|
|
48
26
|
setState: (state) => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
config.setState?.(state);
|
|
52
|
-
});
|
|
27
|
+
setState(state);
|
|
28
|
+
config.setState?.(state);
|
|
53
29
|
},
|
|
54
30
|
}));
|
|
55
31
|
|