import React, { useEffect } from "react"; import { useController } from "@lit/react/use-controller.js"; import { ContextController, WeavyContext } from "@weavy/uikit-web"; import { Context } from "@weavy/uikit-web/dist/types/contexts/index.js"; /** * Hook to consume the Weavy context from the Weavy Web Components using the Context Community Protocol. * The useWeavyContext(ref) must be used with an element reference from any child from the DOM tree since it relies on standard events in the DOM. * * @see https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md * @param ref { (() => HTMLElement) | HTMLElement } - Reference object or function returning a reference object. The object needs to be placed in the DOM. * @param context { Context } - The context to use. Defaults to WeavyContext from uikit-web. * @returns Weavy instance * @example * import React, { useRef } from "react" * import { useWeavyContext } from "@weavy/uikit-react" * * export const MyComponent = () => { * const domRef = useRef(null) * const weavy = useWeavyContext(() => domRef.current) * * useEffect(() => { * if (weavy) { * console.log("We got weavy", weavy.version) * } * }, [weavy]) * * // ... * return ( * <> * * * ) * } */ export function useWeavyContext = typeof WeavyContext, TElement extends HTMLElement = HTMLElement>( ref: (() => TElement | null) | TElement | null, context?: TContext ) { // Using ref.current for backward compatibility only // eslint-disable-next-line react-hooks/refs const domRef = (typeof ref === "function" ? ref() : (ref && "current" in ref) ? ref.current as HTMLElement : ref) || undefined; const controller = useController( React, (host) => new ContextController(host, context ?? WeavyContext, domRef) ); useEffect(() => { if (domRef) { controller.setRef(domRef); } // eslint-disable-next-line react-hooks/refs }, [controller, domRef]); return controller.context?.value; } export type { Context };