@@ -7,7 +7,6 @@ import { GET_INTERNAL_SYMBOL, GET_INTERNAL_MATCH_SYMBOL } from "./_internal/cons
77import core from "./_internal/core" ;
88
99import { ComponentIdContext } from "@zenflux/react-commander/commands-context" ;
10-
1110import commandsManager from "@zenflux/react-commander/commands-manager" ;
1211
1312import type { DCommandArgs , DCommandComponentContextProps , DCommandIdArgs } from "@zenflux/react-commander/definitions" ;
@@ -204,3 +203,76 @@ export function useCommandId( commandName: string, opts?: { match?: string; inde
204203 return id ;
205204}
206205
206+ export function useScopedCommand ( commandName : string , opts ?: { match ?: string ; index ?: number } ) {
207+ const componentContext = React . useContext ( ComponentIdContext ) ;
208+ const fallbackId = React . useId ( ) ;
209+ const ownerId = componentContext ?. isSet ? componentContext . getNameUnique ( ) : ( "GLOBAL-" + fallbackId ) ;
210+
211+ const id = useCommandId ( commandName , opts ) ;
212+
213+ const run = React . useCallback ( ( args : DCommandArgs , callback ?: ( result : unknown ) => void ) => {
214+ if ( ! id ) return ;
215+ return commandsManager . run ( id , args , callback ) ;
216+ } , [ id ] ) ;
217+
218+ const hookScoped = React . useCallback ( (
219+ callback : ( result ?: unknown , args ?: DCommandArgs ) => void ,
220+ options ?: { __ignoreDuplicatedHookError ?: boolean }
221+ ) => {
222+ if ( ! id ) return { dispose : ( ) => void 0 } as any ;
223+ return commandsManager . hookScoped ( id , ownerId , callback , options ) ;
224+ } , [ id , ownerId ] ) ;
225+
226+ const unhookHandle = React . useCallback ( ( handle : { dispose : ( ) => void } ) => {
227+ commandsManager . unhookHandle ( handle as any ) ;
228+ } , [ ] ) ;
229+
230+ const hook = React . useCallback ( (
231+ callback : ( result ?: unknown , args ?: DCommandArgs ) => void ,
232+ options ?: { __ignoreDuplicatedHookError ?: boolean }
233+ ) => {
234+ if ( ! id ) return ;
235+ return commandsManager . hook ( id , callback , options ) ;
236+ } , [ id ] ) ;
237+
238+ const unhook = React . useCallback ( ( ) => {
239+ if ( ! id ) return ;
240+ commandsManager . unhook ( id ) ;
241+ } , [ id ] ) ;
242+
243+ return {
244+ id,
245+ run,
246+ hook,
247+ unhook,
248+ hookScoped,
249+ unhookHandle,
250+ } as const ;
251+ }
252+
253+ function toAdapterKey ( name : string ) : string {
254+ const last = name . split ( "/" ) . pop ( ) || name ;
255+ return last . charAt ( 0 ) . toLowerCase ( ) + last . slice ( 1 ) ;
256+ }
257+
258+ export function useCommands ( input : string [ ] | Record < string , string > ) {
259+ const entries = React . useMemo ( ( ) => {
260+ if ( Array . isArray ( input ) ) {
261+ return input . map ( ( name ) => [ toAdapterKey ( name ) , name ] as const ) ;
262+ }
263+ return Object . entries ( input ) ;
264+ } , [ input ] ) ;
265+
266+ const adapters = entries . map ( ( [ _key , name ] ) => useScopedCommand ( name ) ) ;
267+
268+ const result = React . useMemo ( ( ) => {
269+ const out : { [ k : string ] : ReturnType < typeof useScopedCommand > } = { } ;
270+ entries . forEach ( ( [ key ] , i ) => {
271+ out [ key ] = adapters [ i ] ;
272+ } ) ;
273+ return out ;
274+ } , [ entries , adapters ] ) ;
275+
276+ return result ;
277+ }
278+
0 commit comments