Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add toHierarchy utility for TreeView, RecursiveList #2072

Merged
merged 10 commits into from
Dec 9, 2024

Conversation

metonym
Copy link
Collaborator

@metonym metonym commented Dec 7, 2024

Based on #2069, as I'm unable to push directly to that outside PR. Closes #2069.

This adds a toHierarchy utility per @bhavers's suggestion.

Both TreeView and RecursiveList components have a nodes prop. The structure is hierarchical, where a node specifies "child" nodes via the nodes prop. However, data may often be flat, with a property specifying its parent node ID.

This adds a toHierarchy utility to easily convert a flat array of nodes into a shape acceptable by the recursive components. This utility is separated from any specific component both for reusability but also for performance. If unused, the utility should be tree-shaken from bundles.

The second, required argument is a callback to retrieve the parent ID value. It's generic as to not force using any specific key for the parent ID. However, id and nodes are required, as they match the prop shape for TreeView and RecursiveList.

Usage

import { toHierarchy } from "carbon-components-svelte";

toHierarchy(array, node => node.parentId);

TreeView

<script>
  import { TreeView, toHierarchy } from "carbon-components-svelte";
  import Analytics from "carbon-icons-svelte/lib/Analytics.svelte";

  let nodesFlat = [
    { id: 0, text: "AI / Machine learning", icon: Analytics },
    { id: 1, text: "Analytics" },
    { id: 2, text: "IBM Analytics Engine", pid: 1 },
    { id: 3, text: "Apache Spark", pid: 2 },
    { id: 4, text: "Hadoop", pid: 2 },
    { id: 5, text: "IBM Cloud SQL Query", pid: 1 },
    { id: 6, text: "IBM Db2 Warehouse on Cloud", pid: 1 },
    { id: 7, text: "Blockchain" },
    { id: 8, text: "IBM Blockchain Platform", pid: 7 },
    { id: 9, text: "Databases" },
    { id: 10, text: "IBM Cloud Databases for Elasticsearch", pid: 9 },
    { id: 11, text: "IBM Cloud Databases for Enterprise DB", pid: 9 },
    { id: 12, text: "IBM Cloud Databases for MongoDB", pid: 9 },
    { id: 13, text: "IBM Cloud Databases for PostgreSQL", pid: 9 },
    { id: 14, text: "Integration", disabled: true },
    { id: 15, text: "IBM API Connect", disabled: true, pid: 14 },
  ];
</script>

<TreeView
  labelText="Cloud Products"
  nodes={toHierarchy(nodesFlat, (node) => node.pid)}
/>

Implementation Details

  • Uses a Map for efficient child-parent relationship lookups
  • Handles both root-level and nested nodes appropriately
  • Validates parent existence to prevent orphaned references
  • Preserves original node properties while adding the nodes array where needed
  • toHierarchy uses TypeScript generics for type safety and DX
Screenshot 2024-12-08 at 1 54 18 PM

Additional Notes

  • carbon-preprocess-svelte will need to be re-indexed to optimize the import for toHierarchy. Otherwise, it will need to be directly imported to avoid slower development times (e.g., from "carbon-components-svelte/src/utility/toHierarchy")

@metonym metonym force-pushed the pr-2069-changes branch 6 times, most recently from 921b10e to 1754c6e Compare December 8, 2024 19:03
@metonym metonym marked this pull request as ready for review December 8, 2024 22:10
@metonym metonym force-pushed the pr-2069-changes branch 2 times, most recently from 2087302 to 7c59620 Compare December 9, 2024 02:48
Refactor `toHiearchy` to be more generic, performant

- Use callback to "pick" generic parent ID property instead of requiring that `pid` be hardcoded`
- Account for edge cases of an invalid parent ID
- Use Map to store node children for lookups
- Use one pass instead of removing empty nodes at the very end
- DX: use generics to type `toHierarchy`
- Make `toHierarchy` even more generic (reusable with `RecursiveList`)

Co-Authored-By: Bram <[email protected]>
@metonym metonym merged commit 48afd18 into master Dec 9, 2024
3 checks passed
@metonym metonym deleted the pr-2069-changes branch December 9, 2024 20:22
@metonym
Copy link
Collaborator Author

metonym commented Dec 10, 2024

Released in v0.87.0.

If using optimizeImports from carbon-preprocess-svelte, you'll need to upgrade to [email protected].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants