diff --git a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx
index bb2bcb06a5..73fbb9e5a3 100644
--- a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx
+++ b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx
@@ -59,7 +59,9 @@ describe('useElementFilter', () => {
-
+
+
+
diff --git a/packages/core-plugin-api/src/extensions/useElementFilter.tsx b/packages/core-plugin-api/src/extensions/useElementFilter.tsx
index fef777cb95..e79d2ba508 100644
--- a/packages/core-plugin-api/src/extensions/useElementFilter.tsx
+++ b/packages/core-plugin-api/src/extensions/useElementFilter.tsx
@@ -84,6 +84,22 @@ class ElementCollection {
private readonly featureFlagsApi: FeatureFlagsApi,
) {}
+ /**
+ * Narrows the set of selected components by doing a deep traversal and
+ * only including those that have defined component data for the given `key`.
+ *
+ * Whether an element in the tree has component data set for the given key
+ * is determined by whether `getComponentData` returns undefined.
+ *
+ * The traversal does not continue deeper past elements that match the criteria,
+ * and it also includes the root children in the selection, meaning that if the,
+ * of all the currently selected elements contain data for the given key, this
+ * method is a no-op.
+ *
+ * If `withStrictError` is set, the resulting selection must be a full match, meaning
+ * there may be no elements that were excluded in the selection. If the selection
+ * is not a clean match, an error will be throw with `withStrictError` as the message.
+ */
selectByComponentData(query: { key: string; withStrictError?: string }) {
const selection = selectChildren(
this.node,
@@ -94,6 +110,10 @@ class ElementCollection {
return new ElementCollection(selection, this.featureFlagsApi);
}
+ /**
+ * Finds all elements using the same criteria as `selectByComponentData`, but
+ * returns the actual component data of each of those elements instead.
+ */
findComponentData(query: { key: string }): T[] {
const selection = selectChildren(
this.node,
@@ -105,6 +125,9 @@ class ElementCollection {
.filter((data: T | undefined): data is T => data !== undefined);
}
+ /**
+ * Returns all of the elements currently selected by this collection.
+ */
getElements(): Array<
ReactElement
> {
@@ -114,6 +137,22 @@ class ElementCollection {
}
}
+/**
+ * useElementFilter is a utility that helps you narrow down and retrieve data
+ * from a React element tree, typically operating on the `children` property
+ * passed in to a component. A common use-case is to construct declarative APIs
+ * where a React component defines its behavior based on its children, such as
+ * the relationship between `Routes` and `Route` in `react-router`.
+ *
+ * The purpose of this hook is similar to `React.Children.map`, and it expands upon
+ * it to also handle traversal of fragments and Backstage specific things like the
+ * `FeatureFlagged` component.
+ *
+ * The return value of the hook is computed by the provided filter function, but
+ * with added memoization based on the input `node`. If further memoization
+ * dependencies are used in the filter function, they should be added to the
+ * third `dependencies` argument, just like `useMemo`, `useEffect`, etc.
+ */
export function useElementFilter(
node: ReactNode,
filterFn: (arg: ElementCollection) => T,