/** * Lets a screen put its primary action in the pane header, like the admin's * `usePageHeaderActions()` (resources/js/layouts/authenticated-layout/pageChrome.tsx). */ import { createContext, useContext, useEffect, useState } from 'react'; import type { ReactNode } from 'react'; const SetterContext = createContext< ( node: ReactNode ) => void >( () => undefined ); export interface HeaderActionsHostProps { children: ( actions: ReactNode ) => ReactNode; } /** Wraps the shell; hands the header whatever the current screen registered. */ export function HeaderActionsHost( { children }: HeaderActionsHostProps ) { const [ actions, setActions ] = useState< ReactNode >( null ); return { children( actions ) }; } /** * Register this screen's header action. Pass a memoised node, or one whose * identity changes only when it should: every change re-renders the header. */ export function usePageHeaderActions( node: ReactNode, deps: unknown[] = [] ): void { const set = useContext( SetterContext ); useEffect( () => { set( node ); return () => set( null ); // eslint-disable-next-line react-hooks/exhaustive-deps }, deps ); }