@box/metadata-template-browser 2.3.31 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import{browserReducer,initialState}from"./reducer.js";import{BrowseStateContextProvider,BrowserActionsContextProvider,NavigationStateContextProvider,SearchStateContextProvider,SelectionStateContextProvider}from"./contexts.js";import{useReducer,useRef}from"react";import{jsx}from"react/jsx-runtime";function MetadataTemplateBrowserProvider({children,namespaceFQN,itemsService,eventService,initialSelectedTemplateId,canCreateAtRoot=!1,isNamespacesEnabled=!1}){let[state,dispatch]=useReducer(browserReducer,{...initialState,namespaceFQN,selectedTemplateId:initialSelectedTemplateId??null,canCreateInCurrentNamespace:canCreateAtRoot,canCreateAtRoot}),stateRef=useRef(state);stateRef.current=state;let itemsServiceRef=useRef(itemsService);itemsServiceRef.current=itemsService;let eventServiceRef=useRef(eventService);eventServiceRef.current=eventService;let isNamespacesEnabledRef=useRef(isNamespacesEnabled);return isNamespacesEnabledRef.current=isNamespacesEnabled,jsx(NavigationStateContextProvider,{namespaceFQN:state.namespaceFQN,path:state.path,canCreateInCurrentNamespace:state.canCreateInCurrentNamespace,children:jsx(BrowseStateContextProvider,{browseByFqn:state.browseByFqn,isFetching:state.isFetching,isFetchingMore:state.isFetchingMore,initialLoadError:state.initialLoadError,browseError:state.browseError,loadMoreError:state.loadMoreError,children:jsx(SearchStateContextProvider,{searchValue:state.searchValue,searchQuery:state.searchQuery,searchResults:state.searchResults,searchNextMarker:state.searchNextMarker,isFetchingSearch:state.isFetchingSearch,searchError:state.searchError,children:jsx(SelectionStateContextProvider,{selectedTemplateId:state.selectedTemplateId,children:jsx(BrowserActionsContextProvider,{itemsServiceRef,eventServiceRef,isNamespacesEnabledRef,stateRef,dispatch,children})})})})})}export{MetadataTemplateBrowserProvider};
1
+ import{browserReducer,initialState}from"./reducer.js";import{BrowseStateContextProvider,BrowserActionsContextProvider,NavigationStateContextProvider,SearchStateContextProvider,SelectionStateContextProvider}from"./contexts.js";import{useReducer,useRef}from"react";import{jsx}from"react/jsx-runtime";function MetadataTemplateBrowserProvider({children,namespaceFQN,itemsService,eventService,initialSelectedTemplateId,initialNavigation,canCreateAtRoot=!1,isNamespacesEnabled=!1}){let[state,dispatch]=useReducer(browserReducer,{...initialState,namespaceFQN:initialNavigation?.namespaceFQN??namespaceFQN,path:initialNavigation?.path??[],selectedTemplateId:initialSelectedTemplateId??null,canCreateInCurrentNamespace:initialNavigation?.canCreateInCurrentNamespace??canCreateAtRoot,canCreateAtRoot}),stateRef=useRef(state);stateRef.current=state;let itemsServiceRef=useRef(itemsService);itemsServiceRef.current=itemsService;let eventServiceRef=useRef(eventService);eventServiceRef.current=eventService;let isNamespacesEnabledRef=useRef(isNamespacesEnabled);return isNamespacesEnabledRef.current=isNamespacesEnabled,jsx(NavigationStateContextProvider,{namespaceFQN:state.namespaceFQN,path:state.path,canCreateInCurrentNamespace:state.canCreateInCurrentNamespace,children:jsx(BrowseStateContextProvider,{browseByFqn:state.browseByFqn,isFetching:state.isFetching,isFetchingMore:state.isFetchingMore,initialLoadError:state.initialLoadError,browseError:state.browseError,loadMoreError:state.loadMoreError,children:jsx(SearchStateContextProvider,{searchValue:state.searchValue,searchQuery:state.searchQuery,searchResults:state.searchResults,searchNextMarker:state.searchNextMarker,isFetchingSearch:state.isFetchingSearch,searchError:state.searchError,children:jsx(SelectionStateContextProvider,{selectedTemplateId:state.selectedTemplateId,children:jsx(BrowserActionsContextProvider,{itemsServiceRef,eventServiceRef,isNamespacesEnabledRef,stateRef,dispatch,children})})})})})}export{MetadataTemplateBrowserProvider};
@@ -1 +1 @@
1
- import{EMPTY_BROWSE_NODE}from"../constants.js";var BrowserActionType=function(BrowserActionType){return BrowserActionType.NavigateTo=`NAVIGATE_TO`,BrowserActionType.NavigateBack=`NAVIGATE_BACK`,BrowserActionType.BrowseFetchStart=`BROWSE_FETCH_START`,BrowserActionType.BrowseLoaded=`BROWSE_LOADED`,BrowserActionType.InitialLoadError=`INITIAL_LOAD_ERROR`,BrowserActionType.BrowseError=`BROWSE_ERROR`,BrowserActionType.BrowsePageCancelled=`BROWSE_PAGE_CANCELLED`,BrowserActionType.LoadMoreStart=`LOAD_MORE_START`,BrowserActionType.LoadMoreNamespacesLoaded=`LOAD_MORE_NAMESPACES_LOADED`,BrowserActionType.LoadMoreTemplatesLoaded=`LOAD_MORE_TEMPLATES_LOADED`,BrowserActionType.LoadMoreError=`LOAD_MORE_ERROR`,BrowserActionType.LoadMoreCancelled=`LOAD_MORE_CANCELLED`,BrowserActionType.SearchValueChange=`SEARCH_VALUE_CHANGE`,BrowserActionType.SearchFetchStart=`SEARCH_FETCH_START`,BrowserActionType.SearchLoaded=`SEARCH_LOADED`,BrowserActionType.SearchError=`SEARCH_ERROR`,BrowserActionType.SearchClear=`SEARCH_CLEAR`,BrowserActionType.LoadMoreSearchLoaded=`LOAD_MORE_SEARCH_LOADED`,BrowserActionType.TemplateSelect=`TEMPLATE_SELECT`,BrowserActionType.TemplateCreated=`TEMPLATE_CREATED`,BrowserActionType.TemplateUpdated=`TEMPLATE_UPDATED`,BrowserActionType}({}),initialState={namespaceFQN:``,path:[],canCreateInCurrentNamespace:!1,canCreateAtRoot:!1,browseByFqn:new Map,isFetching:!1,isFetchingMore:!1,initialLoadError:null,browseError:null,loadMoreError:null,searchValue:``,searchQuery:``,searchResults:[],searchNextMarker:void 0,isFetchingSearch:!1,searchError:null,selectedTemplateId:null};function resolveCanCreateForFqn(state,fqn){for(let node of state.browseByFqn.values()){let match=node.namespaces.find(namespace=>namespace.id===fqn);if(match)return match.canCreate??!1}return state.canCreateAtRoot}function mergeTemplates(existing,incoming){let incomingIds=new Set(incoming.map(template=>template.id));return[...existing.filter(template=>!incomingIds.has(template.id)),...incoming]}function appendUniqueTemplates(existing,incoming){let existingIds=new Set(existing.map(template=>template.id));return[...existing,...incoming.filter(template=>!existingIds.has(template.id))]}function setBrowseNode(browseByFqn,fqn,node){return new Map(browseByFqn).set(fqn,node)}function replaceTemplateById(templates,updated){let found=!1,next=templates.map(template=>template.id===updated.id?(found=!0,updated):template);return found?next:null}function browserReducer(state,action){switch(action.type){case`NAVIGATE_TO`:return{...state,namespaceFQN:action.namespace.id,path:[...state.path,{fqn:action.namespace.id,displayName:action.namespace.displayName}],canCreateInCurrentNamespace:action.namespace.canCreate??!1,initialLoadError:null,browseError:null,loadMoreError:null};case`NAVIGATE_BACK`:return state.browseByFqn.has(action.fqn)?{...state,namespaceFQN:action.fqn,path:state.path.filter(entry=>action.fqn===entry.fqn||action.fqn.startsWith(`${entry.fqn}.`)),canCreateInCurrentNamespace:resolveCanCreateForFqn(state,action.fqn),initialLoadError:null,browseError:null,loadMoreError:null}:state;case`BROWSE_FETCH_START`:return{...state,isFetching:!0,initialLoadError:null,browseError:null};case`BROWSE_PAGE_CANCELLED`:return{...state,isFetching:!1};case`BROWSE_LOADED`:{let previous=state.browseByFqn.get(state.namespaceFQN);return{...state,isFetching:!1,browseByFqn:setBrowseNode(state.browseByFqn,state.namespaceFQN,{namespaces:action.namespaces,namespaceNextMarker:action.namespaceNextMarker,isNamespacesExhausted:!action.namespaceNextMarker,templates:previous?mergeTemplates(previous.templates,action.templates):action.templates,templateNextMarker:action.templateNextMarker})}}case`INITIAL_LOAD_ERROR`:return{...state,isFetching:!1,initialLoadError:action.error};case`BROWSE_ERROR`:return{...state,isFetching:!1,browseError:action.error};case`LOAD_MORE_START`:return{...state,isFetchingMore:!0,loadMoreError:null};case`LOAD_MORE_NAMESPACES_LOADED`:{let current=state.browseByFqn.get(state.namespaceFQN)??EMPTY_BROWSE_NODE,namespacesExhausted=!action.nextMarker;return{...state,isFetchingMore:!1,browseByFqn:setBrowseNode(state.browseByFqn,state.namespaceFQN,{...current,namespaces:[...current.namespaces,...action.entries],namespaceNextMarker:action.nextMarker,isNamespacesExhausted:namespacesExhausted,...action.templates!==void 0&&{templates:mergeTemplates(current.templates,action.templates),templateNextMarker:action.templateNextMarker}})}}case`LOAD_MORE_TEMPLATES_LOADED`:{let current=state.browseByFqn.get(state.namespaceFQN)??EMPTY_BROWSE_NODE;return{...state,isFetchingMore:!1,browseByFqn:setBrowseNode(state.browseByFqn,state.namespaceFQN,{...current,templates:appendUniqueTemplates(current.templates,action.entries),templateNextMarker:action.nextMarker})}}case`LOAD_MORE_ERROR`:return{...state,isFetchingMore:!1,loadMoreError:action.error};case`LOAD_MORE_CANCELLED`:return{...state,isFetchingMore:!1,loadMoreError:null};case`SEARCH_VALUE_CHANGE`:return{...state,searchValue:action.value};case`SEARCH_FETCH_START`:return{...state,isFetchingSearch:!0,searchQuery:action.query,searchResults:[],searchNextMarker:void 0,searchError:null};case`SEARCH_LOADED`:return{...state,isFetchingSearch:!1,searchResults:action.results,searchNextMarker:action.nextMarker};case`SEARCH_ERROR`:return{...state,isFetchingSearch:!1,searchError:action.error};case`SEARCH_CLEAR`:return{...state,searchValue:``,searchQuery:``,searchResults:[],searchNextMarker:void 0,isFetchingSearch:!1,searchError:null};case`LOAD_MORE_SEARCH_LOADED`:return{...state,isFetchingMore:!1,searchResults:[...state.searchResults,...action.entries],searchNextMarker:action.nextMarker};case`TEMPLATE_SELECT`:return{...state,selectedTemplateId:action.template.id};case`TEMPLATE_CREATED`:{let node=state.browseByFqn.get(action.namespaceFQN);return node?{...state,browseByFqn:setBrowseNode(state.browseByFqn,action.namespaceFQN,{...node,templates:[action.template,...node.templates.filter(template=>template.id!==action.template.id)]})}:state}case`TEMPLATE_UPDATED`:{let browseChanged=!1,browseByFqn=new Map(state.browseByFqn);for(let[fqn,node]of state.browseByFqn){let templates=replaceTemplateById(node.templates,action.template);templates&&(browseByFqn.set(fqn,{...node,templates}),browseChanged=!0)}let searchResults=replaceTemplateById(state.searchResults,action.template);return!browseChanged&&searchResults===null?state:{...state,...browseChanged&&{browseByFqn},...searchResults!==null&&{searchResults}}}default:return state}}export{BrowserActionType,browserReducer,initialState};
1
+ import{EMPTY_BROWSE_NODE}from"../constants.js";var BrowserActionType=function(BrowserActionType){return BrowserActionType.NavigateTo=`NAVIGATE_TO`,BrowserActionType.NavigateBack=`NAVIGATE_BACK`,BrowserActionType.BrowseFetchStart=`BROWSE_FETCH_START`,BrowserActionType.BrowseLoaded=`BROWSE_LOADED`,BrowserActionType.InitialLoadError=`INITIAL_LOAD_ERROR`,BrowserActionType.BrowseError=`BROWSE_ERROR`,BrowserActionType.BrowsePageCancelled=`BROWSE_PAGE_CANCELLED`,BrowserActionType.LoadMoreStart=`LOAD_MORE_START`,BrowserActionType.LoadMoreNamespacesLoaded=`LOAD_MORE_NAMESPACES_LOADED`,BrowserActionType.LoadMoreTemplatesLoaded=`LOAD_MORE_TEMPLATES_LOADED`,BrowserActionType.LoadMoreError=`LOAD_MORE_ERROR`,BrowserActionType.LoadMoreCancelled=`LOAD_MORE_CANCELLED`,BrowserActionType.SearchValueChange=`SEARCH_VALUE_CHANGE`,BrowserActionType.SearchFetchStart=`SEARCH_FETCH_START`,BrowserActionType.SearchLoaded=`SEARCH_LOADED`,BrowserActionType.SearchError=`SEARCH_ERROR`,BrowserActionType.SearchClear=`SEARCH_CLEAR`,BrowserActionType.LoadMoreSearchLoaded=`LOAD_MORE_SEARCH_LOADED`,BrowserActionType.TemplateSelect=`TEMPLATE_SELECT`,BrowserActionType.TemplateCreated=`TEMPLATE_CREATED`,BrowserActionType.TemplateUpdated=`TEMPLATE_UPDATED`,BrowserActionType}({}),initialState={namespaceFQN:``,path:[],canCreateInCurrentNamespace:!1,canCreateAtRoot:!1,browseByFqn:new Map,isFetching:!1,isFetchingMore:!1,initialLoadError:null,browseError:null,loadMoreError:null,searchValue:``,searchQuery:``,searchResults:[],searchNextMarker:void 0,isFetchingSearch:!1,searchError:null,selectedTemplateId:null};function resolveCanCreateForFqn(state,fqn){let pathEntry=state.path.find(entry=>entry.fqn===fqn);if(pathEntry?.canCreate!==void 0)return pathEntry.canCreate;for(let node of state.browseByFqn.values()){let match=node.namespaces.find(namespace=>namespace.id===fqn);if(match)return match.canCreate??!1}return state.canCreateAtRoot}function mergeTemplates(existing,incoming){let incomingIds=new Set(incoming.map(template=>template.id));return[...existing.filter(template=>!incomingIds.has(template.id)),...incoming]}function appendUniqueTemplates(existing,incoming){let existingIds=new Set(existing.map(template=>template.id));return[...existing,...incoming.filter(template=>!existingIds.has(template.id))]}function setBrowseNode(browseByFqn,fqn,node){return new Map(browseByFqn).set(fqn,node)}function replaceTemplateById(templates,updated){let found=!1,next=templates.map(template=>template.id===updated.id?(found=!0,updated):template);return found?next:null}function browserReducer(state,action){switch(action.type){case`NAVIGATE_TO`:return{...state,namespaceFQN:action.namespace.id,path:[...state.path,{fqn:action.namespace.id,displayName:action.namespace.displayName,canCreate:action.namespace.canCreate}],canCreateInCurrentNamespace:action.namespace.canCreate??!1,initialLoadError:null,browseError:null,loadMoreError:null};case`NAVIGATE_BACK`:return{...state,namespaceFQN:action.fqn,path:state.path.filter(entry=>action.fqn===entry.fqn||action.fqn.startsWith(`${entry.fqn}.`)),canCreateInCurrentNamespace:resolveCanCreateForFqn(state,action.fqn),initialLoadError:null,browseError:null,loadMoreError:null};case`BROWSE_FETCH_START`:return{...state,isFetching:!0,initialLoadError:null,browseError:null};case`BROWSE_PAGE_CANCELLED`:return{...state,isFetching:!1};case`BROWSE_LOADED`:{let previous=state.browseByFqn.get(state.namespaceFQN);return{...state,isFetching:!1,browseByFqn:setBrowseNode(state.browseByFqn,state.namespaceFQN,{namespaces:action.namespaces,namespaceNextMarker:action.namespaceNextMarker,isNamespacesExhausted:!action.namespaceNextMarker,templates:previous?mergeTemplates(previous.templates,action.templates):action.templates,templateNextMarker:action.templateNextMarker})}}case`INITIAL_LOAD_ERROR`:return{...state,isFetching:!1,initialLoadError:action.error};case`BROWSE_ERROR`:return{...state,isFetching:!1,browseError:action.error};case`LOAD_MORE_START`:return{...state,isFetchingMore:!0,loadMoreError:null};case`LOAD_MORE_NAMESPACES_LOADED`:{let current=state.browseByFqn.get(state.namespaceFQN)??EMPTY_BROWSE_NODE,namespacesExhausted=!action.nextMarker;return{...state,isFetchingMore:!1,browseByFqn:setBrowseNode(state.browseByFqn,state.namespaceFQN,{...current,namespaces:[...current.namespaces,...action.entries],namespaceNextMarker:action.nextMarker,isNamespacesExhausted:namespacesExhausted,...action.templates!==void 0&&{templates:mergeTemplates(current.templates,action.templates),templateNextMarker:action.templateNextMarker}})}}case`LOAD_MORE_TEMPLATES_LOADED`:{let current=state.browseByFqn.get(state.namespaceFQN)??EMPTY_BROWSE_NODE;return{...state,isFetchingMore:!1,browseByFqn:setBrowseNode(state.browseByFqn,state.namespaceFQN,{...current,templates:appendUniqueTemplates(current.templates,action.entries),templateNextMarker:action.nextMarker})}}case`LOAD_MORE_ERROR`:return{...state,isFetchingMore:!1,loadMoreError:action.error};case`LOAD_MORE_CANCELLED`:return{...state,isFetchingMore:!1,loadMoreError:null};case`SEARCH_VALUE_CHANGE`:return{...state,searchValue:action.value};case`SEARCH_FETCH_START`:return{...state,isFetchingSearch:!0,searchQuery:action.query,searchResults:[],searchNextMarker:void 0,searchError:null};case`SEARCH_LOADED`:return{...state,isFetchingSearch:!1,searchResults:action.results,searchNextMarker:action.nextMarker};case`SEARCH_ERROR`:return{...state,isFetchingSearch:!1,searchError:action.error};case`SEARCH_CLEAR`:return{...state,searchValue:``,searchQuery:``,searchResults:[],searchNextMarker:void 0,isFetchingSearch:!1,searchError:null};case`LOAD_MORE_SEARCH_LOADED`:return{...state,isFetchingMore:!1,searchResults:[...state.searchResults,...action.entries],searchNextMarker:action.nextMarker};case`TEMPLATE_SELECT`:return{...state,selectedTemplateId:action.template.id};case`TEMPLATE_CREATED`:{let node=state.browseByFqn.get(action.namespaceFQN);return node?{...state,browseByFqn:setBrowseNode(state.browseByFqn,action.namespaceFQN,{...node,templates:[action.template,...node.templates.filter(template=>template.id!==action.template.id)]})}:state}case`TEMPLATE_UPDATED`:{let browseChanged=!1,browseByFqn=new Map(state.browseByFqn);for(let[fqn,node]of state.browseByFqn){let templates=replaceTemplateById(node.templates,action.template);templates&&(browseByFqn.set(fqn,{...node,templates}),browseChanged=!0)}let searchResults=replaceTemplateById(state.searchResults,action.template);return!browseChanged&&searchResults===null?state:{...state,...browseChanged&&{browseByFqn},...searchResults!==null&&{searchResults}}}default:return state}}export{BrowserActionType,browserReducer,initialState};
@@ -1 +1 @@
1
- import{EMPTY_BROWSE_NODE,emptyNamespacesResponse,emptyTemplatesResponse}from"../constants.js";import{BrowserActionType}from"./reducer.js";import{useMemo,useRef}from"react";import debounce from"lodash/debounce";var rejectOnAbort=signal=>new Promise((_,reject)=>{if(signal.aborted){reject(new DOMException(`Aborted`,`AbortError`));return}signal.addEventListener(`abort`,()=>reject(new DOMException(`Aborted`,`AbortError`)),{once:!0})}),callEventCallback=callback=>{try{let result=callback();result instanceof Promise&&result.catch(()=>void 0)}catch{}},runTemplateMutation=async operation=>{try{return await operation()}catch{return}},normalizeSearchQuery=value=>value.trim().replaceAll(/\s+/g,` `),getErrorMessage=error=>error instanceof Error?error.message:typeof error==`string`?error:`An unknown error occurred`,runAbortable=async(signal,fetchFn,onSuccess,onError)=>{try{let result=await fetchFn();signal.aborted||onSuccess(result)}catch(error){signal.aborted||onError(error)}},MISSING_GET_NAMESPACES_MESSAGE=`[MetadataTemplateBrowser] isNamespacesEnabled is true but itemsService.getNamespaces is not implemented. Provide getNamespaces on itemsService to load namespace folders.`;function useTemplateBrowserActions(itemsServiceRef,eventServiceRef,isNamespacesEnabledRef,stateRef,dispatch){let browsePageAbortControllerRef=useRef(null),browseLoadMoreAbortControllerRef=useRef(null),searchAbortControllerRef=useRef(null),hasLoggedMissingGetNamespacesRef=useRef(!1),abandonBrowsePage=()=>{browsePageAbortControllerRef.current?.abort(),browsePageAbortControllerRef.current=null,dispatch({type:BrowserActionType.BrowsePageCancelled})},abandonBrowseLoadMore=()=>{browseLoadMoreAbortControllerRef.current?.abort(),browseLoadMoreAbortControllerRef.current=null,dispatch({type:BrowserActionType.LoadMoreCancelled})},startBrowsePageRequest=()=>{browsePageAbortControllerRef.current?.abort();let controller=new AbortController;return browsePageAbortControllerRef.current=controller,controller.signal},startBrowseLoadMoreRequest=()=>{browseLoadMoreAbortControllerRef.current?.abort();let controller=new AbortController;return browseLoadMoreAbortControllerRef.current=controller,controller.signal},startSearchRequest=()=>{searchAbortControllerRef.current?.abort();let controller=new AbortController;return searchAbortControllerRef.current=controller,controller.signal},cancelSearchRequest=()=>{searchAbortControllerRef.current?.abort(),searchAbortControllerRef.current=null},debouncedSearchRef=useRef(debounce(async query=>{let signal=startSearchRequest();callEventCallback(()=>eventServiceRef.current.onSearchChange?.(query)),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0)),await runAbortable(signal,()=>fetchSearchResults(query,signal),response=>dispatch({type:BrowserActionType.SearchLoaded,results:response.entries,nextMarker:response.next_marker}),error=>dispatch({type:BrowserActionType.SearchError,error:getErrorMessage(error)})),signal.aborted||callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1))},500)),fetchNamespaces=(fqn,signal,marker)=>{if(!isNamespacesEnabledRef.current)return Promise.resolve(emptyNamespacesResponse);let fn=itemsServiceRef.current.getNamespaces;return fn?Promise.race([fn(fqn,{limit:200,marker,signal}),rejectOnAbort(signal)]):(hasLoggedMissingGetNamespacesRef.current||(hasLoggedMissingGetNamespacesRef.current=!0,typeof process<`u`&&process.env.NODE_ENV!==`production`&&console.warn(MISSING_GET_NAMESPACES_MESSAGE)),Promise.resolve(emptyNamespacesResponse))},fetchTemplates=(fqn,signal,marker)=>{let fn=itemsServiceRef.current.getTemplates;return fn?Promise.race([fn(fqn,{limit:200,marker,signal}),rejectOnAbort(signal)]):Promise.resolve(emptyTemplatesResponse)},fetchSearchResults=(query,signal,marker)=>{let fn=itemsServiceRef.current.getSearchResults;return fn?Promise.race([fn(query,{limit:200,marker,signal}),rejectOnAbort(signal)]):Promise.resolve(emptyTemplatesResponse)},dispatchError=(type,error)=>{dispatch({type,error:getErrorMessage(error)})},fetchBrowsePage=async(fqn,signal,errorAction)=>{let success=!1;return await runAbortable(signal,async()=>{let namespacesResponse=await fetchNamespaces(fqn,signal);return[namespacesResponse,namespacesResponse.next_marker?emptyTemplatesResponse:await fetchTemplates(fqn,signal)]},([namespacesResponse,templatesResponse])=>{dispatch({type:BrowserActionType.BrowseLoaded,namespaces:namespacesResponse.entries,namespaceNextMarker:namespacesResponse.next_marker,templates:templatesResponse.entries,templateNextMarker:templatesResponse.next_marker}),success=!0},error=>dispatchError(errorAction,error)),success},initialLoad=async()=>{let signal=startBrowsePageRequest(),{namespaceFQN}=stateRef.current;dispatch({type:BrowserActionType.BrowseFetchStart}),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0)),await fetchBrowsePage(namespaceFQN,signal,BrowserActionType.InitialLoadError),signal.aborted||callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1))},navigateTo=async namespace=>{abandonBrowseLoadMore();let signal=startBrowsePageRequest();dispatch({type:BrowserActionType.NavigateTo,namespace}),dispatch({type:BrowserActionType.BrowseFetchStart}),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0));let success=await fetchBrowsePage(namespace.id,signal,BrowserActionType.BrowseError);signal.aborted||(callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1)),success&&callEventCallback(()=>eventServiceRef.current.onNamespaceChange?.(namespace.id)))},navigateBack=fqn=>{stateRef.current.browseByFqn.has(fqn)&&(abandonBrowsePage(),abandonBrowseLoadMore(),dispatch({type:BrowserActionType.NavigateBack,fqn}),callEventCallback(()=>eventServiceRef.current.onNamespaceChange?.(fqn)))},setSearchValue=value=>{dispatch({type:BrowserActionType.SearchValueChange,value});let normalizedQuery=normalizeSearchQuery(value);if(normalizedQuery===``){debouncedSearchRef.current.cancel(),cancelSearchRequest(),abandonBrowseLoadMore(),dispatch({type:BrowserActionType.SearchClear}),callEventCallback(()=>eventServiceRef.current.onSearchChange?.(``)),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1));return}abandonBrowseLoadMore(),cancelSearchRequest(),dispatch({type:BrowserActionType.SearchFetchStart,query:normalizedQuery}),debouncedSearchRef.current(normalizedQuery)},loadMore=async()=>{let{namespaceFQN,searchQuery,searchNextMarker,browseByFqn}=stateRef.current,{namespaceNextMarker,templateNextMarker,isNamespacesExhausted}=browseByFqn.get(namespaceFQN)??EMPTY_BROWSE_NODE,isSearchMode=!!searchQuery,hasMoreSearchResults=isSearchMode&&!!searchNextMarker,hasMoreNamespaces=!isSearchMode&&!isNamespacesExhausted&&!!namespaceNextMarker,hasMoreTemplates=!isSearchMode&&!!templateNextMarker;if(!(hasMoreSearchResults||hasMoreNamespaces||hasMoreTemplates))return;dispatch({type:BrowserActionType.LoadMoreStart});let dispatchLoadMoreError=error=>{dispatch({type:BrowserActionType.LoadMoreError,error:getErrorMessage(error)})};if(hasMoreSearchResults){let signal=startSearchRequest();await runAbortable(signal,()=>fetchSearchResults(searchQuery,signal,searchNextMarker),response=>dispatch({type:BrowserActionType.LoadMoreSearchLoaded,entries:response.entries,nextMarker:response.next_marker}),dispatchLoadMoreError);return}if(hasMoreNamespaces){let signal=startBrowseLoadMoreRequest();await runAbortable(signal,async()=>{let namespacesResponse=await fetchNamespaces(namespaceFQN,signal,namespaceNextMarker);return[namespacesResponse,namespacesResponse.next_marker?emptyTemplatesResponse:await fetchTemplates(namespaceFQN,signal)]},([namespacesResponse,templatesResponse])=>{let namespacesExhausted=!namespacesResponse.next_marker;dispatch({type:BrowserActionType.LoadMoreNamespacesLoaded,entries:namespacesResponse.entries,nextMarker:namespacesResponse.next_marker,...namespacesExhausted&&{templates:templatesResponse.entries,templateNextMarker:templatesResponse.next_marker}})},dispatchLoadMoreError);return}if(hasMoreTemplates){let signal=startBrowseLoadMoreRequest();await runAbortable(signal,()=>fetchTemplates(namespaceFQN,signal,templateNextMarker),response=>{dispatch({type:BrowserActionType.LoadMoreTemplatesLoaded,entries:response.entries,nextMarker:response.next_marker})},dispatchLoadMoreError)}},selectTemplate=async template=>{stateRef.current.selectedTemplateId!==template.id&&(dispatch({type:BrowserActionType.TemplateSelect,template}),callEventCallback(()=>eventServiceRef.current.onTemplateSelect?.(template)))},createTemplate=async namespaceFQN=>{let template=await runTemplateMutation(()=>itemsServiceRef.current.createTemplate?.(namespaceFQN));template&&(dispatch({type:BrowserActionType.TemplateCreated,template,namespaceFQN}),dispatch({type:BrowserActionType.TemplateSelect,template}),callEventCallback(()=>eventServiceRef.current.onTemplateSelect?.(template)))},editTemplate=async templateId=>{let template=await runTemplateMutation(()=>itemsServiceRef.current.updateTemplate?.(templateId));template&&dispatch({type:BrowserActionType.TemplateUpdated,template})},retry=async()=>{let{searchError,searchQuery,loadMoreError,initialLoadError,browseError,namespaceFQN}=stateRef.current;if(searchError){abandonBrowseLoadMore();let signal=startSearchRequest();dispatch({type:BrowserActionType.SearchFetchStart,query:searchQuery}),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0)),await runAbortable(signal,()=>fetchSearchResults(searchQuery,signal),response=>dispatch({type:BrowserActionType.SearchLoaded,results:response.entries,nextMarker:response.next_marker}),error=>dispatch({type:BrowserActionType.SearchError,error:getErrorMessage(error)})),signal.aborted||callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1));return}if(loadMoreError){await loadMore();return}if(initialLoadError||browseError){let signal=startBrowsePageRequest(),errorAction=initialLoadError?BrowserActionType.InitialLoadError:BrowserActionType.BrowseError;dispatch({type:BrowserActionType.BrowseFetchStart}),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0)),await fetchBrowsePage(namespaceFQN,signal,errorAction),signal.aborted||callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1))}};return useMemo(()=>({initialLoad,navigateTo,navigateBack,setSearchValue,loadMore,selectTemplate,editTemplate,createTemplate,retry}),[])}export{useTemplateBrowserActions};
1
+ import{EMPTY_BROWSE_NODE,emptyNamespacesResponse,emptyTemplatesResponse}from"../constants.js";import{BrowserActionType}from"./reducer.js";import{useMemo,useRef}from"react";import debounce from"lodash/debounce";var toNavigation=state=>({namespaceFQN:state.namespaceFQN,path:state.path,canCreateInCurrentNamespace:state.canCreateInCurrentNamespace}),rejectOnAbort=signal=>new Promise((_,reject)=>{if(signal.aborted){reject(new DOMException(`Aborted`,`AbortError`));return}signal.addEventListener(`abort`,()=>reject(new DOMException(`Aborted`,`AbortError`)),{once:!0})}),callEventCallback=callback=>{try{let result=callback();result instanceof Promise&&result.catch(()=>void 0)}catch{}},runTemplateMutation=async operation=>{try{return await operation()}catch{return}},normalizeSearchQuery=value=>value.trim().replaceAll(/\s+/g,` `),getErrorMessage=error=>error instanceof Error?error.message:typeof error==`string`?error:`An unknown error occurred`,runAbortable=async(signal,fetchFn,onSuccess,onError)=>{try{let result=await fetchFn();signal.aborted||onSuccess(result)}catch(error){signal.aborted||onError(error)}},MISSING_GET_NAMESPACES_MESSAGE=`[MetadataTemplateBrowser] isNamespacesEnabled is true but itemsService.getNamespaces is not implemented. Provide getNamespaces on itemsService to load namespace folders.`;function useTemplateBrowserActions(itemsServiceRef,eventServiceRef,isNamespacesEnabledRef,stateRef,dispatch){let browsePageAbortControllerRef=useRef(null),browseLoadMoreAbortControllerRef=useRef(null),searchAbortControllerRef=useRef(null),hasLoggedMissingGetNamespacesRef=useRef(!1),abandonBrowsePage=()=>{let wasLoading=browsePageAbortControllerRef.current!==null;return browsePageAbortControllerRef.current?.abort(),browsePageAbortControllerRef.current=null,dispatch({type:BrowserActionType.BrowsePageCancelled}),wasLoading},abandonBrowseLoadMore=()=>{browseLoadMoreAbortControllerRef.current?.abort(),browseLoadMoreAbortControllerRef.current=null,dispatch({type:BrowserActionType.LoadMoreCancelled})},startBrowsePageRequest=()=>{browsePageAbortControllerRef.current?.abort();let controller=new AbortController;return browsePageAbortControllerRef.current=controller,controller.signal},startBrowseLoadMoreRequest=()=>{browseLoadMoreAbortControllerRef.current?.abort();let controller=new AbortController;return browseLoadMoreAbortControllerRef.current=controller,controller.signal},startSearchRequest=()=>{searchAbortControllerRef.current?.abort();let controller=new AbortController;return searchAbortControllerRef.current=controller,controller.signal},cancelSearchRequest=()=>{searchAbortControllerRef.current?.abort(),searchAbortControllerRef.current=null},debouncedSearchRef=useRef(debounce(async query=>{let signal=startSearchRequest();callEventCallback(()=>eventServiceRef.current.onSearchChange?.(query)),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0)),await runAbortable(signal,()=>fetchSearchResults(query,signal),response=>dispatch({type:BrowserActionType.SearchLoaded,results:response.entries,nextMarker:response.next_marker}),error=>dispatch({type:BrowserActionType.SearchError,error:getErrorMessage(error)})),signal.aborted||callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1))},500)),fetchNamespaces=(fqn,signal,marker)=>{if(!isNamespacesEnabledRef.current)return Promise.resolve(emptyNamespacesResponse);let fn=itemsServiceRef.current.getNamespaces;return fn?Promise.race([fn(fqn,{limit:200,marker,signal}),rejectOnAbort(signal)]):(hasLoggedMissingGetNamespacesRef.current||(hasLoggedMissingGetNamespacesRef.current=!0,typeof process<`u`&&process.env.NODE_ENV!==`production`&&console.warn(MISSING_GET_NAMESPACES_MESSAGE)),Promise.resolve(emptyNamespacesResponse))},fetchTemplates=(fqn,signal,marker)=>{let fn=itemsServiceRef.current.getTemplates;return fn?Promise.race([fn(fqn,{limit:200,marker,signal}),rejectOnAbort(signal)]):Promise.resolve(emptyTemplatesResponse)},fetchSearchResults=(query,signal,marker)=>{let fn=itemsServiceRef.current.getSearchResults;return fn?Promise.race([fn(query,{limit:200,marker,signal}),rejectOnAbort(signal)]):Promise.resolve(emptyTemplatesResponse)},dispatchError=(type,error)=>{dispatch({type,error:getErrorMessage(error)})},fetchBrowsePage=async(fqn,signal,errorAction)=>{let success=!1;return await runAbortable(signal,async()=>{let namespacesResponse=await fetchNamespaces(fqn,signal);return[namespacesResponse,namespacesResponse.next_marker?emptyTemplatesResponse:await fetchTemplates(fqn,signal)]},([namespacesResponse,templatesResponse])=>{dispatch({type:BrowserActionType.BrowseLoaded,namespaces:namespacesResponse.entries,namespaceNextMarker:namespacesResponse.next_marker,templates:templatesResponse.entries,templateNextMarker:templatesResponse.next_marker}),success=!0},error=>dispatchError(errorAction,error)),browsePageAbortControllerRef.current?.signal===signal&&(browsePageAbortControllerRef.current=null),success},initialLoad=async()=>{let signal=startBrowsePageRequest(),{namespaceFQN}=stateRef.current;dispatch({type:BrowserActionType.BrowseFetchStart}),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0)),await fetchBrowsePage(namespaceFQN,signal,BrowserActionType.InitialLoadError),signal.aborted||callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1))},navigateTo=async namespace=>{abandonBrowseLoadMore();let signal=startBrowsePageRequest();dispatch({type:BrowserActionType.NavigateTo,namespace}),dispatch({type:BrowserActionType.BrowseFetchStart}),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0));let success=await fetchBrowsePage(namespace.id,signal,BrowserActionType.BrowseError);signal.aborted||(callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1)),success&&callEventCallback(()=>eventServiceRef.current.onNamespaceChange?.(namespace.id)))},navigateBack=async fqn=>{let isCached=stateRef.current.browseByFqn.has(fqn),wasLoading=abandonBrowsePage();if(abandonBrowseLoadMore(),dispatch({type:BrowserActionType.NavigateBack,fqn}),callEventCallback(()=>eventServiceRef.current.onNamespaceChange?.(fqn)),isCached){wasLoading&&callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1));return}let signal=startBrowsePageRequest();dispatch({type:BrowserActionType.BrowseFetchStart}),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0)),await fetchBrowsePage(fqn,signal,BrowserActionType.BrowseError),signal.aborted||callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1))},setSearchValue=value=>{dispatch({type:BrowserActionType.SearchValueChange,value});let normalizedQuery=normalizeSearchQuery(value);if(normalizedQuery===``){debouncedSearchRef.current.cancel(),cancelSearchRequest(),abandonBrowseLoadMore(),dispatch({type:BrowserActionType.SearchClear}),callEventCallback(()=>eventServiceRef.current.onSearchChange?.(``)),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1));return}abandonBrowseLoadMore(),cancelSearchRequest(),dispatch({type:BrowserActionType.SearchFetchStart,query:normalizedQuery}),debouncedSearchRef.current(normalizedQuery)},loadMore=async()=>{let{namespaceFQN,searchQuery,searchNextMarker,browseByFqn}=stateRef.current,{namespaceNextMarker,templateNextMarker,isNamespacesExhausted}=browseByFqn.get(namespaceFQN)??EMPTY_BROWSE_NODE,isSearchMode=!!searchQuery,hasMoreSearchResults=isSearchMode&&!!searchNextMarker,hasMoreNamespaces=!isSearchMode&&!isNamespacesExhausted&&!!namespaceNextMarker,hasMoreTemplates=!isSearchMode&&!!templateNextMarker;if(!(hasMoreSearchResults||hasMoreNamespaces||hasMoreTemplates))return;dispatch({type:BrowserActionType.LoadMoreStart});let dispatchLoadMoreError=error=>{dispatch({type:BrowserActionType.LoadMoreError,error:getErrorMessage(error)})};if(hasMoreSearchResults){let signal=startSearchRequest();await runAbortable(signal,()=>fetchSearchResults(searchQuery,signal,searchNextMarker),response=>dispatch({type:BrowserActionType.LoadMoreSearchLoaded,entries:response.entries,nextMarker:response.next_marker}),dispatchLoadMoreError);return}if(hasMoreNamespaces){let signal=startBrowseLoadMoreRequest();await runAbortable(signal,async()=>{let namespacesResponse=await fetchNamespaces(namespaceFQN,signal,namespaceNextMarker);return[namespacesResponse,namespacesResponse.next_marker?emptyTemplatesResponse:await fetchTemplates(namespaceFQN,signal)]},([namespacesResponse,templatesResponse])=>{let namespacesExhausted=!namespacesResponse.next_marker;dispatch({type:BrowserActionType.LoadMoreNamespacesLoaded,entries:namespacesResponse.entries,nextMarker:namespacesResponse.next_marker,...namespacesExhausted&&{templates:templatesResponse.entries,templateNextMarker:templatesResponse.next_marker}})},dispatchLoadMoreError);return}if(hasMoreTemplates){let signal=startBrowseLoadMoreRequest();await runAbortable(signal,()=>fetchTemplates(namespaceFQN,signal,templateNextMarker),response=>{dispatch({type:BrowserActionType.LoadMoreTemplatesLoaded,entries:response.entries,nextMarker:response.next_marker})},dispatchLoadMoreError)}},selectTemplate=async template=>{stateRef.current.selectedTemplateId!==template.id&&(dispatch({type:BrowserActionType.TemplateSelect,template}),callEventCallback(()=>eventServiceRef.current.onTemplateSelect?.(template)))},createTemplate=async namespaceFQN=>{let navigation=toNavigation(stateRef.current),template=await runTemplateMutation(()=>itemsServiceRef.current.createTemplate?.(namespaceFQN,navigation));template&&(dispatch({type:BrowserActionType.TemplateCreated,template,namespaceFQN}),dispatch({type:BrowserActionType.TemplateSelect,template}),callEventCallback(()=>eventServiceRef.current.onTemplateSelect?.(template)))},editTemplate=async templateId=>{let navigation=toNavigation(stateRef.current),template=await runTemplateMutation(()=>itemsServiceRef.current.updateTemplate?.(templateId,navigation));template&&dispatch({type:BrowserActionType.TemplateUpdated,template})},retry=async()=>{let{searchError,searchQuery,loadMoreError,initialLoadError,browseError,namespaceFQN}=stateRef.current;if(searchError){abandonBrowseLoadMore();let signal=startSearchRequest();dispatch({type:BrowserActionType.SearchFetchStart,query:searchQuery}),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0)),await runAbortable(signal,()=>fetchSearchResults(searchQuery,signal),response=>dispatch({type:BrowserActionType.SearchLoaded,results:response.entries,nextMarker:response.next_marker}),error=>dispatch({type:BrowserActionType.SearchError,error:getErrorMessage(error)})),signal.aborted||callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1));return}if(loadMoreError){await loadMore();return}if(initialLoadError||browseError){let signal=startBrowsePageRequest(),errorAction=initialLoadError?BrowserActionType.InitialLoadError:BrowserActionType.BrowseError;dispatch({type:BrowserActionType.BrowseFetchStart}),callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!0)),await fetchBrowsePage(namespaceFQN,signal,errorAction),signal.aborted||callEventCallback(()=>eventServiceRef.current.onNewViewLoading?.(!1))}};return useMemo(()=>({initialLoad,navigateTo,navigateBack,setSearchValue,loadMore,selectTemplate,editTemplate,createTemplate,retry}),[])}export{useTemplateBrowserActions};
@@ -1 +1 @@
1
- import{ConsumerStateContextProvider}from"./contexts/contexts.js";import{MetadataTemplateBrowserProvider}from"./contexts/provider.js";import{t as MetadataTemplateBrowserController}from"../../chunks/metadata-template-browser-controller.js";import{TooltipProvider}from"@box/blueprint-web";import{jsx}from"react/jsx-runtime";function MetadataTemplateBrowser({enterpriseId,itemsService,eventService,isLoading,isDisabled,isNamespacesEnabled,initialSelectedTemplateId,canCreateAtRoot,appliedTemplateIds}){return jsx(TooltipProvider,{children:jsx(ConsumerStateContextProvider,{appliedTemplateIds,isDisabled,isLoading,isNamespacesEnabled,children:jsx(MetadataTemplateBrowserProvider,{namespaceFQN:enterpriseId,itemsService,eventService,initialSelectedTemplateId,canCreateAtRoot,isNamespacesEnabled,children:jsx(MetadataTemplateBrowserController,{})})})})}export{MetadataTemplateBrowser};
1
+ import{ConsumerStateContextProvider}from"./contexts/contexts.js";import{MetadataTemplateBrowserProvider}from"./contexts/provider.js";import{t as MetadataTemplateBrowserController}from"../../chunks/metadata-template-browser-controller.js";import{TooltipProvider}from"@box/blueprint-web";import{jsx}from"react/jsx-runtime";function MetadataTemplateBrowser({enterpriseId,itemsService,eventService,isLoading,isDisabled,isNamespacesEnabled,initialSelectedTemplateId,initialNavigation,canCreateAtRoot,appliedTemplateIds}){return jsx(TooltipProvider,{children:jsx(ConsumerStateContextProvider,{appliedTemplateIds,isDisabled,isLoading,isNamespacesEnabled,children:jsx(MetadataTemplateBrowserProvider,{namespaceFQN:enterpriseId,itemsService,eventService,initialSelectedTemplateId,initialNavigation,canCreateAtRoot,isNamespacesEnabled,children:jsx(MetadataTemplateBrowserController,{})})})})}export{MetadataTemplateBrowser};
@@ -1,3 +1,3 @@
1
1
  export { MetadataTemplateBrowser } from './lib/metadata-template-browser';
2
2
  /** Public domain types for implementing `ItemsService` / `EventService` and working with template payloads. */
3
- export type { EventService, FetchParams, FetchResponse, ItemsService, MetadataField, MetadataFieldOption, MetadataFieldType, MetadataNamespace, MetadataTemplate, } from './lib/types';
3
+ export type { BreadcrumbEntry, BrowserNavigation, EventService, FetchParams, FetchResponse, ItemsService, MetadataField, MetadataFieldOption, MetadataFieldType, MetadataNamespace, MetadataTemplate, } from './lib/types';
@@ -1,10 +1,11 @@
1
- import { EventService, ItemsService } from '../types';
1
+ import { BrowserNavigation, EventService, ItemsService } from '../types';
2
2
  export interface MetadataTemplateBrowserProviderProps {
3
3
  readonly children: React.ReactNode;
4
4
  readonly namespaceFQN: string;
5
5
  readonly itemsService: ItemsService;
6
6
  readonly eventService: EventService;
7
7
  readonly initialSelectedTemplateId?: string;
8
+ readonly initialNavigation?: BrowserNavigation;
8
9
  /**
9
10
  * Whether template creation is allowed at the root namespace (enterprise level).
10
11
  * Mirrored into `canCreateInCurrentNamespace` in the navigation state on mount.
@@ -23,4 +24,4 @@ export interface MetadataTemplateBrowserProviderProps {
23
24
  * reducer, wraps consumer-provided services in stable refs, and composes all
24
25
  * state and actions contexts in a single tree.
25
26
  */
26
- export declare function MetadataTemplateBrowserProvider({ children, namespaceFQN, itemsService, eventService, initialSelectedTemplateId, canCreateAtRoot, isNamespacesEnabled, }: Readonly<MetadataTemplateBrowserProviderProps>): import("react/jsx-runtime").JSX.Element;
27
+ export declare function MetadataTemplateBrowserProvider({ children, namespaceFQN, itemsService, eventService, initialSelectedTemplateId, initialNavigation, canCreateAtRoot, isNamespacesEnabled, }: Readonly<MetadataTemplateBrowserProviderProps>): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,4 @@
1
- import { EventService, ItemsService } from './types';
1
+ import { BrowserNavigation, EventService, ItemsService } from './types';
2
2
  export interface MetadataTemplateBrowserProps {
3
3
  /** Enterprise ID used as the root namespace FQN (e.g. "enterprise_123"). */
4
4
  enterpriseId: string;
@@ -25,6 +25,11 @@ export interface MetadataTemplateBrowserProps {
25
25
  isNamespacesEnabled?: boolean;
26
26
  /** Template ID to auto-select after the initial load completes. */
27
27
  initialSelectedTemplateId?: string;
28
+ /**
29
+ * Browse location to open at. `initialLoad` fetches this FQN instead of
30
+ * the enterprise root. Omit to start at the enterprise root.
31
+ */
32
+ initialNavigation?: BrowserNavigation;
28
33
  /**
29
34
  * Whether template creation is allowed at the root (enterprise) namespace.
30
35
  * When true and `itemsService.createTemplate` is provided, a create-template
@@ -42,4 +47,4 @@ export interface MetadataTemplateBrowserProps {
42
47
  * Public entry point for the metadata template browser.
43
48
  * Wraps the provider and controller into a single composable component.
44
49
  */
45
- export declare function MetadataTemplateBrowser({ enterpriseId, itemsService, eventService, isLoading, isDisabled, isNamespacesEnabled, initialSelectedTemplateId, canCreateAtRoot, appliedTemplateIds, }: Readonly<MetadataTemplateBrowserProps>): import("react/jsx-runtime").JSX.Element;
50
+ export declare function MetadataTemplateBrowser({ enterpriseId, itemsService, eventService, isLoading, isDisabled, isNamespacesEnabled, initialSelectedTemplateId, initialNavigation, canCreateAtRoot, appliedTemplateIds, }: Readonly<MetadataTemplateBrowserProps>): import("react/jsx-runtime").JSX.Element;
@@ -33,3 +33,8 @@ export declare function navigateIntoNamespace(canvas: StoryPlayCanvas, name: str
33
33
  * Waits for the list loading region shown during an in-flight search.
34
34
  */
35
35
  export declare function findLoadingTemplatesStatus(canvas: StoryPlayCanvas): Promise<HTMLElement>;
36
+ /**
37
+ * Reveals a template row's edit affordance by hovering, then clicks it.
38
+ * The button is rendered but hidden until hover, so a direct click misses it.
39
+ */
40
+ export declare function hoverAndClickEditTemplate(canvas: StoryPlayCanvas, name: string): Promise<void>;
@@ -56,11 +56,15 @@ export interface ItemsService {
56
56
  * failure reporting. A rejection is swallowed rather than surfaced as a list
57
57
  * error, so reject only once the failure has been reported to the user.
58
58
  *
59
+ * `navigation` is the browse location at the moment of the call. Hosts whose
60
+ * create UI unmounts the browser store it and pass it back as
61
+ * `initialNavigation` so the next mount opens at the same place.
62
+ *
59
63
  * Providing this method is what enables the browser's create-template
60
64
  * affordances; `canCreateAtRoot` and `MetadataNamespace.canCreate` decide where
61
65
  * they appear.
62
66
  */
63
- createTemplate?: (namespaceFQN: string) => Promise<MetadataTemplate | undefined>;
67
+ createTemplate?: (namespaceFQN: string, navigation: BrowserNavigation) => Promise<MetadataTemplate | undefined>;
64
68
  /**
65
69
  * Updates the template identified by `templateId` under the same contract as
66
70
  * `createTemplate`, resolving with the updated template or `undefined`.
@@ -68,7 +72,7 @@ export interface ItemsService {
68
72
  * Providing this method is what enables the row edit affordance;
69
73
  * `MetadataTemplate.canEdit` decides which rows show it.
70
74
  */
71
- updateTemplate?: (templateId: string) => Promise<MetadataTemplate | undefined>;
75
+ updateTemplate?: (templateId: string, navigation: BrowserNavigation) => Promise<MetadataTemplate | undefined>;
72
76
  }
73
77
  export interface EventService {
74
78
  onNamespaceChange?: (namespaceFQN: string) => Promise<void>;
@@ -84,6 +88,18 @@ export interface EventService {
84
88
  export interface BreadcrumbEntry {
85
89
  fqn: string;
86
90
  displayName: string;
91
+ /** Create permission at this level. Used when restoring a snapshot. */
92
+ canCreate?: boolean;
93
+ }
94
+ /**
95
+ * Browse location, handed to `ItemsService.createTemplate` / `updateTemplate` so a
96
+ * host whose editor unmounts the browser can pass it back as `initialNavigation`.
97
+ * Restores the location only; browse data is refetched on the next mount.
98
+ */
99
+ export interface BrowserNavigation {
100
+ namespaceFQN: string;
101
+ path: BreadcrumbEntry[];
102
+ canCreateInCurrentNamespace: boolean;
87
103
  }
88
104
  export interface SearchStateContextValue {
89
105
  searchValue: string;
@@ -140,8 +156,8 @@ export interface BrowserActionsContextValue {
140
156
  initialLoad: () => Promise<void>;
141
157
  /** Navigates into a namespace, loading its child namespaces and templates. */
142
158
  navigateTo: (namespace: MetadataNamespace) => Promise<void>;
143
- /** Navigates back to the level identified by `fqn`, already stored in `browseByFqn`. */
144
- navigateBack: (fqn: string) => void;
159
+ /** Navigates back to `fqn`. Uses the cached node when present, otherwise fetches. */
160
+ navigateBack: (fqn: string) => Promise<void>;
145
161
  /** Updates the search query; an empty string exits search mode and returns to browse. */
146
162
  setSearchValue: (value: string) => void;
147
163
  /**
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@box/metadata-template-browser",
3
- "version": "2.3.31",
3
+ "version": "2.4.1",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "peerDependencies": {
6
- "@box/blueprint-web": "^17.9.0",
7
- "@box/blueprint-web-assets": "^5.10.4",
6
+ "@box/blueprint-web": "^17.9.1",
7
+ "@box/blueprint-web-assets": "^5.10.5",
8
8
  "lodash": "^4.17.15",
9
9
  "react": "^18.0.0",
10
10
  "react-aria-components": "1.16.0",
@@ -12,10 +12,10 @@
12
12
  "react-intl": "^6.4.2"
13
13
  },
14
14
  "devDependencies": {
15
- "@box/blueprint-web": "^17.9.0",
16
- "@box/blueprint-web-assets": "^5.10.4",
15
+ "@box/blueprint-web": "^17.9.1",
16
+ "@box/blueprint-web-assets": "^5.10.5",
17
17
  "@box/eslint-plugin-blueprint": "2.2.16",
18
- "@box/storybook-utils": "1.2.48",
18
+ "@box/storybook-utils": "1.2.49",
19
19
  "react-intl": "^6.4.2"
20
20
  },
21
21
  "publishConfig": {