@headless-tree/react 1.2.1 → 1.4.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,15 @@
1
1
  # @headless-tree/react
2
2
 
3
+ ## 1.4.0
4
+
5
+ ## 1.3.0
6
+
7
+ ### Patch Changes
8
+
9
+ - 32e71e9: Added optional @headless-tree/react/react17 import for useTree for compatibility
10
+ - 662e2a8: Improved customizability of checkboxes feature (still alpha state), allowing you to customize `propagateCheckedState` and `canCheckFolders` independently
11
+ - 662e2a8: Changed to new buildtool in core packages (now using tsup) to hopefully fix some ESM/CJS integrations
12
+
3
13
  ## 1.2.1
4
14
 
5
15
  ### Patch Changes
@@ -0,0 +1,37 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
32
+
33
+ export {
34
+ __spreadValues,
35
+ __spreadProps,
36
+ __objRest
37
+ };
@@ -0,0 +1,13 @@
1
+ import React, { HTMLProps } from 'react';
2
+ import * as _headless_tree_core from '@headless-tree/core';
3
+ import { TreeInstance, DndState, AssistiveDndState, HotkeysConfig, TreeConfig } from '@headless-tree/core';
4
+
5
+ declare const getDefaultLabel: <T>(dnd: DndState<T> | null | undefined, assistiveState: AssistiveDndState, hotkeys: HotkeysConfig<T>) => string;
6
+ declare const AssistiveTreeDescription: <T>({ tree, getLabel, ...props }: {
7
+ tree: TreeInstance<T>;
8
+ getLabel?: typeof getDefaultLabel;
9
+ } & HTMLProps<HTMLSpanElement>) => React.JSX.Element;
10
+
11
+ declare const useTree: <T>(config: TreeConfig<T>) => _headless_tree_core.TreeInstance<T>;
12
+
13
+ export { AssistiveTreeDescription, useTree };
@@ -0,0 +1,13 @@
1
+ import React, { HTMLProps } from 'react';
2
+ import * as _headless_tree_core from '@headless-tree/core';
3
+ import { TreeInstance, DndState, AssistiveDndState, HotkeysConfig, TreeConfig } from '@headless-tree/core';
4
+
5
+ declare const getDefaultLabel: <T>(dnd: DndState<T> | null | undefined, assistiveState: AssistiveDndState, hotkeys: HotkeysConfig<T>) => string;
6
+ declare const AssistiveTreeDescription: <T>({ tree, getLabel, ...props }: {
7
+ tree: TreeInstance<T>;
8
+ getLabel?: typeof getDefaultLabel;
9
+ } & HTMLProps<HTMLSpanElement>) => React.JSX.Element;
10
+
11
+ declare const useTree: <T>(config: TreeConfig<T>) => _headless_tree_core.TreeInstance<T>;
12
+
13
+ export { AssistiveTreeDescription, useTree };
package/dist/index.js ADDED
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
+ var __getProtoOf = Object.getPrototypeOf;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __spreadValues = (a, b) => {
14
+ for (var prop in b || (b = {}))
15
+ if (__hasOwnProp.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ if (__getOwnPropSymbols)
18
+ for (var prop of __getOwnPropSymbols(b)) {
19
+ if (__propIsEnum.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ }
22
+ return a;
23
+ };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __objRest = (source, exclude) => {
26
+ var target = {};
27
+ for (var prop in source)
28
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
29
+ target[prop] = source[prop];
30
+ if (source != null && __getOwnPropSymbols)
31
+ for (var prop of __getOwnPropSymbols(source)) {
32
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
33
+ target[prop] = source[prop];
34
+ }
35
+ return target;
36
+ };
37
+ var __export = (target, all) => {
38
+ for (var name in all)
39
+ __defProp(target, name, { get: all[name], enumerable: true });
40
+ };
41
+ var __copyProps = (to, from, except, desc) => {
42
+ if (from && typeof from === "object" || typeof from === "function") {
43
+ for (let key of __getOwnPropNames(from))
44
+ if (!__hasOwnProp.call(to, key) && key !== except)
45
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
46
+ }
47
+ return to;
48
+ };
49
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
50
+ // If the importer is in node compatibility mode or this is not an ESM
51
+ // file that has been converted to a CommonJS file using a Babel-
52
+ // compatible transform (i.e. "__esModule" has not been set), then set
53
+ // "default" to the CommonJS "module.exports" for node compatibility.
54
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
55
+ mod
56
+ ));
57
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
58
+
59
+ // src/index.ts
60
+ var index_exports = {};
61
+ __export(index_exports, {
62
+ AssistiveTreeDescription: () => AssistiveTreeDescription,
63
+ useTree: () => useTree
64
+ });
65
+ module.exports = __toCommonJS(index_exports);
66
+
67
+ // src/assistive-tree-description.tsx
68
+ var import_react = __toESM(require("react"));
69
+ var import_core = require("@headless-tree/core");
70
+ var styles = {
71
+ position: "absolute",
72
+ margin: "-1px",
73
+ width: "1px",
74
+ height: "1px",
75
+ overflow: "hidden",
76
+ clip: "rect(0 0 0 0)"
77
+ };
78
+ var getDefaultLabel = (dnd, assistiveState, hotkeys) => {
79
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
80
+ if (!hotkeys.startDrag) return "";
81
+ const itemNames = (_b = (_a = dnd == null ? void 0 : dnd.draggedItems) == null ? void 0 : _a.map((item) => item.getItemName()).join(", ")) != null ? _b : "";
82
+ const position = !(dnd == null ? void 0 : dnd.dragTarget) ? "None" : "childIndex" in dnd.dragTarget ? `${dnd.dragTarget.childIndex} of ${dnd.dragTarget.item.getChildren().length} in ${dnd.dragTarget.item.getItemName()}` : `in ${dnd.dragTarget.item.getItemName()}`;
83
+ const navGuide = `Press ${(_c = hotkeys.dragUp) == null ? void 0 : _c.hotkey} and ${(_d = hotkeys.dragDown) == null ? void 0 : _d.hotkey} to move up or down, ${(_e = hotkeys.completeDrag) == null ? void 0 : _e.hotkey} to drop, ${(_f = hotkeys.cancelDrag) == null ? void 0 : _f.hotkey} to abort.`;
84
+ switch (assistiveState) {
85
+ case import_core.AssistiveDndState.Started:
86
+ return itemNames ? `Dragging ${itemNames}. Current position: ${position}. ${navGuide}` : `Current position: ${position}. ${navGuide}`;
87
+ case import_core.AssistiveDndState.Dragging:
88
+ return itemNames ? `${itemNames}, ${position}` : position;
89
+ case import_core.AssistiveDndState.Completed:
90
+ return `Drag completed. Press ${(_g = hotkeys.startDrag) == null ? void 0 : _g.hotkey} to move selected items`;
91
+ case import_core.AssistiveDndState.Aborted:
92
+ return `Drag cancelled. Press ${(_h = hotkeys.startDrag) == null ? void 0 : _h.hotkey} to move selected items`;
93
+ case import_core.AssistiveDndState.None:
94
+ default:
95
+ return `Press ${(_i = hotkeys.startDrag) == null ? void 0 : _i.hotkey} to move selected items`;
96
+ }
97
+ };
98
+ var AssistiveTreeDescription = (_a) => {
99
+ var _b = _a, {
100
+ tree,
101
+ getLabel = getDefaultLabel
102
+ } = _b, props = __objRest(_b, [
103
+ "tree",
104
+ "getLabel"
105
+ ]);
106
+ var _a2;
107
+ const state = tree.getState();
108
+ return /* @__PURE__ */ import_react.default.createElement(
109
+ "span",
110
+ __spreadProps(__spreadValues({
111
+ "aria-live": "assertive"
112
+ }, props), {
113
+ style: __spreadValues(__spreadValues({}, styles), props.style)
114
+ }),
115
+ getLabel(
116
+ state.dnd,
117
+ (_a2 = state.assistiveDndState) != null ? _a2 : import_core.AssistiveDndState.None,
118
+ tree.getHotkeyPresets()
119
+ )
120
+ );
121
+ };
122
+
123
+ // src/use-tree.tsx
124
+ var import_react2 = require("react");
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
+ var useTree = (config) => {
143
+ const apply = useApplyAfterMount();
144
+ const [tree] = (0, import_react2.useState)(() => ({ current: (0, import_core2.createTree)(config) }));
145
+ const [state, setState] = (0, import_react2.useState)(
146
+ () => tree.current.getState()
147
+ );
148
+ (0, import_react2.useEffect)(() => {
149
+ tree.current.rebuildTree();
150
+ }, [tree]);
151
+ tree.current.setConfig((prev) => __spreadProps(__spreadValues(__spreadValues({}, prev), config), {
152
+ state: __spreadValues(__spreadValues({}, state), config.state),
153
+ setState: (state2) => {
154
+ apply(() => {
155
+ var _a;
156
+ setState(state2);
157
+ (_a = config.setState) == null ? void 0 : _a.call(config, state2);
158
+ });
159
+ }
160
+ }));
161
+ return tree.current;
162
+ };
163
+ // Annotate the CommonJS export names for ESM import in node:
164
+ 0 && (module.exports = {
165
+ AssistiveTreeDescription,
166
+ useTree
167
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,108 @@
1
+ import {
2
+ __objRest,
3
+ __spreadProps,
4
+ __spreadValues
5
+ } from "./chunk-FWCSY2DS.mjs";
6
+
7
+ // src/assistive-tree-description.tsx
8
+ import React from "react";
9
+ import {
10
+ AssistiveDndState
11
+ } from "@headless-tree/core";
12
+ var styles = {
13
+ position: "absolute",
14
+ margin: "-1px",
15
+ width: "1px",
16
+ height: "1px",
17
+ overflow: "hidden",
18
+ clip: "rect(0 0 0 0)"
19
+ };
20
+ var getDefaultLabel = (dnd, assistiveState, hotkeys) => {
21
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
22
+ if (!hotkeys.startDrag) return "";
23
+ const itemNames = (_b = (_a = dnd == null ? void 0 : dnd.draggedItems) == null ? void 0 : _a.map((item) => item.getItemName()).join(", ")) != null ? _b : "";
24
+ const position = !(dnd == null ? void 0 : dnd.dragTarget) ? "None" : "childIndex" in dnd.dragTarget ? `${dnd.dragTarget.childIndex} of ${dnd.dragTarget.item.getChildren().length} in ${dnd.dragTarget.item.getItemName()}` : `in ${dnd.dragTarget.item.getItemName()}`;
25
+ const navGuide = `Press ${(_c = hotkeys.dragUp) == null ? void 0 : _c.hotkey} and ${(_d = hotkeys.dragDown) == null ? void 0 : _d.hotkey} to move up or down, ${(_e = hotkeys.completeDrag) == null ? void 0 : _e.hotkey} to drop, ${(_f = hotkeys.cancelDrag) == null ? void 0 : _f.hotkey} to abort.`;
26
+ switch (assistiveState) {
27
+ case AssistiveDndState.Started:
28
+ return itemNames ? `Dragging ${itemNames}. Current position: ${position}. ${navGuide}` : `Current position: ${position}. ${navGuide}`;
29
+ case AssistiveDndState.Dragging:
30
+ return itemNames ? `${itemNames}, ${position}` : position;
31
+ case AssistiveDndState.Completed:
32
+ return `Drag completed. Press ${(_g = hotkeys.startDrag) == null ? void 0 : _g.hotkey} to move selected items`;
33
+ case AssistiveDndState.Aborted:
34
+ return `Drag cancelled. Press ${(_h = hotkeys.startDrag) == null ? void 0 : _h.hotkey} to move selected items`;
35
+ case AssistiveDndState.None:
36
+ default:
37
+ return `Press ${(_i = hotkeys.startDrag) == null ? void 0 : _i.hotkey} to move selected items`;
38
+ }
39
+ };
40
+ var AssistiveTreeDescription = (_a) => {
41
+ var _b = _a, {
42
+ tree,
43
+ getLabel = getDefaultLabel
44
+ } = _b, props = __objRest(_b, [
45
+ "tree",
46
+ "getLabel"
47
+ ]);
48
+ var _a2;
49
+ const state = tree.getState();
50
+ return /* @__PURE__ */ React.createElement(
51
+ "span",
52
+ __spreadProps(__spreadValues({
53
+ "aria-live": "assertive"
54
+ }, props), {
55
+ style: __spreadValues(__spreadValues({}, styles), props.style)
56
+ }),
57
+ getLabel(
58
+ state.dnd,
59
+ (_a2 = state.assistiveDndState) != null ? _a2 : AssistiveDndState.None,
60
+ tree.getHotkeyPresets()
61
+ )
62
+ );
63
+ };
64
+
65
+ // src/use-tree.tsx
66
+ import { useEffect, useRef, useState } from "react";
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
+ var useTree = (config) => {
85
+ const apply = useApplyAfterMount();
86
+ const [tree] = useState(() => ({ current: createTree(config) }));
87
+ const [state, setState] = useState(
88
+ () => tree.current.getState()
89
+ );
90
+ useEffect(() => {
91
+ tree.current.rebuildTree();
92
+ }, [tree]);
93
+ tree.current.setConfig((prev) => __spreadProps(__spreadValues(__spreadValues({}, prev), config), {
94
+ state: __spreadValues(__spreadValues({}, state), config.state),
95
+ setState: (state2) => {
96
+ apply(() => {
97
+ var _a;
98
+ setState(state2);
99
+ (_a = config.setState) == null ? void 0 : _a.call(config, state2);
100
+ });
101
+ }
102
+ }));
103
+ return tree.current;
104
+ };
105
+ export {
106
+ AssistiveTreeDescription,
107
+ useTree
108
+ };
@@ -0,0 +1,6 @@
1
+ import * as _headless_tree_core from '@headless-tree/core';
2
+ import { TreeConfig } from '@headless-tree/core';
3
+
4
+ declare const useTree: <T>(config: TreeConfig<T>) => _headless_tree_core.TreeInstance<T>;
5
+
6
+ export { useTree };
@@ -0,0 +1,6 @@
1
+ import * as _headless_tree_core from '@headless-tree/core';
2
+ import { TreeConfig } from '@headless-tree/core';
3
+
4
+ declare const useTree: <T>(config: TreeConfig<T>) => _headless_tree_core.TreeInstance<T>;
5
+
6
+ export { useTree };
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __defProps = Object.defineProperties;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
+ var __spreadValues = (a, b) => {
12
+ for (var prop in b || (b = {}))
13
+ if (__hasOwnProp.call(b, prop))
14
+ __defNormalProp(a, prop, b[prop]);
15
+ if (__getOwnPropSymbols)
16
+ for (var prop of __getOwnPropSymbols(b)) {
17
+ if (__propIsEnum.call(b, prop))
18
+ __defNormalProp(a, prop, b[prop]);
19
+ }
20
+ return a;
21
+ };
22
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
23
+ var __export = (target, all) => {
24
+ for (var name in all)
25
+ __defProp(target, name, { get: all[name], enumerable: true });
26
+ };
27
+ var __copyProps = (to, from, except, desc) => {
28
+ if (from && typeof from === "object" || typeof from === "function") {
29
+ for (let key of __getOwnPropNames(from))
30
+ if (!__hasOwnProp.call(to, key) && key !== except)
31
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
32
+ }
33
+ return to;
34
+ };
35
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
+
37
+ // src/react17/index.tsx
38
+ var react17_exports = {};
39
+ __export(react17_exports, {
40
+ useTree: () => useTree
41
+ });
42
+ module.exports = __toCommonJS(react17_exports);
43
+ var import_react = require("react");
44
+ var import_core = require("@headless-tree/core");
45
+ var useTree = (config) => {
46
+ const [tree] = (0, import_react.useState)(() => ({ current: (0, import_core.createTree)(config) }));
47
+ const [state, setState] = (0, import_react.useState)(
48
+ () => tree.current.getState()
49
+ );
50
+ (0, import_react.useEffect)(() => {
51
+ tree.current.rebuildTree();
52
+ }, [tree]);
53
+ tree.current.setConfig((prev) => __spreadProps(__spreadValues(__spreadValues({}, prev), config), {
54
+ state: __spreadValues(__spreadValues({}, state), config.state),
55
+ setState: (state2) => {
56
+ var _a;
57
+ setState(state2);
58
+ (_a = config.setState) == null ? void 0 : _a.call(config, state2);
59
+ }
60
+ }));
61
+ return tree.current;
62
+ };
63
+ // Annotate the CommonJS export names for ESM import in node:
64
+ 0 && (module.exports = {
65
+ useTree
66
+ });
@@ -0,0 +1,29 @@
1
+ import {
2
+ __spreadProps,
3
+ __spreadValues
4
+ } from "../chunk-FWCSY2DS.mjs";
5
+
6
+ // src/react17/index.tsx
7
+ import { useEffect, useState } from "react";
8
+ import { createTree } from "@headless-tree/core";
9
+ var useTree = (config) => {
10
+ const [tree] = useState(() => ({ current: createTree(config) }));
11
+ const [state, setState] = useState(
12
+ () => tree.current.getState()
13
+ );
14
+ useEffect(() => {
15
+ tree.current.rebuildTree();
16
+ }, [tree]);
17
+ tree.current.setConfig((prev) => __spreadProps(__spreadValues(__spreadValues({}, prev), config), {
18
+ state: __spreadValues(__spreadValues({}, state), config.state),
19
+ setState: (state2) => {
20
+ var _a;
21
+ setState(state2);
22
+ (_a = config.setState) == null ? void 0 : _a.call(config, state2);
23
+ }
24
+ }));
25
+ return tree.current;
26
+ };
27
+ export {
28
+ useTree
29
+ };
package/package.json CHANGED
@@ -1,19 +1,36 @@
1
1
  {
2
2
  "name": "@headless-tree/react",
3
- "version": "1.2.1",
4
- "main": "lib/cjs/index.js",
5
- "module": "lib/esm/index.js",
6
- "types": "lib/esm/index.d.ts",
3
+ "version": "1.4.0",
4
+ "main": "dist/index.d.ts",
5
+ "module": "dist/index.mjs",
6
+ "types": "dist/index.d.mts",
7
7
  "exports": {
8
- "types": "./lib/esm/index.d.ts",
9
- "import": "./lib/esm/index.js",
10
- "default": "./lib/cjs/index.js"
8
+ ".": {
9
+ "import": {
10
+ "types": "./dist/index.d.mts",
11
+ "default": "./dist/index.mjs"
12
+ },
13
+ "require": {
14
+ "types": "./dist/index.js",
15
+ "default": "./dist/index.d.ts"
16
+ }
17
+ },
18
+ "./react17": {
19
+ "import": {
20
+ "types": "./dist/react17/index.d.mts",
21
+ "default": "./dist/react17/index.mjs"
22
+ },
23
+ "require": {
24
+ "types": "./dist/react17/index.js",
25
+ "default": "./dist/react17/index.d.ts"
26
+ }
27
+ },
28
+ "./package.json": "./package.json"
11
29
  },
12
30
  "sideEffects": false,
13
31
  "scripts": {
14
- "build:cjs": "tsc -m commonjs --outDir lib/cjs",
15
- "build:esm": "tsc",
16
- "start": "tsc -w"
32
+ "build": "tsup ./src/index.ts ./src/react17/index.tsx --format esm,cjs --dts",
33
+ "start": "tsup ./src/index.ts --format esm,cjs --dts --watch"
17
34
  },
18
35
  "repository": {
19
36
  "type": "git",
@@ -31,6 +48,7 @@
31
48
  "prop-types": "15.8.1",
32
49
  "react": "^18.2.0",
33
50
  "react-dom": "^18.2.0",
51
+ "tsup": "^8.5.0",
34
52
  "typescript": "^5.7.2"
35
53
  },
36
54
  "peerDependencies": {
@@ -0,0 +1,29 @@
1
+ import { useEffect, useState } from "react";
2
+ import { TreeConfig, TreeState, createTree } from "@headless-tree/core";
3
+
4
+ export const useTree = <T,>(config: TreeConfig<T>) => {
5
+ const [tree] = useState(() => ({ current: createTree(config) }));
6
+ const [state, setState] = useState<Partial<TreeState<T>>>(() =>
7
+ tree.current.getState(),
8
+ );
9
+
10
+ useEffect(() => {
11
+ tree.current.rebuildTree();
12
+ }, [tree]); // runs only once after mount
13
+
14
+ tree.current.setConfig((prev) => ({
15
+ ...prev,
16
+ ...config,
17
+ state: {
18
+ // ...prev.state,
19
+ ...state,
20
+ ...config.state,
21
+ },
22
+ setState: (state) => {
23
+ setState(state);
24
+ config.setState?.(state);
25
+ },
26
+ }));
27
+
28
+ return tree.current;
29
+ };
package/src/use-tree.tsx CHANGED
@@ -1,7 +1,34 @@
1
- import { useEffect, useInsertionEffect, useState } from "react";
1
+ import { useEffect, useRef, 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
+
4
30
  export const useTree = <T,>(config: TreeConfig<T>) => {
31
+ const apply = useApplyAfterMount();
5
32
  const [tree] = useState(() => ({ current: createTree(config) }));
6
33
  const [state, setState] = useState<Partial<TreeState<T>>>(() =>
7
34
  tree.current.getState(),
@@ -11,21 +38,20 @@ export const useTree = <T,>(config: TreeConfig<T>) => {
11
38
  tree.current.rebuildTree();
12
39
  }, [tree]); // runs only once after mount
13
40
 
14
- useInsertionEffect(() => {
15
- tree.current.setConfig((prev) => ({
16
- ...prev,
17
- ...config,
18
- state: {
19
- // ...prev.state,
20
- ...state,
21
- ...config.state,
22
- },
23
- setState: (state) => {
41
+ tree.current.setConfig((prev) => ({
42
+ ...prev,
43
+ ...config,
44
+ state: {
45
+ ...state,
46
+ ...config.state,
47
+ },
48
+ setState: (state) => {
49
+ apply(() => {
24
50
  setState(state);
25
51
  config.setState?.(state);
26
- },
27
- }));
28
- });
52
+ });
53
+ },
54
+ }));
29
55
 
30
56
  return tree.current;
31
57
  };
package/tsconfig.json CHANGED
@@ -1,7 +1,4 @@
1
1
  {
2
2
  "extends": "../../tsconfig.json",
3
- "include": ["./src/**/*"],
4
- "compilerOptions": {
5
- "outDir": "lib/esm"
6
- }
3
+ "include": ["./src/**/*"]
7
4
  }
@@ -1,8 +0,0 @@
1
- import React, { HTMLProps } from "react";
2
- import { AssistiveDndState, DndState, HotkeysConfig, TreeInstance } from "@headless-tree/core";
3
- declare const getDefaultLabel: <T>(dnd: DndState<T> | null | undefined, assistiveState: AssistiveDndState, hotkeys: HotkeysConfig<T>) => string;
4
- export declare const AssistiveTreeDescription: <T>({ tree, getLabel, ...props }: {
5
- tree: TreeInstance<T>;
6
- getLabel?: typeof getDefaultLabel;
7
- } & HTMLProps<HTMLSpanElement>) => React.JSX.Element;
8
- export {};
@@ -1,63 +0,0 @@
1
- "use strict";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
- var __importDefault = (this && this.__importDefault) || function (mod) {
14
- return (mod && mod.__esModule) ? mod : { "default": mod };
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.AssistiveTreeDescription = void 0;
18
- const react_1 = __importDefault(require("react"));
19
- const core_1 = require("@headless-tree/core");
20
- // https://medium.com/salesforce-ux/4-major-patterns-for-accessible-drag-and-drop-1d43f64ebf09
21
- const styles = {
22
- position: "absolute",
23
- margin: "-1px",
24
- width: "1px",
25
- height: "1px",
26
- overflow: "hidden",
27
- clip: "rect(0 0 0 0)",
28
- };
29
- const getDefaultLabel = (dnd, assistiveState, hotkeys) => {
30
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
31
- if (!hotkeys.startDrag)
32
- return ""; // No hotkey feature configured
33
- const itemNames = (_b = (_a = dnd === null || dnd === void 0 ? void 0 : dnd.draggedItems) === null || _a === void 0 ? void 0 : _a.map((item) => item.getItemName()).join(", ")) !== null && _b !== void 0 ? _b : "";
34
- const position = !(dnd === null || dnd === void 0 ? void 0 : dnd.dragTarget)
35
- ? "None"
36
- : "childIndex" in dnd.dragTarget
37
- ? `${dnd.dragTarget.childIndex} of ${dnd.dragTarget.item.getChildren().length} in ${dnd.dragTarget.item.getItemName()}`
38
- : `in ${dnd.dragTarget.item.getItemName()}`;
39
- const navGuide = `Press ${(_c = hotkeys.dragUp) === null || _c === void 0 ? void 0 : _c.hotkey} and ${(_d = hotkeys.dragDown) === null || _d === void 0 ? void 0 : _d.hotkey} to move up or down, ` +
40
- `${(_e = hotkeys.completeDrag) === null || _e === void 0 ? void 0 : _e.hotkey} to drop, ${(_f = hotkeys.cancelDrag) === null || _f === void 0 ? void 0 : _f.hotkey} to abort.`;
41
- switch (assistiveState) {
42
- case core_1.AssistiveDndState.Started:
43
- return itemNames
44
- ? `Dragging ${itemNames}. Current position: ${position}. ${navGuide}`
45
- : `Current position: ${position}. ${navGuide}`;
46
- case core_1.AssistiveDndState.Dragging:
47
- return itemNames ? `${itemNames}, ${position}` : position;
48
- case core_1.AssistiveDndState.Completed:
49
- return `Drag completed. Press ${(_g = hotkeys.startDrag) === null || _g === void 0 ? void 0 : _g.hotkey} to move selected items`;
50
- case core_1.AssistiveDndState.Aborted:
51
- return `Drag cancelled. Press ${(_h = hotkeys.startDrag) === null || _h === void 0 ? void 0 : _h.hotkey} to move selected items`;
52
- case core_1.AssistiveDndState.None:
53
- default:
54
- return `Press ${(_j = hotkeys.startDrag) === null || _j === void 0 ? void 0 : _j.hotkey} to move selected items`;
55
- }
56
- };
57
- const AssistiveTreeDescription = (_a) => {
58
- var _b;
59
- var { tree, getLabel = getDefaultLabel } = _a, props = __rest(_a, ["tree", "getLabel"]);
60
- const state = tree.getState();
61
- return (react_1.default.createElement("span", Object.assign({ "aria-live": "assertive" }, props, { style: Object.assign(Object.assign({}, styles), props.style) }), getLabel(state.dnd, (_b = state.assistiveDndState) !== null && _b !== void 0 ? _b : core_1.AssistiveDndState.None, tree.getHotkeyPresets())));
62
- };
63
- exports.AssistiveTreeDescription = AssistiveTreeDescription;
@@ -1,2 +0,0 @@
1
- export * from "./assistive-tree-description";
2
- export * from "./use-tree";
package/lib/cjs/index.js DELETED
@@ -1,18 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./assistive-tree-description"), exports);
18
- __exportStar(require("./use-tree"), exports);
@@ -1,2 +0,0 @@
1
- import { TreeConfig } from "@headless-tree/core";
2
- export declare const useTree: <T>(config: TreeConfig<T>) => import("@headless-tree/core").TreeInstance<T>;
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useTree = void 0;
4
- const react_1 = require("react");
5
- const core_1 = require("@headless-tree/core");
6
- const useTree = (config) => {
7
- const [tree] = (0, react_1.useState)(() => ({ current: (0, core_1.createTree)(config) }));
8
- const [state, setState] = (0, react_1.useState)(() => tree.current.getState());
9
- (0, react_1.useEffect)(() => {
10
- tree.current.rebuildTree();
11
- }, [tree]); // runs only once after mount
12
- (0, react_1.useInsertionEffect)(() => {
13
- tree.current.setConfig((prev) => (Object.assign(Object.assign(Object.assign({}, prev), config), { state: Object.assign(Object.assign({}, state), config.state), setState: (state) => {
14
- var _a;
15
- setState(state);
16
- (_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state);
17
- } })));
18
- });
19
- return tree.current;
20
- };
21
- exports.useTree = useTree;
@@ -1,8 +0,0 @@
1
- import React, { HTMLProps } from "react";
2
- import { AssistiveDndState, DndState, HotkeysConfig, TreeInstance } from "@headless-tree/core";
3
- declare const getDefaultLabel: <T>(dnd: DndState<T> | null | undefined, assistiveState: AssistiveDndState, hotkeys: HotkeysConfig<T>) => string;
4
- export declare const AssistiveTreeDescription: <T>({ tree, getLabel, ...props }: {
5
- tree: TreeInstance<T>;
6
- getLabel?: typeof getDefaultLabel;
7
- } & HTMLProps<HTMLSpanElement>) => React.JSX.Element;
8
- export {};
@@ -1,56 +0,0 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
- import React from "react";
13
- import { AssistiveDndState, } from "@headless-tree/core";
14
- // https://medium.com/salesforce-ux/4-major-patterns-for-accessible-drag-and-drop-1d43f64ebf09
15
- const styles = {
16
- position: "absolute",
17
- margin: "-1px",
18
- width: "1px",
19
- height: "1px",
20
- overflow: "hidden",
21
- clip: "rect(0 0 0 0)",
22
- };
23
- const getDefaultLabel = (dnd, assistiveState, hotkeys) => {
24
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
25
- if (!hotkeys.startDrag)
26
- return ""; // No hotkey feature configured
27
- const itemNames = (_b = (_a = dnd === null || dnd === void 0 ? void 0 : dnd.draggedItems) === null || _a === void 0 ? void 0 : _a.map((item) => item.getItemName()).join(", ")) !== null && _b !== void 0 ? _b : "";
28
- const position = !(dnd === null || dnd === void 0 ? void 0 : dnd.dragTarget)
29
- ? "None"
30
- : "childIndex" in dnd.dragTarget
31
- ? `${dnd.dragTarget.childIndex} of ${dnd.dragTarget.item.getChildren().length} in ${dnd.dragTarget.item.getItemName()}`
32
- : `in ${dnd.dragTarget.item.getItemName()}`;
33
- const navGuide = `Press ${(_c = hotkeys.dragUp) === null || _c === void 0 ? void 0 : _c.hotkey} and ${(_d = hotkeys.dragDown) === null || _d === void 0 ? void 0 : _d.hotkey} to move up or down, ` +
34
- `${(_e = hotkeys.completeDrag) === null || _e === void 0 ? void 0 : _e.hotkey} to drop, ${(_f = hotkeys.cancelDrag) === null || _f === void 0 ? void 0 : _f.hotkey} to abort.`;
35
- switch (assistiveState) {
36
- case AssistiveDndState.Started:
37
- return itemNames
38
- ? `Dragging ${itemNames}. Current position: ${position}. ${navGuide}`
39
- : `Current position: ${position}. ${navGuide}`;
40
- case AssistiveDndState.Dragging:
41
- return itemNames ? `${itemNames}, ${position}` : position;
42
- case AssistiveDndState.Completed:
43
- return `Drag completed. Press ${(_g = hotkeys.startDrag) === null || _g === void 0 ? void 0 : _g.hotkey} to move selected items`;
44
- case AssistiveDndState.Aborted:
45
- return `Drag cancelled. Press ${(_h = hotkeys.startDrag) === null || _h === void 0 ? void 0 : _h.hotkey} to move selected items`;
46
- case AssistiveDndState.None:
47
- default:
48
- return `Press ${(_j = hotkeys.startDrag) === null || _j === void 0 ? void 0 : _j.hotkey} to move selected items`;
49
- }
50
- };
51
- export const AssistiveTreeDescription = (_a) => {
52
- var _b;
53
- var { tree, getLabel = getDefaultLabel } = _a, props = __rest(_a, ["tree", "getLabel"]);
54
- const state = tree.getState();
55
- return (React.createElement("span", Object.assign({ "aria-live": "assertive" }, props, { style: Object.assign(Object.assign({}, styles), props.style) }), getLabel(state.dnd, (_b = state.assistiveDndState) !== null && _b !== void 0 ? _b : AssistiveDndState.None, tree.getHotkeyPresets())));
56
- };
@@ -1,2 +0,0 @@
1
- export * from "./assistive-tree-description";
2
- export * from "./use-tree";
package/lib/esm/index.js DELETED
@@ -1,2 +0,0 @@
1
- export * from "./assistive-tree-description";
2
- export * from "./use-tree";
@@ -1,2 +0,0 @@
1
- import { TreeConfig } from "@headless-tree/core";
2
- export declare const useTree: <T>(config: TreeConfig<T>) => import("@headless-tree/core").TreeInstance<T>;
@@ -1,17 +0,0 @@
1
- import { useEffect, useInsertionEffect, useState } from "react";
2
- import { createTree } from "@headless-tree/core";
3
- export const useTree = (config) => {
4
- const [tree] = useState(() => ({ current: createTree(config) }));
5
- const [state, setState] = useState(() => tree.current.getState());
6
- useEffect(() => {
7
- tree.current.rebuildTree();
8
- }, [tree]); // runs only once after mount
9
- useInsertionEffect(() => {
10
- tree.current.setConfig((prev) => (Object.assign(Object.assign(Object.assign({}, prev), config), { state: Object.assign(Object.assign({}, state), config.state), setState: (state) => {
11
- var _a;
12
- setState(state);
13
- (_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state);
14
- } })));
15
- });
16
- return tree.current;
17
- };