@headless-tree/core 0.0.0-20250415151520 → 0.0.0-20250426164105

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,6 +1,12 @@
1
1
  # @headless-tree/core
2
2
 
3
- ## 0.0.0-20250415151520
3
+ ## 0.0.0-20250426164105
4
+
5
+ ### Patch Changes
6
+
7
+ - 6ed84b4: recursive item references are filtered out when rendering (#89)
8
+
9
+ ## 1.0.0
4
10
 
5
11
  ### Minor Changes
6
12
 
@@ -30,7 +30,6 @@ exports.hotkeysCoreFeature = {
30
30
  (_a = (_e = data.current).pressedKeys) !== null && _a !== void 0 ? _a : (_e.pressedKeys = new Set());
31
31
  const newMatch = !data.current.pressedKeys.has(e.key);
32
32
  data.current.pressedKeys.add(e.key);
33
- console.log("HOTKEYS", data.current.pressedKeys);
34
33
  const hotkeyName = findHotkeyMatch(data.current.pressedKeys, tree, tree.getHotkeyPresets(), tree.getConfig().hotkeys);
35
34
  if (!hotkeyName)
36
35
  return;
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.treeFeature = void 0;
13
13
  const utils_1 = require("../../utils");
14
+ const errors_1 = require("../../utilities/errors");
14
15
  exports.treeFeature = {
15
16
  key: "tree",
16
17
  getInitialState: (initialState) => (Object.assign({ expandedItems: [], focusedItem: null }, initialState)),
@@ -25,13 +26,17 @@ exports.treeFeature = {
25
26
  const { expandedItems } = tree.getState();
26
27
  const flatItems = [];
27
28
  const expandedItemsSet = new Set(expandedItems); // TODO support setting state expandedItems as set instead of array
28
- const recursiveAdd = (itemId, parentId, level, setSize, posInSet) => {
29
+ const recursiveAdd = (itemId, path, level, setSize, posInSet) => {
29
30
  var _a;
31
+ if (path.includes(itemId)) {
32
+ (0, errors_1.logWarning)(`Circular reference for ${path.join(".")}`);
33
+ return;
34
+ }
30
35
  flatItems.push({
31
36
  itemId,
32
37
  level,
33
38
  index: flatItems.length,
34
- parentId,
39
+ parentId: path.at(-1),
35
40
  setSize,
36
41
  posInSet,
37
42
  });
@@ -39,14 +44,14 @@ exports.treeFeature = {
39
44
  const children = (_a = tree.retrieveChildrenIds(itemId)) !== null && _a !== void 0 ? _a : [];
40
45
  let i = 0;
41
46
  for (const childId of children) {
42
- recursiveAdd(childId, itemId, level + 1, children.length, i++);
47
+ recursiveAdd(childId, path.concat(itemId), level + 1, children.length, i++);
43
48
  }
44
49
  }
45
50
  };
46
51
  const children = tree.retrieveChildrenIds(rootItemId);
47
52
  let i = 0;
48
53
  for (const itemId of children) {
49
- recursiveAdd(itemId, rootItemId, 0, children.length, i++);
54
+ recursiveAdd(itemId, [rootItemId], 0, children.length, i++);
50
55
  }
51
56
  return flatItems;
52
57
  },
@@ -1 +1,2 @@
1
1
  export declare const throwError: (message: string) => Error;
2
+ export declare const logWarning: (message: string) => void;
@@ -1,5 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.throwError = void 0;
4
- const throwError = (message) => Error(`Headless Tree: ${message}`);
3
+ exports.logWarning = exports.throwError = void 0;
4
+ const prefix = "Headless Tree: ";
5
+ const throwError = (message) => Error(prefix + message);
5
6
  exports.throwError = throwError;
7
+ // eslint-disable-next-line no-console
8
+ const logWarning = (message) => console.warn(prefix + message);
9
+ exports.logWarning = logWarning;
@@ -27,7 +27,6 @@ export const hotkeysCoreFeature = {
27
27
  (_a = (_e = data.current).pressedKeys) !== null && _a !== void 0 ? _a : (_e.pressedKeys = new Set());
28
28
  const newMatch = !data.current.pressedKeys.has(e.key);
29
29
  data.current.pressedKeys.add(e.key);
30
- console.log("HOTKEYS", data.current.pressedKeys);
31
30
  const hotkeyName = findHotkeyMatch(data.current.pressedKeys, tree, tree.getHotkeyPresets(), tree.getConfig().hotkeys);
32
31
  if (!hotkeyName)
33
32
  return;
@@ -8,6 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { makeStateUpdater, poll } from "../../utils";
11
+ import { logWarning } from "../../utilities/errors";
11
12
  export const treeFeature = {
12
13
  key: "tree",
13
14
  getInitialState: (initialState) => (Object.assign({ expandedItems: [], focusedItem: null }, initialState)),
@@ -22,13 +23,17 @@ export const treeFeature = {
22
23
  const { expandedItems } = tree.getState();
23
24
  const flatItems = [];
24
25
  const expandedItemsSet = new Set(expandedItems); // TODO support setting state expandedItems as set instead of array
25
- const recursiveAdd = (itemId, parentId, level, setSize, posInSet) => {
26
+ const recursiveAdd = (itemId, path, level, setSize, posInSet) => {
26
27
  var _a;
28
+ if (path.includes(itemId)) {
29
+ logWarning(`Circular reference for ${path.join(".")}`);
30
+ return;
31
+ }
27
32
  flatItems.push({
28
33
  itemId,
29
34
  level,
30
35
  index: flatItems.length,
31
- parentId,
36
+ parentId: path.at(-1),
32
37
  setSize,
33
38
  posInSet,
34
39
  });
@@ -36,14 +41,14 @@ export const treeFeature = {
36
41
  const children = (_a = tree.retrieveChildrenIds(itemId)) !== null && _a !== void 0 ? _a : [];
37
42
  let i = 0;
38
43
  for (const childId of children) {
39
- recursiveAdd(childId, itemId, level + 1, children.length, i++);
44
+ recursiveAdd(childId, path.concat(itemId), level + 1, children.length, i++);
40
45
  }
41
46
  }
42
47
  };
43
48
  const children = tree.retrieveChildrenIds(rootItemId);
44
49
  let i = 0;
45
50
  for (const itemId of children) {
46
- recursiveAdd(itemId, rootItemId, 0, children.length, i++);
51
+ recursiveAdd(itemId, [rootItemId], 0, children.length, i++);
47
52
  }
48
53
  return flatItems;
49
54
  },
@@ -1 +1,2 @@
1
1
  export declare const throwError: (message: string) => Error;
2
+ export declare const logWarning: (message: string) => void;
@@ -1 +1,4 @@
1
- export const throwError = (message) => Error(`Headless Tree: ${message}`);
1
+ const prefix = "Headless Tree: ";
2
+ export const throwError = (message) => Error(prefix + message);
3
+ // eslint-disable-next-line no-console
4
+ export const logWarning = (message) => console.warn(prefix + message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-tree/core",
3
- "version": "0.0.0-20250415151520",
3
+ "version": "0.0.0-20250426164105",
4
4
  "type": "module",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/esm/index.js",
@@ -48,7 +48,6 @@ export const hotkeysCoreFeature: FeatureImplementation = {
48
48
  data.current.pressedKeys ??= new Set();
49
49
  const newMatch = !data.current.pressedKeys.has(e.key);
50
50
  data.current.pressedKeys.add(e.key);
51
- console.log("HOTKEYS", data.current.pressedKeys);
52
51
 
53
52
  const hotkeyName = findHotkeyMatch(
54
53
  data.current.pressedKeys,
@@ -22,7 +22,7 @@ export type SearchFeatureDef<T> = {
22
22
  closeSearch: () => void;
23
23
  isSearchOpen: () => boolean;
24
24
  getSearchValue: () => string;
25
- registerSearchInputElement: (element: HTMLInputElement | null) => void;
25
+ registerSearchInputElement: (element: HTMLInputElement | null) => void; // TODO remove
26
26
  getSearchInputElement: () => HTMLInputElement | null;
27
27
  getSearchInputElementProps: () => any;
28
28
  getSearchMatchingItems: () => ItemInstance<T>[];
@@ -1,6 +1,7 @@
1
1
  import { FeatureImplementation, ItemInstance } from "../../types/core";
2
2
  import { ItemMeta } from "./types";
3
3
  import { makeStateUpdater, poll } from "../../utils";
4
+ import { logWarning } from "../../utilities/errors";
4
5
 
5
6
  export const treeFeature: FeatureImplementation<any> = {
6
7
  key: "tree",
@@ -31,16 +32,21 @@ export const treeFeature: FeatureImplementation<any> = {
31
32
 
32
33
  const recursiveAdd = (
33
34
  itemId: string,
34
- parentId: string,
35
+ path: string[],
35
36
  level: number,
36
37
  setSize: number,
37
38
  posInSet: number,
38
39
  ) => {
40
+ if (path.includes(itemId)) {
41
+ logWarning(`Circular reference for ${path.join(".")}`);
42
+ return;
43
+ }
44
+
39
45
  flatItems.push({
40
46
  itemId,
41
47
  level,
42
48
  index: flatItems.length,
43
- parentId,
49
+ parentId: path.at(-1) as string,
44
50
  setSize,
45
51
  posInSet,
46
52
  });
@@ -49,7 +55,13 @@ export const treeFeature: FeatureImplementation<any> = {
49
55
  const children = tree.retrieveChildrenIds(itemId) ?? [];
50
56
  let i = 0;
51
57
  for (const childId of children) {
52
- recursiveAdd(childId, itemId, level + 1, children.length, i++);
58
+ recursiveAdd(
59
+ childId,
60
+ path.concat(itemId),
61
+ level + 1,
62
+ children.length,
63
+ i++,
64
+ );
53
65
  }
54
66
  }
55
67
  };
@@ -57,7 +69,7 @@ export const treeFeature: FeatureImplementation<any> = {
57
69
  const children = tree.retrieveChildrenIds(rootItemId);
58
70
  let i = 0;
59
71
  for (const itemId of children) {
60
- recursiveAdd(itemId, rootItemId, 0, children.length, i++);
72
+ recursiveAdd(itemId, [rootItemId], 0, children.length, i++);
61
73
  }
62
74
 
63
75
  return flatItems;
@@ -1,2 +1,6 @@
1
- export const throwError = (message: string) =>
2
- Error(`Headless Tree: ${message}`);
1
+ const prefix = "Headless Tree: ";
2
+
3
+ export const throwError = (message: string) => Error(prefix + message);
4
+
5
+ // eslint-disable-next-line no-console
6
+ export const logWarning = (message: string) => console.warn(prefix + message);