Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
import React, { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
|
|
/**
|
|
* Carries "the user clicked a virtual Layers row -- scroll that array item's
|
|
* card into view" from the Layers panel (left) to the array editors (right).
|
|
*
|
|
* Deliberately a request, not a command: consumers that don't implement
|
|
* scrolling simply ignore it. Selecting the parent node always happens in
|
|
* LayersPanel itself, so a click is useful even with no consumer at all.
|
|
*/
|
|
|
|
export interface LayerFocusRequest {
|
|
nodeId: string;
|
|
prop: string;
|
|
index: number;
|
|
/** Bumped on every request so an identical repeat still re-fires effects. */
|
|
nonce: number;
|
|
}
|
|
|
|
export interface LayerFocusValue {
|
|
focus: LayerFocusRequest | null;
|
|
requestFocus(nodeId: string, prop: string, index: number): void;
|
|
}
|
|
|
|
const LayerFocusContext = createContext<LayerFocusValue>({
|
|
focus: null,
|
|
requestFocus: () => {},
|
|
});
|
|
|
|
export const useLayerFocus = (): LayerFocusValue => useContext(LayerFocusContext);
|
|
|
|
export const LayerFocusProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
const [focus, setFocus] = useState<LayerFocusRequest | null>(null);
|
|
const nonceRef = useRef(0);
|
|
|
|
const requestFocus = useCallback((nodeId: string, prop: string, index: number) => {
|
|
nonceRef.current += 1;
|
|
setFocus({ nodeId, prop, index, nonce: nonceRef.current });
|
|
}, []);
|
|
|
|
const value = useMemo(() => ({ focus, requestFocus }), [focus, requestFocus]);
|
|
|
|
return <LayerFocusContext.Provider value={value}>{children}</LayerFocusContext.Provider>;
|
|
};
|