Skip to content

Commit

Permalink
Make toHierarchy even more generic (reusable with RecursiveList)
Browse files Browse the repository at this point in the history
  • Loading branch information
metonym committed Dec 8, 2024
1 parent 1125970 commit d39fa97
Show file tree
Hide file tree
Showing 15 changed files with 111 additions and 14 deletions.
9 changes: 8 additions & 1 deletion docs/src/pages/components/RecursiveList.svx
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<FileSource src="/framed/RecursiveList/RecursiveListOrderedNative" />
<FileSource src="/framed/RecursiveList/RecursiveListOrderedNative" />

## 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.

<FileSource src="/framed/RecursiveList/RecursiveListFlatArray" />
20 changes: 20 additions & 0 deletions docs/src/pages/framed/RecursiveList/RecursiveListFlatArray.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script>
import { RecursiveList, toHierarchy } from "carbon-components-svelte";
const nodesFlat = [
{ id: 1, text: "Item 1" },
{ id: 2, text: "Item 1a", pid: 1 },
{ id: 3, html: "<h5>HTML content</h5>", pid: 2 },
{ id: 4, text: "Item 2" },
{ id: 5, href: "https://svelte.dev/", pid: 4 },
{
id: 6,
href: "https://svelte.dev/",
text: "Link with custom text",
pid: 4,
},
{ id: 7, text: "Item 3" },
];
</script>

<RecursiveList nodes={toHierarchy(nodesFlat, (node) => node.pid)} />
1 change: 0 additions & 1 deletion src/TreeView/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { default as TreeView } from "./TreeView.svelte";
export { toHierarchy } from "./treeview";
1 change: 0 additions & 1 deletion src/TreeView/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { default as TreeView } from "./TreeView.svelte";
export { toHierarchy } from "./treeview";
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -153,3 +152,4 @@ export {
HeaderSearch,
} from "./UIShell";
export { UnorderedList } from "./UnorderedList";
export { toHierarchy } from "./utils/toHierarchy";
2 changes: 2 additions & 0 deletions src/TreeView/treeview.d.ts → src/utils/toHierarchy.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ export function toHierarchy<
*/
getParentId: (node: T) => T[K] | null,
): (T & { nodes?: (T & { nodes?: T[] })[] })[];

export default toHierarchy;
2 changes: 2 additions & 0 deletions src/TreeView/treeview.js → src/utils/toHierarchy.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@ export function toHierarchy(flatArray, getParentId) {

return tree;
}

export default toHierarchy;
24 changes: 24 additions & 0 deletions tests/RecursiveList/RecursiveList.hierarchy.test.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script lang="ts">
import { RecursiveList } from "carbon-components-svelte";
import toHierarchy from "../../src/utils/toHierarchy";
let nodes = toHierarchy(
[
{ id: 1, text: "Item 1" },
{ id: 2, text: "Item 1a", pid: 1 },
{ id: 3, html: "<h5>HTML content</h5>", pid: 2 },
{ id: 4, text: "Item 2" },
{ id: 5, href: "https://svelte.dev/", pid: 4 },
{
id: 6,
href: "https://svelte.dev/",
text: "Link with custom text",
pid: 4,
},
{ id: 7, text: "Item 3" },
],
(node) => node.pid,
);
</script>

<RecursiveList type="ordered" {nodes} />
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
];
</script>

Expand Down
47 changes: 47 additions & 0 deletions tests/RecursiveList/RecursiveList.test.ts
Original file line number Diff line number Diff line change
@@ -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/");
});
});
2 changes: 1 addition & 1 deletion tests/TreeView/TreeView.hierarchy.test.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { Button, TreeView } from "carbon-components-svelte";
import { toHierarchy } from "../../src/TreeView/treeview";
import { toHierarchy } from "../../src/utils/toHierarchy";
import type { TreeNodeId } from "carbon-components-svelte/TreeView/TreeView.svelte";
import Analytics from "carbon-icons-svelte/lib/Analytics.svelte";
Expand Down
2 changes: 1 addition & 1 deletion tests/TreeView/to-hierarchy.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { toHierarchy } from "../../src/TreeView/treeview";
import { toHierarchy } from "../../src/utils/toHierarchy";

describe("toHierarchy", () => {
test("should create a flat hierarchy when no items have parents", () => {
Expand Down
1 change: 0 additions & 1 deletion types/TreeView/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { default as TreeView } from "./TreeView.svelte";
export { toHierarchy } from "./treeview";
2 changes: 1 addition & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ export { default as TooltipFooter } from "./Tooltip/TooltipFooter.svelte";
export { default as TooltipDefinition } from "./TooltipDefinition/TooltipDefinition.svelte";
export { default as TooltipIcon } from "./TooltipIcon/TooltipIcon.svelte";
export { default as TreeView } from "./TreeView/TreeView.svelte";
export { default as toHierarchy } from "./TreeView/treeview";
export { default as Truncate } from "./Truncate/Truncate.svelte";
export { default as truncate } from "./Truncate/truncate";
export { default as Header } from "./UIShell/Header.svelte";
Expand All @@ -167,3 +166,4 @@ export { default as SkipToContent } from "./UIShell/SkipToContent.svelte";
export { default as HeaderGlobalAction } from "./UIShell/HeaderGlobalAction.svelte";
export { default as HeaderSearch } from "./UIShell/HeaderSearch.svelte";
export { default as UnorderedList } from "./UnorderedList/UnorderedList.svelte";
export { default as toHierarchy } from "./utils/toHierarchy";
2 changes: 2 additions & 0 deletions types/TreeView/treeview.d.ts → types/utils/toHierarchy.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ export function toHierarchy<
*/
getParentId: (node: T) => T[K] | null,
): (T & { nodes?: (T & { nodes?: T[] })[] })[];

export default toHierarchy;

0 comments on commit d39fa97

Please sign in to comment.