diff --git a/packages/cli/src/commands/add.tsx b/packages/cli/src/commands/add.tsx index 9c91151..14d3077 100644 --- a/packages/cli/src/commands/add.tsx +++ b/packages/cli/src/commands/add.tsx @@ -5,7 +5,7 @@ import {mkdir, writeFile} from 'node:fs/promises' import {join} from 'node:path' import {getAvailableComponentNames, getComponentRealname, getComponentURL, getRegistry} from '../helpers/registry.js' import ora from 'ora' -import React, {ComponentPropsWithoutRef, useState} from 'react' +import React, {ComponentPropsWithoutRef} from 'react' import {render, Box} from 'ink' import {SearchBox} from '../components/SearchBox.js' import {getComponentsInstalled} from '../helpers/path.js' @@ -16,43 +16,18 @@ function Generator() { let complete: boolean = false function ComponentSelector( - props: Omit>, 'helper' | 'onSubmit'> & { - installed: string[] - onComplete: (value: T, force: 'yes' | 'no' | null) => void - skipForce: boolean - }, + props: Omit>, 'helper'>, ) { - const [forceStaged, setForceStaged] = useState(false) - const [onCompleteCache, setCache] = useState({key: '', displayName: '', installed: false} as T) - return ( - {!forceStaged ? ( - { - if (T.installed && !props.skipForce) { - setForceStaged(true) - setCache(T) - } else { - complete = true - props.onComplete(T, null) - } - }} - /> - ) : null} - {forceStaged ? ( - { - complete = true - props.onComplete(onCompleteCache, value) - }} - /> - ) : null} + { + complete = true + props.onSubmit?.(value) + }} + /> ) } @@ -70,6 +45,36 @@ function Generator() { ] as const } +function Generator2() { + let complete = false + + function ForceSelector({onComplete}: {onComplete: (value: 'yes' | 'no') => void}) { + return ( + { + complete = true + onComplete(value) + }} + /> + ) + } + + return [ + ForceSelector, + new Promise((r) => { + const i = setInterval(() => { + if (complete) { + r() + clearInterval(i) + } + }, 100) + }), + ] as const +} + export default class Add extends Command { static override args = { name: Args.string({description: 'name of component to install'}), @@ -121,7 +126,12 @@ export default class Add extends Command { })) let name: string | undefined = args.name?.toLowerCase?.() - let quit = false + let requireForce: boolean = + !name || !componentNames.includes(name.toLowerCase()) + ? false + : searchBoxComponent.find(({key}) => key === name)?.installed + ? !force + : false if (!name || !componentNames.includes(name.toLowerCase())) { const [ComponentSelector, waitForComplete] = Generator() @@ -130,12 +140,27 @@ export default class Add extends Command { { + onSubmit={(comp) => { name = comp.key - force = forceSelected === 'yes' - quit = forceSelected === 'no' + requireForce = comp.installed + inkInstance.clear() + }} + />, + ) + await waitForComplete + inkInstance.unmount() + } + + let quit = false + + if (requireForce) { + const [ForceSelector, waitForComplete] = Generator2() + + const inkInstance = render( + { + force = value === 'yes' + quit = value === 'no' inkInstance.clear() }} />,