diff --git a/docs/src/pages/components/RecursiveList.svx b/docs/src/pages/components/RecursiveList.svx
index d5941bdafe..fba581d110 100644
--- a/docs/src/pages/components/RecursiveList.svx
+++ b/docs/src/pages/components/RecursiveList.svx
@@ -37,4 +37,11 @@ Set `type` to `"ordered"` to use the ordered list variant.
Set `type` to `"ordered-native"` to use the native styles for an ordered list.
-
\ No newline at end of file
+
+
+## Flat data structure
+
+If working with a flat data structure, use the `toHierarchy` utility
+to convert a flat data structure into a hierarchical array accepted by the `nodes` prop.
+
+
diff --git a/docs/src/pages/framed/RecursiveList/RecursiveListFlatArray.svelte b/docs/src/pages/framed/RecursiveList/RecursiveListFlatArray.svelte
new file mode 100644
index 0000000000..356ffb45d1
--- /dev/null
+++ b/docs/src/pages/framed/RecursiveList/RecursiveListFlatArray.svelte
@@ -0,0 +1,20 @@
+
+
+ node.pid)} />
diff --git a/src/TreeView/index.d.ts b/src/TreeView/index.d.ts
index 52e3204e61..59f96be0f3 100644
--- a/src/TreeView/index.d.ts
+++ b/src/TreeView/index.d.ts
@@ -1,2 +1 @@
export { default as TreeView } from "./TreeView.svelte";
-export { toHierarchy } from "./treeview";
diff --git a/src/TreeView/index.js b/src/TreeView/index.js
index 52e3204e61..59f96be0f3 100644
--- a/src/TreeView/index.js
+++ b/src/TreeView/index.js
@@ -1,2 +1 @@
export { default as TreeView } from "./TreeView.svelte";
-export { toHierarchy } from "./treeview";
diff --git a/src/index.js b/src/index.js
index 75a2c8dcc9..e28120a430 100644
--- a/src/index.js
+++ b/src/index.js
@@ -127,7 +127,6 @@ export { Tooltip, TooltipFooter } from "./Tooltip";
export { TooltipDefinition } from "./TooltipDefinition";
export { TooltipIcon } from "./TooltipIcon";
export { TreeView } from "./TreeView";
-export { toHierarchy } from "./TreeView/treeview";
export { Truncate } from "./Truncate";
export { default as truncate } from "./Truncate/truncate";
export {
@@ -153,3 +152,4 @@ export {
HeaderSearch,
} from "./UIShell";
export { UnorderedList } from "./UnorderedList";
+export { toHierarchy } from "./utils/toHierarchy";
diff --git a/src/TreeView/treeview.d.ts b/src/utils/toHierarchy.d.ts
similarity index 94%
rename from src/TreeView/treeview.d.ts
rename to src/utils/toHierarchy.d.ts
index 61655606e9..a805f8999c 100644
--- a/src/TreeView/treeview.d.ts
+++ b/src/utils/toHierarchy.d.ts
@@ -17,3 +17,5 @@ export function toHierarchy<
*/
getParentId: (node: T) => T[K] | null,
): (T & { nodes?: (T & { nodes?: T[] })[] })[];
+
+export default toHierarchy;
diff --git a/src/TreeView/treeview.js b/src/utils/toHierarchy.js
similarity index 98%
rename from src/TreeView/treeview.js
rename to src/utils/toHierarchy.js
index 8e13743f86..a0e7f32c17 100644
--- a/src/TreeView/treeview.js
+++ b/src/utils/toHierarchy.js
@@ -47,3 +47,5 @@ export function toHierarchy(flatArray, getParentId) {
return tree;
}
+
+export default toHierarchy;
diff --git a/tests/RecursiveList/RecursiveList.hierarchy.test.svelte b/tests/RecursiveList/RecursiveList.hierarchy.test.svelte
new file mode 100644
index 0000000000..ec44d23732
--- /dev/null
+++ b/tests/RecursiveList/RecursiveList.hierarchy.test.svelte
@@ -0,0 +1,24 @@
+
+
+
diff --git a/tests/RecursiveList.test.svelte b/tests/RecursiveList/RecursiveList.test.svelte
similarity index 83%
rename from tests/RecursiveList.test.svelte
rename to tests/RecursiveList/RecursiveList.test.svelte
index 4aeda09427..cb1e9f980d 100644
--- a/tests/RecursiveList.test.svelte
+++ b/tests/RecursiveList/RecursiveList.test.svelte
@@ -14,18 +14,14 @@
{
text: "Item 2",
nodes: [
- {
- href: "https://svelte.dev/",
- },
+ { href: "https://svelte.dev/" },
{
href: "https://svelte.dev/",
text: "Link with custom text",
},
],
},
- {
- text: "Item 3",
- },
+ { text: "Item 3" },
];
diff --git a/tests/RecursiveList/RecursiveList.test.ts b/tests/RecursiveList/RecursiveList.test.ts
new file mode 100644
index 0000000000..1614c1545a
--- /dev/null
+++ b/tests/RecursiveList/RecursiveList.test.ts
@@ -0,0 +1,47 @@
+import { render, screen } from "@testing-library/svelte";
+import RecursiveListHierarchyTest from "./RecursiveList.hierarchy.test.svelte";
+import RecursiveListTest from "./RecursiveList.test.svelte";
+
+const testCases = [
+ { name: "RecursiveList", component: RecursiveListTest },
+ { name: "RecursiveList hierarchy", component: RecursiveListHierarchyTest },
+];
+
+describe.each(testCases)("$name", ({ component }) => {
+ it("renders all top-level items", () => {
+ render(component);
+
+ expect(screen.getByText("Item 1")).toBeInTheDocument();
+ expect(screen.getByText("Item 2")).toBeInTheDocument();
+ expect(screen.getByText("Item 3")).toBeInTheDocument();
+
+ expect(screen.getAllByRole("list")).toHaveLength(4);
+
+ // Nested items
+ expect(screen.getByText("Item 1a")).toBeInTheDocument();
+ });
+
+ it("renders HTML content", () => {
+ render(component);
+
+ const htmlContent = screen.getByText("HTML content");
+ expect(htmlContent.tagName).toBe("H5");
+ });
+
+ it("renders links correctly", () => {
+ render(component);
+
+ const links = screen.getAllByRole("link");
+ expect(links).toHaveLength(2);
+
+ // Link with custom text
+ const customLink = screen.getByText("Link with custom text");
+ expect(customLink).toHaveAttribute("href", "https://svelte.dev/");
+
+ // Plain link
+ const plainLink = links.find(
+ (link) => link.textContent === "https://svelte.dev/",
+ );
+ expect(plainLink).toHaveAttribute("href", "https://svelte.dev/");
+ });
+});
diff --git a/tests/TreeView/TreeView.hierarchy.test.svelte b/tests/TreeView/TreeView.hierarchy.test.svelte
index 86d2c62fe7..492a33e38b 100644
--- a/tests/TreeView/TreeView.hierarchy.test.svelte
+++ b/tests/TreeView/TreeView.hierarchy.test.svelte
@@ -1,6 +1,6 @@