(function (root, factory) { const filterCommands = factory(); if (typeof module === 'object' && module.exports) module.exports = filterCommands; if (root) root.filterCommands = filterCommands; })(typeof globalThis !== 'undefined' ? globalThis : this, function () { function filterCommands(commands, filter) { const term = String(filter || '').toLowerCase(); return commands.filter(command => command.name.toLowerCase().includes(term)); } filterCommands.nextSelection = function nextSelection(current, key, count) { if (count < 1) return -1; if (key === 'ArrowDown') return (current + 1 + count) % count; if (key === 'ArrowUp') return (current - 1 + count) % count; return current; }; filterCommands.searchUrl = function searchUrl(query, page, scope, continuation) { const streamPages = continuation ? (continuation.issues ? '&issues_page=' + encodeURIComponent(continuation.issues) : '') + (continuation.pulls ? '&pulls_page=' + encodeURIComponent(continuation.pulls) : '') : ''; return 'api/v1/search?q=' + encodeURIComponent(query) + '&limit=10&page=' + page + '&kind=' + encodeURIComponent(scope.kind) + '&state=' + encodeURIComponent(scope.state) + (scope.repository ? '&repository=' + encodeURIComponent(scope.repository) : '') + streamPages; }; filterCommands.createGlobalSearchController = function createGlobalSearchController(options) { const search = options.search; const onState = options.onState; const delay = options.delay === undefined ? 250 : options.delay; let timer = null; let generation = 0; let activeController = null; let scope = { kind:'all', state:'all' }; let state = { status: 'idle', query: '', items: [], more: false, next: 1, scope }; function publish(next) { state = next; onState(next); return state; } async function requestPage(query, page, current, append, continuation) { const requestController = new AbortController(); activeController = requestController; try { const requestScope = { ...scope }; const result = await search( query, requestController.signal, page, requestScope, continuation ); const partial = result.partial === true; const incoming = result.items || result; const combined = append ? state.items.concat(incoming) : incoming; const items = [...new Map((combined || []).map(item => [`${item.kind}:${item.repository}:${item.number}`, item] )).values()]; if (current === generation) return publish({ status: 'ready', query, items, partial, more: !!result.has_more, next: result.next_page, continuation:result.continuation, failedStreams:result.failed_streams || [], scope:requestScope, }); } catch (error) { if (error && error.name === 'AbortError') return; if (current === generation) return publish(append ? { ...state, status: 'ready' } : { status: 'error', query, items: [], error, scope:{ ...scope } }); } finally { if (activeController === requestController) activeController = null; } } return { setQuery(value) { const query = String(value || '').trim(); generation += 1; const current = generation; if (timer !== null) clearTimeout(timer); if (activeController !== null) activeController.abort(); activeController = null; if (query.length < 2) { publish({ status: 'idle', query, items: [], more: false, next: 1, scope:{ ...scope } }); return; } publish({ status: 'loading', query, items: [], more: false, next: 1, scope:{ ...scope } }); timer = setTimeout(() => requestPage(query, 1, current, false), delay); }, setScope(value) { const repository = typeof value?.repository === 'string' && /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(value.repository.trim()) ? value.repository.trim() : ''; const next = { kind:['all', 'issue', 'pull'].includes(value?.kind) ? value.kind : 'all', state:['all', 'open', 'closed'].includes(value?.state) ? value.state : 'all', ...(repository ? { repository } : {}), }; if (next.kind === scope.kind && next.state === scope.state && (next.repository || '') === (scope.repository || '')) return; const query = state.query; scope = next; this.setQuery(query); }, loadMore() { if (state.status !== 'ready' || !state.more || activeController) return Promise.resolve(state); const current = generation; const page = state.next; return requestPage(state.query, page, current, true, state.continuation); }, }; }; return filterCommands; });