import { useGraphStore } from './use-graph-store';
import { util } from '@joint/core';
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector';
import type { GraphLink } from '../types/link-types';
import type { CellMap } from '../utils/cell/cell-map';
/**
* Default selector function to return all links.
* This function is used when no selector is provided.
* It simply returns the items passed to it.
* @param items - The items to select from.
* @returns - The selected items.
* @group utils
* @description
*/
function defaultSelector(items: CellMap): Link[] {
return items.map((item) => item) as Link[];
}
/**
* A hook to access the graph store's links.
*
* This hook returns the selected links from the graph store. It accepts:
* - a selector function, which extracts the desired portion from the links map.
* (By default, it returns all links.)
* - an optional `isEqual` function, used to compare previous and new values to prevent unnecessary re-renders.
*
* How it works:
* 1. The hook subscribes to the links of the graph store.
* 2. It retrieves the links and then applies the selector.
* 3. The `isEqual` comparator (defaulting to a deep comparison) checks if the selected value has really changed.
* @example
* ```ts
* // Using without a selector (returns all links):
* const links = useLinks();
* ```
* @example
* ```ts
* // Using with a selector (extract part of the links data):
* const linkIds = useLinks((links) => links.map(link => link.id));
* ```
* @example
* // Using with a custom isEqual function:
* ```ts
* const filteredLinks = useLinks(
* (links) => links,
* (prev, next) => prev.length === next.length
* );
* ```
* @group Hooks
* @param selector - A function to select a portion of the links.
* @param isEqual - A function to compare the previous and new values.
* @returns - The selected links.
*/
export function useLinks(
selector: (
items: CellMap
) => SelectorReturnType = defaultSelector as () => SelectorReturnType,
isEqual: (a: SelectorReturnType, b: SelectorReturnType) => boolean = util.isEqual
): SelectorReturnType {
const { subscribe, getLinks } = useGraphStore();
const typedGetLinks = getLinks as () => CellMap;
const elements = useSyncExternalStoreWithSelector(
subscribe,
typedGetLinks,
typedGetLinks,
selector,
isEqual
);
return elements;
}