"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateCommandPaletteStore = generateCommandPaletteStore;
function generateCommandPaletteStore() {
    return `import { useMemo, useSyncExternalStore } from 'react'

import { CommandPaletteAction, CommandPaletteActionPage, CommandPaletteActionResult } from './command-palette-action'

type GroupedActions = {
  group: string
  actions: CommandPaletteAction[]
}

type CommandPaletteState = {
  page: CommandPaletteActionPage
  componentActions: CommandPaletteAction[]
  globalActions: CommandPaletteAction[]
  running: boolean
  search: string
  globalRenderer: ((component: React.FC | null) => void) | null
}

type CommandPaletteActions = {
  find: (key: string) => CommandPaletteAction | undefined
  back: () => void
  reset: () => void
  cancel: () => void
  select: (key: string, signal: AbortSignal, query?: string, input?: unknown) => Promise<CommandPaletteActionResult>
  registerPageActions: (page: CommandPaletteActionPage) => void
  deregisterPageActions: () => void
  registerComponentActions: (actions: CommandPaletteAction[]) => void
  deregisterComponentActions: (actions: CommandPaletteAction[]) => void
  registerGlobalActions: (...actions: CommandPaletteAction[]) => void
  registerGlobalRenderer: (render: (component: React.FC | null) => void) => void
  calculateAvailableLLMActions: () => CommandPaletteAction[]
}

type CommandPaletteStore = CommandPaletteState & { actions: CommandPaletteActions }

const listeners = new Set<() => void>()
const rootPage: CommandPaletteActionPage = { actions: [] }

const into = (back: CommandPaletteActionPage, page: CommandPaletteActionPage): CommandPaletteActionPage => ({
  ...page,
  back,
})

const subscribe = (listener: () => void) => {
  listeners.add(listener)
  return () => listeners.delete(listener)
}

const notify = () => {
  for (const listener of listeners) {
    listener()
  }
}

const setStore = (update: Partial<CommandPaletteState>) => {
  store = {
    ...store,
    ...update,
  }
  notify()
}

const createActions = (): CommandPaletteActions => ({
  calculateAvailableLLMActions() {
    const { page, componentActions, globalActions } = store
    const isRoot = !page.back
    const isVisibleToLLM = (action: CommandPaletteAction) => action.visibility === 'visible' || action.visibility === 'llm'
    const all = [
      ...page.actions.filter(isVisibleToLLM),
      ...(isRoot ? componentActions.filter(isVisibleToLLM) : []),
      ...globalActions.filter(isVisibleToLLM),
    ]

    const seen = new Set<string>()
    return all.filter((action) => {
      if (seen.has(action.key)) {
        return false
      }

      seen.add(action.key)
      return true
    })
  },

  find(key: string) {
    const { page, componentActions, globalActions } = store
    const isRoot = !page.back

    return (
      page.actions.find((action) => action.key === key) ??
      (isRoot ? componentActions.find((action) => action.key === key) : undefined) ??
      globalActions.find((action) => action.key === key)
    )
  },

  back() {
    const { page } = store
    if (page.back) {
      setStore({ page: page.back })
    }
  },

  reset() {
    let next = store.page

    while (next.back) {
      next = next.back
    }

    setStore({ page: next })
  },

  cancel() {
    const { globalRenderer } = store
    globalRenderer?.(null)
    setStore({ running: false })
  },

  async select(key, signal, query = '', input = undefined) {
    const { page, componentActions, globalActions, globalRenderer, running: wasRunning } = store
    const isRoot = !page.back

    const action =
      page.actions.find((candidate) => candidate.key === key) ??
      (isRoot ? componentActions.find((candidate) => candidate.key === key) : undefined) ??
      globalActions.find((candidate) => candidate.key === key)

    if (!action) {
      return { kind: 'close' }
    }

    setStore({ running: true })

    try {
      signal.throwIfAborted()
      const result = await action.run(query, input, signal, globalRenderer ?? (() => null))

      if (result.kind === 'page') {
        setStore({ page: into(page, result) })
      }

      return result
    } finally {
      globalRenderer?.(null)
      setStore({ running: wasRunning })
    }
  },

  registerPageActions(page) {
    setStore({ page })
  },

  deregisterPageActions() {
    setStore({ page: rootPage })
  },

  registerComponentActions(actions) {
    const incoming = new Set(actions.map((action) => action.key))
    const componentActions = [...store.componentActions.filter((action) => !incoming.has(action.key)), ...actions]
    setStore({ componentActions })
  },

  deregisterComponentActions(actions) {
    const toRemove = new Set(actions.map((action) => action.key))
    setStore({ componentActions: store.componentActions.filter((action) => !toRemove.has(action.key)) })
  },

  registerGlobalActions(...actions) {
    const incoming = new Set(actions.map((action) => action.key))
    const globalActions = [...store.globalActions.filter((action) => !incoming.has(action.key)), ...actions]
    setStore({ globalActions })
  },

  registerGlobalRenderer(render) {
    setStore({ globalRenderer: render })
  },
})

let store: CommandPaletteStore = {
  page: rootPage,
  componentActions: [],
  globalActions: [],
  running: false,
  search: '',
  globalRenderer: null,
  actions: {} as CommandPaletteActions,
}
store.actions = createActions()

export const useCommandPaletteState = <T>(selector: (state: CommandPaletteState) => T): T =>
  useSyncExternalStore(subscribe, () => selector(store), () => selector(store))

export const useCommandPaletteActions = (): CommandPaletteActions =>
  useSyncExternalStore(subscribe, () => store.actions, () => store.actions)

export const useCommandPaletteAvailableActions = (query: string): GroupedActions[] => {
  const page = useCommandPaletteState((state) => state.page)
  const componentActions = useCommandPaletteState((state) => state.componentActions)
  const globalActions = useCommandPaletteState((state) => state.globalActions)

  return useMemo(
    () => calculateAvailableActions({ page, componentActions, globalActions, query }),
    [page, componentActions, globalActions, query],
  )
}

const calculateAvailableActions = ({
  page,
  componentActions,
  globalActions,
  query,
}: {
  page: CommandPaletteActionPage
  componentActions: CommandPaletteAction[]
  globalActions: CommandPaletteAction[]
  query: string
}): GroupedActions[] => {
  const hasQuery = query.trim().length > 0
  const isRoot = !page.back

  const canBeShownToUser = (action: CommandPaletteAction) => action.visibility === 'visible' || action.visibility === 'user'

  const actionByGroup = new Map<string, CommandPaletteAction[]>()
  const ungrouped: CommandPaletteAction[] = []
  const seen = new Set<string>()

  for (const action of [...page.actions, ...(isRoot ? componentActions : [])]) {
    if (!canBeShownToUser(action)) {
      continue
    }

    if (seen.has(action.key)) {
      continue
    }

    if (action.group) {
      const existing = actionByGroup.get(action.group) ?? []
      actionByGroup.set(action.group, [...existing, action])
    } else {
      ungrouped.push(action)
    }

    seen.add(action.key)
  }

  const result: GroupedActions[] = []

  if (isRoot) {
    const filteredGlobal = globalActions.filter((action) => canBeShownToUser(action) && !seen.has(action.key))
    if (filteredGlobal.length > 0) {
      result.push({ group: 'Global actions', actions: filteredGlobal })
    }
  }

  if (ungrouped.length > 0) {
    result.push({ group: 'On this page', actions: ungrouped })
  }

  for (const [group, actions] of actionByGroup.entries()) {
    result.push({ group, actions })
  }

  if (!hasQuery) {
    return result
  }

  const terms = query
    .toLowerCase()
    .split(/\\s+/)
    .map((term) => term.trim())
    .filter(Boolean)

  const matches = (action: CommandPaletteAction) => {
    const text = [action.label, ...(action.keywords ?? [])].join(' ').toLowerCase()
    return terms.every((term) => text.includes(term))
  }

  return result
    .map((group) => ({ ...group, actions: group.actions.filter(matches) }))
    .filter((group) => group.actions.length > 0)
}
`;
}
//# sourceMappingURL=command-palette-store.generator.js.map