@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 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
- apply(() => {
155
- var _a;
156
- setState(state2);
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, useRef, useState } from "react";
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
- apply(() => {
97
- var _a;
98
- setState(state2);
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
- "version": "1.4.0",
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.js",
15
- "default": "./dist/index.d.ts"
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.js",
25
- "default": "./dist/react17/index.d.ts"
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
  [![Documentation](https://img.shields.io/badge/docs-1e1f22?style=flat)](https://headless-tree.lukasbach.com/)
4
4
  [![Chat on Discord](https://img.shields.io/badge/discord-4c57d9?style=flat&logo=discord&logoColor=ffffff)](https://discord.gg/KuZ6EezzVw)
5
- [![Follow on BLuesky](https://img.shields.io/badge/bluesky-0285FF?style=flat&logo=bluesky&logoColor=ffffff)](https://bsky.app/profile/lukasbach.bsky.social)
5
+ [![Follow on Bluesky](https://img.shields.io/badge/bluesky-0285FF?style=flat&logo=bluesky&logoColor=ffffff)](https://bsky.app/profile/lukasbach.bsky.social)
6
+ [![Follow on X](https://img.shields.io/badge/x-000000?style=flat&logo=x&logoColor=ffffff)](https://x.com/lukasmbach)
6
7
  [![Support on Github Sponsors](https://img.shields.io/badge/sponsor-EA4AAA?style=flat&logo=githubsponsors&logoColor=ffffff)](https://github.com/sponsors/lukasbach)
7
8
  [![Follow on Github](https://img.shields.io/badge/follow-181717?style=flat&logo=github&logoColor=ffffff)](https://github.com/lukasbach)
8
9
  [![NPM Core package](https://img.shields.io/badge/core-CB3837?style=flat&logo=npm&logoColor=ffffff)](https://www.npmjs.com/package/@headless-tree/core)
9
10
  [![NPM React package](https://img.shields.io/badge/react-CB3837?style=flat&logo=npm&logoColor=ffffff)](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, useRef, useState } from "react";
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
- }, [tree]); // runs only once after mount
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
- apply(() => {
50
- setState(state);
51
- config.setState?.(state);
52
- });
27
+ setState(state);
28
+ config.setState?.(state);
53
29
  },
54
30
  }));
55
31