mirror of
https://github.com/stackblitz-labs/bolt.diy
synced 2025-01-22 19:06:12 +00:00
Split code a little bit
This commit is contained in:
parent
f6a9861390
commit
2fd0c06ed4
@ -23,45 +23,8 @@ import { ImportButtons } from '~/components/chat/chatExportAndImport/ImportButto
|
|||||||
import { ExamplePrompts } from '~/components/chat/ExamplePrompts';
|
import { ExamplePrompts } from '~/components/chat/ExamplePrompts';
|
||||||
|
|
||||||
import FilePreview from './FilePreview';
|
import FilePreview from './FilePreview';
|
||||||
|
import { ModelSelector } from '~/components/chat/ModelSelector';
|
||||||
// @ts-ignore TODO: Introduce proper types
|
import { SpeechRecognitionButton } from '~/components/chat/SpeechRecognition';
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const ModelSelector = ({ model, setModel, provider, setProvider, modelList, providerList, apiKeys }) => {
|
|
||||||
return (
|
|
||||||
<div className="mb-2 flex gap-2 flex-col sm:flex-row">
|
|
||||||
<select
|
|
||||||
value={provider?.name}
|
|
||||||
onChange={(e) => {
|
|
||||||
setProvider(providerList.find((p: ProviderInfo) => p.name === e.target.value));
|
|
||||||
|
|
||||||
const firstModel = [...modelList].find((m) => m.provider == e.target.value);
|
|
||||||
setModel(firstModel ? firstModel.name : '');
|
|
||||||
}}
|
|
||||||
className="flex-1 p-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus transition-all"
|
|
||||||
>
|
|
||||||
{providerList.map((provider: ProviderInfo) => (
|
|
||||||
<option key={provider.name} value={provider.name}>
|
|
||||||
{provider.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
<select
|
|
||||||
key={provider?.name}
|
|
||||||
value={model}
|
|
||||||
onChange={(e) => setModel(e.target.value)}
|
|
||||||
className="flex-1 p-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus transition-all lg:max-w-[70%]"
|
|
||||||
>
|
|
||||||
{[...modelList]
|
|
||||||
.filter((e) => e.provider == provider?.name && e.name)
|
|
||||||
.map((modelOption) => (
|
|
||||||
<option key={modelOption.name} value={modelOption.name}>
|
|
||||||
{modelOption.label}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const TEXTAREA_MIN_HEIGHT = 76;
|
const TEXTAREA_MIN_HEIGHT = 76;
|
||||||
|
|
||||||
@ -93,31 +56,6 @@ interface BaseChatProps {
|
|||||||
setImageDataList?: (dataList: string[]) => void;
|
setImageDataList?: (dataList: string[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SpeechRecognitionButton = ({
|
|
||||||
isListening,
|
|
||||||
onStart,
|
|
||||||
onStop,
|
|
||||||
disabled,
|
|
||||||
}: {
|
|
||||||
isListening: boolean;
|
|
||||||
onStart: () => void;
|
|
||||||
onStop: () => void;
|
|
||||||
disabled: boolean;
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<IconButton
|
|
||||||
title={isListening ? 'Stop listening' : 'Start speech recognition'}
|
|
||||||
disabled={disabled}
|
|
||||||
className={classNames('transition-all', {
|
|
||||||
'text-bolt-elements-item-contentAccent': isListening,
|
|
||||||
})}
|
|
||||||
onClick={isListening ? onStop : onStart}
|
|
||||||
>
|
|
||||||
{isListening ? <div className="i-ph:microphone-slash text-xl" /> : <div className="i-ph:microphone text-xl" />}
|
|
||||||
</IconButton>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
|
63
app/components/chat/ModelSelector.tsx
Normal file
63
app/components/chat/ModelSelector.tsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import type { ProviderInfo } from '~/types/model';
|
||||||
|
import type { ModelInfo } from '~/utils/types';
|
||||||
|
|
||||||
|
interface ModelSelectorProps {
|
||||||
|
model?: string;
|
||||||
|
setModel?: (model: string) => void;
|
||||||
|
provider?: ProviderInfo;
|
||||||
|
setProvider?: (provider: ProviderInfo) => void;
|
||||||
|
modelList: ModelInfo[];
|
||||||
|
providerList: ProviderInfo[];
|
||||||
|
apiKeys: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ModelSelector = ({
|
||||||
|
model,
|
||||||
|
setModel,
|
||||||
|
provider,
|
||||||
|
setProvider,
|
||||||
|
modelList,
|
||||||
|
providerList,
|
||||||
|
}: ModelSelectorProps) => {
|
||||||
|
return (
|
||||||
|
<div className="mb-2 flex gap-2 flex-col sm:flex-row">
|
||||||
|
<select
|
||||||
|
value={provider?.name ?? ''}
|
||||||
|
onChange={(e) => {
|
||||||
|
const newProvider = providerList.find((p: ProviderInfo) => p.name === e.target.value);
|
||||||
|
|
||||||
|
if (newProvider && setProvider) {
|
||||||
|
setProvider(newProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstModel = [...modelList].find((m) => m.provider === e.target.value);
|
||||||
|
|
||||||
|
if (firstModel && setModel) {
|
||||||
|
setModel(firstModel.name);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="flex-1 p-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus transition-all"
|
||||||
|
>
|
||||||
|
{providerList.map((provider: ProviderInfo) => (
|
||||||
|
<option key={provider.name} value={provider.name}>
|
||||||
|
{provider.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<select
|
||||||
|
key={provider?.name}
|
||||||
|
value={model}
|
||||||
|
onChange={(e) => setModel?.(e.target.value)}
|
||||||
|
className="flex-1 p-2 rounded-lg border border-bolt-elements-borderColor bg-bolt-elements-prompt-background text-bolt-elements-textPrimary focus:outline-none focus:ring-2 focus:ring-bolt-elements-focus transition-all lg:max-w-[70%]"
|
||||||
|
>
|
||||||
|
{[...modelList]
|
||||||
|
.filter((e) => e.provider == provider?.name && e.name)
|
||||||
|
.map((modelOption) => (
|
||||||
|
<option key={modelOption.name} value={modelOption.name}>
|
||||||
|
{modelOption.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
28
app/components/chat/SpeechRecognition.tsx
Normal file
28
app/components/chat/SpeechRecognition.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { IconButton } from '~/components/ui/IconButton';
|
||||||
|
import { classNames } from '~/utils/classNames';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export const SpeechRecognitionButton = ({
|
||||||
|
isListening,
|
||||||
|
onStart,
|
||||||
|
onStop,
|
||||||
|
disabled,
|
||||||
|
}: {
|
||||||
|
isListening: boolean;
|
||||||
|
onStart: () => void;
|
||||||
|
onStop: () => void;
|
||||||
|
disabled: boolean;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
title={isListening ? 'Stop listening' : 'Start speech recognition'}
|
||||||
|
disabled={disabled}
|
||||||
|
className={classNames('transition-all', {
|
||||||
|
'text-bolt-elements-item-contentAccent': isListening,
|
||||||
|
})}
|
||||||
|
onClick={isListening ? onStop : onStart}
|
||||||
|
>
|
||||||
|
{isListening ? <div className="i-ph:microphone-slash text-xl" /> : <div className="i-ph:microphone text-xl" />}
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user