"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateCommandPalette = generateCommandPalette;
const Generator = __importStar(require("@postxl/generator"));
function generateCommandPalette({ context }) {
    const imports = Generator.ImportGenerator.from(Generator.toFilePath('./command-palette.tsx'))
        .addImport({
        from: Generator.toPackageName('react'),
        items: [
            Generator.toClassName('Component'),
            Generator.toTypeName('ErrorInfo'),
            Generator.toTypeName('PropsWithChildren'),
            Generator.toFunctionName('useCallback'),
            Generator.toFunctionName('useDeferredValue'),
            Generator.toFunctionName('useEffect'),
            Generator.toFunctionName('useMemo'),
            Generator.toFunctionName('useRef'),
            Generator.toFunctionName('useState'),
        ],
    })
        .addImport({
        from: Generator.toPackageName('@postxl/ui-components'),
        items: [
            Generator.toFunctionName('CommandDialog'),
            Generator.toFunctionName('CommandGroup'),
            Generator.toFunctionName('CommandInput'),
            Generator.toFunctionName('CommandItem'),
            Generator.toFunctionName('CommandList'),
        ],
    })
        .addImport({ from: Generator.toBackendModuleLocation('@lib/router'), items: [Generator.toConstantName('router')] });
    for (const hook of context.frontendActions.globalActionHooks) {
        imports.add(hook);
    }
    const hookCalls = context.frontendActions.globalActionHooks.map((hook) => `  ${hook.name}()`).join('\n');
    return `
${imports.generate()}

import {
  useCommandPaletteActions,
  useCommandPaletteAvailableActions,
  useCommandPaletteState,
} from './command-palette-store'

type CommandPaletteErrorBoundaryState = {
  hasError: boolean
}

class CommandPaletteErrorBoundary extends Component<PropsWithChildren, CommandPaletteErrorBoundaryState> {
  public constructor(props: PropsWithChildren) {
    super(props)
    this.state = { hasError: false }
  }

  public static getDerivedStateFromError(): CommandPaletteErrorBoundaryState {
    return { hasError: true }
  }

  public componentDidCatch(error: unknown, info: ErrorInfo) {
    console.error('CommandPalette rendering failed:', error, info)
  }

  public render() {
    if (this.state.hasError) {
      return null
    }

    return this.props.children
  }
}

export function CommandPalette() {
  return (
    <CommandPaletteErrorBoundary>
      <CommandPaletteInner />
    </CommandPaletteErrorBoundary>
  )
}

function CommandPaletteInner() {
  const { find, cancel, registerGlobalRenderer, deregisterPageActions } = useCommandPaletteActions()
  const isRunning = useCommandPaletteState((state) => state.running)
  const {
    mode,
    open,
    value,
    inputRef,
    handleKeydown,
    handleOpenChange: onOpenChange,
    handleSelect,
    handleValueChange,
  } = useCommandPaletteInput()

  const deferredValue = useDeferredValue(value)
  const availableActions = useCommandPaletteAvailableActions(deferredValue)

${hookCalls}

  const suggestions = useMemo(() => {
    if (mode.value === 'search') {
      return []
    }

    return find(mode.key)?.suggestions ?? []
  }, [mode, find])

  const [CustomContent, setCustomContent] = useState<React.FC | null>(null)

  const handleOpenChange = useCallback(
    (isOpen: boolean) => {
      if (!isOpen) {
        cancel()
        setCustomContent(null)
      }

      onOpenChange(isOpen)
    },
    [cancel, onOpenChange],
  )

  useEffect(() => {
    registerGlobalRenderer((component) => setCustomContent(() => component))
  }, [registerGlobalRenderer])

  useEffect(() => {
    const down = (event: KeyboardEvent) => {
      if (event.key.toLowerCase() === 'k' && (event.metaKey || event.ctrlKey)) {
        event.preventDefault()
        handleOpenChange(true)
      }

      handleKeydown(event)
    }

    document.addEventListener('keydown', down)
    return () => document.removeEventListener('keydown', down)
  }, [handleKeydown, handleOpenChange])

  useEffect(() => {
    return router.subscribe('onBeforeRouteMount', () => {
      deregisterPageActions()
    })
  }, [deregisterPageActions])

  return (
    <CommandDialog open={open} onOpenChange={handleOpenChange}>
      <CommandInput
        ref={inputRef}
        value={value}
        onValueChange={handleValueChange}
        placeholder={mode.value === 'search' ? 'Type a command or search...' : 'Enter value...'}
      />

      {CustomContent ? (
        <CustomContent />
      ) : (
        <CommandList>
          {mode.value === 'input' &&
            suggestions.map((suggestion) => (
              <CommandItem key={suggestion} value={suggestion} onSelect={() => handleSelect(suggestion, 'input')}>
                {suggestion}
              </CommandItem>
            ))}

          {availableActions.map(({ group, actions }) => (
            <CommandGroup key={group} heading={group}>
              {actions.map((action) => (
                <CommandItem
                  key={action.key}
                  value={action.key}
                  keywords={action.keywords}
                  onSelect={() => handleSelect(action.key, action.kind)}
                >
                  {action.icon}
                  {action.label}
                </CommandItem>
              ))}
            </CommandGroup>
          ))}
        </CommandList>
      )}

      {isRunning && <div className="px-3 py-2 text-sm text-muted-foreground">Running action...</div>}
    </CommandDialog>
  )
}

const useCommandPaletteInput = () => {
  const { select, back, reset } = useCommandPaletteActions()

  const didSelect = useRef(false)
  const inputRef = useRef<HTMLInputElement | null>(null)
  const abortRef = useRef<AbortController | null>(null)

  const [open, setOpen] = useState(false)
  const [value, setValue] = useState('')
  const [mode, setMode] = useState<{ value: 'search' } | { value: 'input'; key: string }>({ value: 'search' })

  const handleOpenChange = useCallback(
    (isOpen: boolean) => {
      setOpen(isOpen)

      if (!isOpen) {
        setValue('')
        setMode({ value: 'search' })
        reset()
        abortRef.current?.abort()
      }

      if (isOpen) {
        setTimeout(() => inputRef.current?.focus(), 75)
      }
    },
    [reset],
  )

  const runAction = useCallback(
    async (key: string, query = '', input: unknown = undefined) => {
      abortRef.current = new AbortController()
      const result = await select(key, abortRef.current.signal, query, input)
      handleOpenChange(result.kind !== 'close')
      setMode({ value: 'search' })
      return result
    },
    [handleOpenChange, select],
  )

  const handleKeydown = useCallback(
    (event: KeyboardEvent) => {
      if (!open) {
        return
      }

      if (event.key === 'Backspace' && value === '') {
        if (mode.value === 'input') {
          setMode({ value: 'search' })
          return
        }

        back()
        return
      }

      if (event.key === 'Escape') {
        handleOpenChange(false)
        return
      }

      if (event.key === 'Enter') {
        event.preventDefault()

        if (didSelect.current) {
          didSelect.current = false
          return
        }

        if (mode.value === 'input') {
          void runAction(mode.key, value, { query: value })
          return
        }
      }
    },
    [open, value, mode, back, handleOpenChange, runAction],
  )

  const handleSelect = useCallback(
    (key: string, kind: 'command' | 'input') => {
      didSelect.current = true

      if (mode.value === 'search') {
        if (kind === 'input') {
          setValue('')
          setMode({ value: 'input', key })
          return
        }

        void runAction(key)
        return
      }

      void runAction(mode.key, key, { query: key })
    },
    [mode, runAction],
  )

  return {
    mode,
    open,
    value,
    inputRef,
    handleOpenChange,
    handleKeydown,
    handleSelect,
    handleValueChange: setValue,
  }
}
`;
}
//# sourceMappingURL=command-palette.generator.js.map