mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-15 23:15:30 +01:00
cleanup: code formatting and improve readability across multiple components
This commit is contained in:
parent
4808c5be48
commit
a06e999dd6
144 changed files with 608 additions and 648 deletions
12
client/src/@types/i18next.d.ts
vendored
12
client/src/@types/i18next.d.ts
vendored
|
|
@ -1,9 +1,9 @@
|
|||
import { defaultNS, resources } from '~/locales/i18n';
|
||||
|
||||
declare module 'i18next' {
|
||||
interface CustomTypeOptions {
|
||||
defaultNS: typeof defaultNS;
|
||||
resources: typeof resources.en;
|
||||
strictKeyChecks: true
|
||||
}
|
||||
}
|
||||
interface CustomTypeOptions {
|
||||
defaultNS: typeof defaultNS;
|
||||
resources: typeof resources.en;
|
||||
strictKeyChecks: true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
export type RenderProp<
|
||||
P = React.HTMLAttributes<any> & {
|
||||
ref?: React.Ref<any>;
|
||||
|
|
|
|||
|
|
@ -9,16 +9,17 @@ export function useDebounceCodeBlock() {
|
|||
const setCodeBlocks = useSetRecoilState(codeBlocksState);
|
||||
const setCodeBlockIds = useSetRecoilState(codeBlockIdsState);
|
||||
|
||||
const updateCodeBlock = useCallback((codeBlock: CodeBlock) => {
|
||||
console.log('Updating code block:', codeBlock);
|
||||
setCodeBlocks((prev) => ({
|
||||
...prev,
|
||||
[codeBlock.id]: codeBlock,
|
||||
}));
|
||||
setCodeBlockIds((prev) =>
|
||||
prev.includes(codeBlock.id) ? prev : [...prev, codeBlock.id],
|
||||
);
|
||||
}, [setCodeBlocks, setCodeBlockIds]);
|
||||
const updateCodeBlock = useCallback(
|
||||
(codeBlock: CodeBlock) => {
|
||||
console.log('Updating code block:', codeBlock);
|
||||
setCodeBlocks((prev) => ({
|
||||
...prev,
|
||||
[codeBlock.id]: codeBlock,
|
||||
}));
|
||||
setCodeBlockIds((prev) => (prev.includes(codeBlock.id) ? prev : [...prev, codeBlock.id]));
|
||||
},
|
||||
[setCodeBlocks, setCodeBlockIds],
|
||||
);
|
||||
|
||||
const debouncedUpdateCodeBlock = useCallback(
|
||||
debounce((codeBlock: CodeBlock) => {
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ function AuthLayout({
|
|||
{children}
|
||||
{!pathname.includes('2fa') &&
|
||||
(pathname.includes('login') || pathname.includes('register')) && (
|
||||
<SocialLoginRender startupConfig={startupConfig} />
|
||||
)}
|
||||
<SocialLoginRender startupConfig={startupConfig} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Footer startupConfig={startupConfig} />
|
||||
|
|
|
|||
|
|
@ -105,23 +105,12 @@ function RequestPasswordReset() {
|
|||
},
|
||||
})}
|
||||
aria-invalid={!!errors.email}
|
||||
className="
|
||||
peer w-full rounded-lg border border-gray-300 bg-transparent px-4 py-3
|
||||
text-base text-gray-900 placeholder-transparent transition-all
|
||||
focus:border-green-500 focus:outline-none focus:ring-2 focus:ring-green-500/20
|
||||
dark:border-gray-700 dark:text-white dark:focus:border-green-500
|
||||
"
|
||||
className="peer w-full rounded-lg border border-gray-300 bg-transparent px-4 py-3 text-base text-gray-900 placeholder-transparent transition-all focus:border-green-500 focus:outline-none focus:ring-2 focus:ring-green-500/20 dark:border-gray-700 dark:text-white dark:focus:border-green-500"
|
||||
placeholder="email@example.com"
|
||||
/>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="
|
||||
absolute -top-2 left-2 z-10 bg-white px-2 text-sm text-gray-600
|
||||
transition-all peer-placeholder-shown:top-3 peer-placeholder-shown:text-base
|
||||
peer-placeholder-shown:text-gray-500 peer-focus:-top-2 peer-focus:text-sm
|
||||
peer-focus:text-green-600 dark:bg-gray-900 dark:text-gray-400
|
||||
dark:peer-focus:text-green-500
|
||||
"
|
||||
className="absolute -top-2 left-2 z-10 bg-white px-2 text-sm text-gray-600 transition-all peer-placeholder-shown:top-3 peer-placeholder-shown:text-base peer-placeholder-shown:text-gray-500 peer-focus:-top-2 peer-focus:text-sm peer-focus:text-green-600 dark:bg-gray-900 dark:text-gray-400 dark:peer-focus:text-green-500"
|
||||
>
|
||||
{localize('com_auth_email_address')}
|
||||
</label>
|
||||
|
|
@ -136,12 +125,7 @@ function RequestPasswordReset() {
|
|||
<button
|
||||
type="submit"
|
||||
disabled={!!errors.email}
|
||||
className="
|
||||
w-full rounded-2xl bg-green-600 px-4 py-3 text-sm font-medium text-white
|
||||
transition-colors hover:bg-green-700 focus:outline-none focus:ring-2
|
||||
focus:ring-green-500 focus:ring-offset-2 disabled:opacity-50
|
||||
disabled:hover:bg-green-600 dark:bg-green-600 dark:hover:bg-green-700
|
||||
"
|
||||
className="w-full rounded-2xl bg-green-600 px-4 py-3 text-sm font-medium text-white transition-colors hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 disabled:opacity-50 disabled:hover:bg-green-600 dark:bg-green-600 dark:hover:bg-green-700"
|
||||
>
|
||||
{localize('com_auth_continue')}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -89,20 +89,12 @@ function ResetPassword() {
|
|||
},
|
||||
})}
|
||||
aria-invalid={!!errors.password}
|
||||
className="
|
||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||
"
|
||||
className="webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none"
|
||||
placeholder=" "
|
||||
/>
|
||||
<label
|
||||
htmlFor="password"
|
||||
className="
|
||||
absolute start-3 top-1.5 z-10 origin-[0] -translate-y-4 scale-75 transform bg-surface-primary px-2 text-sm text-text-secondary-alt duration-200
|
||||
peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100
|
||||
peer-focus:top-1.5 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-2 peer-focus:text-green-500
|
||||
rtl:peer-focus:left-auto rtl:peer-focus:translate-x-1/4
|
||||
"
|
||||
className="absolute start-3 top-1.5 z-10 origin-[0] -translate-y-4 scale-75 transform bg-surface-primary px-2 text-sm text-text-secondary-alt duration-200 peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100 peer-focus:top-1.5 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-2 peer-focus:text-green-500 rtl:peer-focus:left-auto rtl:peer-focus:translate-x-1/4"
|
||||
>
|
||||
{localize('com_auth_password')}
|
||||
</label>
|
||||
|
|
@ -124,20 +116,12 @@ function ResetPassword() {
|
|||
validate: (value) => value === password || localize('com_auth_password_not_match'),
|
||||
})}
|
||||
aria-invalid={!!errors.confirm_password}
|
||||
className="
|
||||
webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light
|
||||
bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none
|
||||
"
|
||||
className="webkit-dark-styles transition-color peer w-full rounded-2xl border border-border-light bg-surface-primary px-3.5 pb-2.5 pt-3 text-text-primary duration-200 focus:border-green-500 focus:outline-none"
|
||||
placeholder=" "
|
||||
/>
|
||||
<label
|
||||
htmlFor="confirm_password"
|
||||
className="
|
||||
absolute start-3 top-1.5 z-10 origin-[0] -translate-y-4 scale-75 transform bg-surface-primary px-2 text-sm text-text-secondary-alt duration-200
|
||||
peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100
|
||||
peer-focus:top-1.5 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-2 peer-focus:text-green-500
|
||||
rtl:peer-focus:left-auto rtl:peer-focus:translate-x-1/4
|
||||
"
|
||||
className="absolute start-3 top-1.5 z-10 origin-[0] -translate-y-4 scale-75 transform bg-surface-primary px-2 text-sm text-text-secondary-alt duration-200 peer-placeholder-shown:top-1/2 peer-placeholder-shown:-translate-y-1/2 peer-placeholder-shown:scale-100 peer-focus:top-1.5 peer-focus:-translate-y-4 peer-focus:scale-75 peer-focus:px-2 peer-focus:text-green-500 rtl:peer-focus:left-auto rtl:peer-focus:translate-x-1/4"
|
||||
>
|
||||
{localize('com_auth_password_confirm')}
|
||||
</label>
|
||||
|
|
@ -163,12 +147,7 @@ function ResetPassword() {
|
|||
disabled={!!errors.password || !!errors.confirm_password}
|
||||
type="submit"
|
||||
aria-label={localize('com_auth_submit_registration')}
|
||||
className="
|
||||
w-full rounded-2xl bg-green-600 px-4 py-3 text-sm font-medium text-white
|
||||
transition-colors hover:bg-green-700 focus:outline-none focus:ring-2
|
||||
focus:ring-green-500 focus:ring-offset-2 disabled:opacity-50
|
||||
disabled:hover:bg-green-600 dark:bg-green-600 dark:hover:bg-green-700
|
||||
"
|
||||
className="w-full rounded-2xl bg-green-600 px-4 py-3 text-sm font-medium text-white transition-colors hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 disabled:opacity-50 disabled:hover:bg-green-600 dark:bg-green-600 dark:hover:bg-green-700"
|
||||
>
|
||||
{localize('com_auth_continue')}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -156,7 +156,6 @@ test('renders registration form', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line jest/no-commented-out-tests
|
||||
// test('calls registerUser.mutate on registration', async () => {
|
||||
// const mutate = jest.fn();
|
||||
// const { getByTestId, getByRole, history } = setup({
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
export default function DragDropOverlay() {
|
||||
return (
|
||||
<div
|
||||
className="bg-surface-primary/85 fixed inset-0 z-[9999] flex flex-col items-center justify-center
|
||||
gap-2 text-text-primary
|
||||
backdrop-blur-[4px] transition-all duration-200
|
||||
ease-in-out animate-in fade-in
|
||||
zoom-in-95 hover:backdrop-blur-sm"
|
||||
>
|
||||
<div className="bg-surface-primary/85 fixed inset-0 z-[9999] flex flex-col items-center justify-center gap-2 text-text-primary backdrop-blur-[4px] transition-all duration-200 ease-in-out animate-in fade-in zoom-in-95 hover:backdrop-blur-sm">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 132 108"
|
||||
|
|
@ -55,8 +49,8 @@ export default function DragDropOverlay() {
|
|||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
<h3>Add anything</h3>
|
||||
<h4>Drop any file here to add it to the conversation</h4>
|
||||
<h3>{localize('com_ui_add_anything')}</h3>
|
||||
<h4>{localize('com_ui_add_anything_description')}</h4>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,9 +93,9 @@ const ImagePreview = ({
|
|||
|
||||
const style: styleProps = imageUrl
|
||||
? {
|
||||
...baseStyle,
|
||||
backgroundImage: `url(${imageUrl})`,
|
||||
}
|
||||
...baseStyle,
|
||||
backgroundImage: `url(${imageUrl})`,
|
||||
}
|
||||
: baseStyle;
|
||||
|
||||
if (typeof style.backgroundImage !== 'string' || style.backgroundImage.length === 0) {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ export default function StreamAudio({ index = 0 }) {
|
|||
const { pauseGlobalAudio } = usePauseGlobalAudio();
|
||||
|
||||
const { conversationId: paramId } = useParams();
|
||||
const queryParam = paramId === 'new' ? paramId : latestMessage?.conversationId ?? paramId ?? '';
|
||||
const queryParam = paramId === 'new' ? paramId : (latestMessage?.conversationId ?? paramId ?? '');
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const getMessages = useCallback(
|
||||
|
|
|
|||
|
|
@ -102,12 +102,12 @@ export function EndpointItem({ endpoint }: EndpointItemProps) {
|
|||
if (endpoint.hasModels) {
|
||||
const filteredModels = searchValue
|
||||
? filterModels(
|
||||
endpoint,
|
||||
(endpoint.models || []).map((model) => model.name),
|
||||
searchValue,
|
||||
agentsMap,
|
||||
assistantsMap,
|
||||
)
|
||||
endpoint,
|
||||
(endpoint.models || []).map((model) => model.name),
|
||||
searchValue,
|
||||
agentsMap,
|
||||
assistantsMap,
|
||||
)
|
||||
: null;
|
||||
const placeholder =
|
||||
isAgentsEndpoint(endpoint.value) || isAssistantsEndpoint(endpoint.value)
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ export function EndpointModelItem({ modelId, endpoint, isSelected }: EndpointMod
|
|||
</div>
|
||||
) : (isAgentsEndpoint(endpoint.value) || isAssistantsEndpoint(endpoint.value)) &&
|
||||
endpoint.icon ? (
|
||||
<div className="flex h-5 w-5 items-center justify-center overflow-hidden rounded-full">
|
||||
{endpoint.icon}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex h-5 w-5 items-center justify-center overflow-hidden rounded-full">
|
||||
{endpoint.icon}
|
||||
</div>
|
||||
) : null}
|
||||
<span>{modelName}</span>
|
||||
</div>
|
||||
{isGlobal && <EarthIcon className="ml-auto size-4 text-green-400" />}
|
||||
|
|
|
|||
|
|
@ -102,22 +102,22 @@ export function SearchResults({ results, localize, searchValue }: SearchResultsP
|
|||
const filteredModels = endpoint.label.toLowerCase().includes(lowerQuery)
|
||||
? endpoint.models
|
||||
: endpoint.models.filter((model) => {
|
||||
let modelName = model.name;
|
||||
if (
|
||||
isAgentsEndpoint(endpoint.value) &&
|
||||
let modelName = model.name;
|
||||
if (
|
||||
isAgentsEndpoint(endpoint.value) &&
|
||||
endpoint.agentNames &&
|
||||
endpoint.agentNames[model.name]
|
||||
) {
|
||||
modelName = endpoint.agentNames[model.name];
|
||||
} else if (
|
||||
isAssistantsEndpoint(endpoint.value) &&
|
||||
) {
|
||||
modelName = endpoint.agentNames[model.name];
|
||||
} else if (
|
||||
isAssistantsEndpoint(endpoint.value) &&
|
||||
endpoint.assistantNames &&
|
||||
endpoint.assistantNames[model.name]
|
||||
) {
|
||||
modelName = endpoint.assistantNames[model.name];
|
||||
}
|
||||
return modelName.toLowerCase().includes(lowerQuery);
|
||||
});
|
||||
) {
|
||||
modelName = endpoint.assistantNames[model.name];
|
||||
}
|
||||
return modelName.toLowerCase().includes(lowerQuery);
|
||||
});
|
||||
|
||||
if (!filteredModels.length) {
|
||||
return null; // skip if no models match
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export const data: TModelSpec[] = [
|
|||
iconURL: EModelEndpoint.openAI, // Allow using project-included icons
|
||||
preset: {
|
||||
chatGptLabel: 'Vision Helper',
|
||||
greeting: 'What\'s up!!',
|
||||
greeting: "What's up!!",
|
||||
endpoint: EModelEndpoint.openAI,
|
||||
model: 'gpt-4-turbo',
|
||||
promptPrefix:
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ const MenuItem: FC<MenuItemProps> = ({
|
|||
>
|
||||
<div className="flex grow items-center justify-between gap-2">
|
||||
<div>
|
||||
<div className={cn('flex items-center gap-1 ')}>
|
||||
<div className={cn('flex items-center gap-1')}>
|
||||
{icon != null ? icon : null}
|
||||
<div className={cn('truncate', textClassName)}>
|
||||
{title}
|
||||
|
|
@ -72,7 +72,7 @@ const MenuItem: FC<MenuItemProps> = ({
|
|||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="icon-md block "
|
||||
className="icon-md block"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
|
|
|
|||
|
|
@ -117,9 +117,9 @@ const EditTextPart = ({
|
|||
messages.map((msg) =>
|
||||
msg.messageId === messageId
|
||||
? {
|
||||
...msg,
|
||||
content: updatedContent,
|
||||
}
|
||||
...msg,
|
||||
content: updatedContent,
|
||||
}
|
||||
: msg,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil';
|
|||
import { useMessageProcess } from '~/hooks';
|
||||
import type { TMessageProps } from '~/common';
|
||||
import MessageRender from './ui/MessageRender';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
|
||||
import MultiMessage from './MultiMessage';
|
||||
import { cn } from '~/utils';
|
||||
import store from '~/store';
|
||||
|
|
@ -73,7 +73,7 @@ export default function Message(props: TMessageProps) {
|
|||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="m-auto justify-center p-4 py-2 md:gap-6 ">
|
||||
<div className="m-auto justify-center p-4 py-2 md:gap-6">
|
||||
<MessageRender {...props} />
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ export function TemporaryChat() {
|
|||
render={
|
||||
<button
|
||||
onClick={handleBadgeToggle}
|
||||
aria-label={localize(temporaryBadge.label)}
|
||||
aria-label={localize(temporaryBadge.label)}
|
||||
className={cn(
|
||||
'inline-flex size-10 flex-shrink-0 items-center justify-center rounded-xl border border-border-light text-text-primary transition-all ease-in-out hover:bg-surface-tertiary',
|
||||
isTemporary
|
||||
|
|
|
|||
|
|
@ -48,15 +48,15 @@ const UserAvatar = memo(({ size, user, avatarSrc, username, className }: UserAva
|
|||
>
|
||||
{(!(user?.avatar ?? '') && (!(user?.username ?? '') || user?.username.trim() === '')) ||
|
||||
imageError ? (
|
||||
renderDefaultAvatar()
|
||||
) : (
|
||||
<img
|
||||
className="rounded-full"
|
||||
src={(user?.avatar ?? '') || avatarSrc}
|
||||
alt="avatar"
|
||||
onError={handleImageError}
|
||||
/>
|
||||
)}
|
||||
renderDefaultAvatar()
|
||||
) : (
|
||||
<img
|
||||
className="rounded-full"
|
||||
src={(user?.avatar ?? '') || avatarSrc}
|
||||
alt="avatar"
|
||||
onError={handleImageError}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ const SaveAsPresetDialog = ({ open, onOpenChange, preset }: TEditPresetProps) =>
|
|||
});
|
||||
|
||||
const toastTitle =
|
||||
_preset.title ?? '' ? `\`${_preset.title}\`` : localize('com_endpoint_preset_title');
|
||||
(_preset.title ?? '') ? `\`${_preset.title}\`` : localize('com_endpoint_preset_title');
|
||||
|
||||
createPresetMutation.mutate(_preset, {
|
||||
onSuccess: () => {
|
||||
|
|
@ -76,7 +76,7 @@ const SaveAsPresetDialog = ({ open, onOpenChange, preset }: TEditPresetProps) =>
|
|||
aria-label={localize('com_endpoint_preset_name')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex h-10 max-h-10 w-full resize-none border-border-medium px-3 py-2 ',
|
||||
'flex h-10 max-h-10 w-full resize-none border-border-medium px-3 py-2',
|
||||
removeFocusOutlines,
|
||||
)}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ export default function Settings({
|
|||
placeholder={localize('com_endpoint_openai_prompt_prefix_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[138px] min-h-[100px] w-full resize-none px-3 py-2 ',
|
||||
'flex max-h-[138px] min-h-[100px] w-full resize-none px-3 py-2',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -160,6 +160,7 @@ export default function Settings({
|
|||
<div className="flex justify-between">
|
||||
<Label htmlFor="top-p-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_top_p')}{' '}
|
||||
{/* eslint-disable-next-line i18next/no-literal-string */}
|
||||
<small className="opacity-40">({localize('com_endpoint_default')}: 1)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
|
|
@ -198,7 +199,8 @@ export default function Settings({
|
|||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="freq-penalty-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_frequency_penalty')}{' '}
|
||||
{localize('com_endpoint_frequency_penalty')}
|
||||
{/* eslint-disable-next-line i18next/no-literal-string */}
|
||||
<small className="opacity-40">({localize('com_endpoint_default')}: 0)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
|
|
@ -238,6 +240,7 @@ export default function Settings({
|
|||
<div className="flex justify-between">
|
||||
<Label htmlFor="pres-penalty-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_presence_penalty')}{' '}
|
||||
{/* eslint-disable-next-line i18next/no-literal-string */}
|
||||
<small className="opacity-40">({localize('com_endpoint_default')}: 0)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
placeholder={localize('com_endpoint_prompt_prefix_assistants_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[240px] min-h-[80px] w-full resize-none px-3 py-2 ',
|
||||
'flex max-h-[240px] min-h-[80px] w-full resize-none px-3 py-2',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -178,7 +178,7 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
placeholder={localize('com_endpoint_instructions_assistants_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[240px] min-h-[80px] w-full resize-none px-3 py-2 ',
|
||||
'flex max-h-[240px] min-h-[80px] w-full resize-none px-3 py-2',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ function Examples({ readonly, examples, setExample, addExample, removeExample }:
|
|||
placeholder="Set example input. Example is ignored if empty."
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[138px] min-h-[75px] w-full resize-none px-3 py-2 ',
|
||||
'flex max-h-[138px] min-h-[75px] w-full resize-none px-3 py-2',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -67,7 +67,7 @@ function Examples({ readonly, examples, setExample, addExample, removeExample }:
|
|||
placeholder={'Set example output. Example is ignored if empty.'}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[300px] min-h-[75px] w-full resize-none px-3 py-2 ',
|
||||
'flex max-h-[300px] min-h-[75px] w-full resize-none px-3 py-2',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
placeholder={localize('com_endpoint_prompt_prefix_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[138px] min-h-[100px] w-full resize-none px-3 py-2 ',
|
||||
'flex max-h-[138px] min-h-[100px] w-full resize-none px-3 py-2',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -221,7 +221,7 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
<Label htmlFor="top-k-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_top_k')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num',{ 0: google.topK.default + '' })})
|
||||
({localize('com_endpoint_default_with_num', { 0: google.topK.default + '' })})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
|
|
@ -261,7 +261,11 @@ export default function Settings({ conversation, setOption, models, readonly }:
|
|||
<Label htmlFor="max-tokens-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_max_output_tokens')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', { 0: google.maxOutputTokens.default + '' })})
|
||||
(
|
||||
{localize('com_endpoint_default_with_num', {
|
||||
0: google.maxOutputTokens.default + '',
|
||||
})}
|
||||
)
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ export default function Settings({
|
|||
)}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[138px] min-h-[100px] w-full resize-none px-3 py-2 ',
|
||||
'flex max-h-[138px] min-h-[100px] w-full resize-none px-3 py-2',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export default function Continue({ onClick }: TGenButtonProps) {
|
|||
|
||||
return (
|
||||
<Button type="continue" onClick={onClick}>
|
||||
<ContinueIcon className="text-gray-600/90 dark:text-gray-400 " />
|
||||
<ContinueIcon className="text-gray-600/90 dark:text-gray-400" />
|
||||
{localize('com_ui_continue')}
|
||||
</Button>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export default function Stop({ onClick }: TGenButtonProps) {
|
|||
|
||||
return (
|
||||
<Button type="stop" onClick={onClick}>
|
||||
<StopGeneratingIcon className="text-gray-600/90 dark:text-gray-400 " />
|
||||
<StopGeneratingIcon className="text-gray-600/90 dark:text-gray-400" />
|
||||
{localize('com_ui_stop')}
|
||||
</Button>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -171,8 +171,8 @@ const SetKeyDialog = ({
|
|||
{expiryTime === 'never'
|
||||
? localize('com_endpoint_config_key_never_expires')
|
||||
: `${localize('com_endpoint_config_key_encryption')} ${new Date(
|
||||
expiryTime ?? 0,
|
||||
).toLocaleString()}`}
|
||||
expiryTime ?? 0,
|
||||
).toLocaleString()}`}
|
||||
</small>
|
||||
<Dropdown
|
||||
label="Expires "
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ const Plugin: React.FC<PluginProps> = ({ plugin }) => {
|
|||
if (!plugin.loading && latestPlugin === 'self reflection') {
|
||||
return 'Finished';
|
||||
} else if (latestPlugin === 'self reflection') {
|
||||
return 'I\'m thinking...';
|
||||
return "I'm thinking...";
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
|
|
@ -112,9 +112,7 @@ const Plugin: React.FC<PluginProps> = ({ plugin }) => {
|
|||
/>
|
||||
{plugin.outputs && plugin.outputs.length > 0 && (
|
||||
<CodeBlock
|
||||
lang={
|
||||
latestPlugin ? `RESPONSE FROM ${latestPlugin.toUpperCase()}` : 'RESPONSE'
|
||||
}
|
||||
lang={latestPlugin ? `RESPONSE FROM ${latestPlugin.toUpperCase()}` : 'RESPONSE'}
|
||||
codeChildren={formatJSON(plugin.outputs ?? '')}
|
||||
plugin={true}
|
||||
classProp="max-h-[450px]"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { useMessageProcess } from '~/hooks';
|
||||
import type { TMessageProps } from '~/common';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
|
||||
import MultiMessage from '~/components/Chat/Messages/MultiMessage';
|
||||
import ContentRender from './ContentRender';
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ export default function MessageContent(props: TMessageProps) {
|
|||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="m-auto justify-center p-4 py-2 md:gap-6 ">
|
||||
<div className="m-auto justify-center p-4 py-2 md:gap-6">
|
||||
<ContentRender {...props} />
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export default function NavToggle({
|
|||
className,
|
||||
'-translate-y-1/2 transition-transform',
|
||||
navVisible ? 'rotate-0' : 'rotate-180',
|
||||
navVisible && translateX ? 'translate-x-[260px]' : 'translate-x-0 ',
|
||||
navVisible && translateX ? 'translate-x-[260px]' : 'translate-x-0',
|
||||
)}
|
||||
onMouseEnter={() => setIsHovering(true)}
|
||||
onMouseLeave={() => setIsHovering(false)}
|
||||
|
|
|
|||
|
|
@ -87,11 +87,11 @@ export default function Settings({ open, onOpenChange }: TDialogProps) {
|
|||
},
|
||||
...(startupConfig?.balance?.enabled
|
||||
? [
|
||||
{
|
||||
value: SettingsTabValues.BALANCE,
|
||||
{
|
||||
value: SettingsTabValues.BALANCE,
|
||||
icon: <DollarSign size={18} />,
|
||||
label: 'com_nav_setting_balance' as TranslationKeys,
|
||||
},
|
||||
label: 'com_nav_setting_balance' as TranslationKeys,
|
||||
},
|
||||
]
|
||||
: ([] as { value: SettingsTabValues; icon: React.JSX.Element; label: TranslationKeys }[])),
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ export default function DecibelSelector() {
|
|||
<div className="flex items-center justify-between">
|
||||
<div>{localize('com_nav_db_sensitivity')}</div>
|
||||
<div className="w-2" />
|
||||
<small className="opacity-40">({localize('com_endpoint_default_with_num', { 0: '-45' })})</small>
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', { 0: '-45' })})
|
||||
</small>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<Slider
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ const EngineSTTDropdown: React.FC<EngineSTTDropdownProps> = ({ external }) => {
|
|||
|
||||
const endpointOptions = external
|
||||
? [
|
||||
{ value: 'browser', label: localize('com_nav_browser') },
|
||||
{ value: 'external', label: localize('com_nav_external') },
|
||||
]
|
||||
{ value: 'browser', label: localize('com_nav_browser') },
|
||||
{ value: 'external', label: localize('com_nav_external') },
|
||||
]
|
||||
: [{ value: 'browser', label: localize('com_nav_browser') }];
|
||||
|
||||
const handleSelect = (value: string) => {
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ const EngineTTSDropdown: React.FC<EngineTTSDropdownProps> = ({ external }) => {
|
|||
|
||||
const endpointOptions = external
|
||||
? [
|
||||
{ value: 'browser', label: localize('com_nav_browser') },
|
||||
{ value: 'external', label: localize('com_nav_external') },
|
||||
]
|
||||
{ value: 'browser', label: localize('com_nav_browser') },
|
||||
{ value: 'external', label: localize('com_nav_external') },
|
||||
]
|
||||
: [{ value: 'browser', label: localize('com_nav_browser') }];
|
||||
|
||||
const handleSelect = (value: string) => {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ export default function DecibelSelector() {
|
|||
<div className="flex items-center justify-between">
|
||||
<div>{localize('com_nav_playback_rate')}</div>
|
||||
<div className="w-2" />
|
||||
<small className="opacity-40">({localize('com_endpoint_default_with_num', { 0: '1' })})</small>
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', { 0: '1' })})
|
||||
</small>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<Slider
|
||||
|
|
|
|||
|
|
@ -187,8 +187,7 @@ function PluginStoreDialog({ isOpen, setIsOpen }: TPluginStoreDialogProps) {
|
|||
value={searchValue}
|
||||
onChange={handleSearch}
|
||||
placeholder={localize('com_nav_plugin_search')}
|
||||
className="
|
||||
text-token-text-primary flex rounded-md border border-border-heavy bg-surface-tertiary py-2 pl-10 pr-2"
|
||||
className="text-token-text-primary flex rounded-md border border-border-heavy bg-surface-tertiary py-2 pl-10 pr-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ type TPluginTooltipProps = {
|
|||
function PluginTooltip({ content, position }: TPluginTooltipProps) {
|
||||
return (
|
||||
<HoverCardPortal>
|
||||
<HoverCardContent side={position} className="w-80 ">
|
||||
<HoverCardContent side={position} className="w-80">
|
||||
<div className="space-y-2">
|
||||
<div className="text-sm text-gray-600 dark:text-gray-300">
|
||||
<div dangerouslySetInnerHTML={{ __html: content }} />
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ export default function FilterPrompts({
|
|||
const categoryOptions = categories
|
||||
? [...categories]
|
||||
: [
|
||||
{
|
||||
value: SystemCategories.NO_CATEGORY,
|
||||
label: localize('com_ui_no_category'),
|
||||
},
|
||||
];
|
||||
{
|
||||
value: SystemCategories.NO_CATEGORY,
|
||||
label: localize('com_ui_no_category'),
|
||||
},
|
||||
];
|
||||
|
||||
return [...baseOptions, ...categoryOptions];
|
||||
}, [categories, localize]);
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@ export default function ListCard({
|
|||
<div
|
||||
onClick={onClick}
|
||||
onKeyDown={handleKeyDown}
|
||||
className="relative my-2 flex w-full cursor-pointer flex-col gap-2 rounded-xl border border-border-light px-3 pb-4 pt-3 text-start
|
||||
align-top text-[15px] shadow-sm transition-all duration-300 ease-in-out hover:bg-surface-tertiary hover:shadow-lg"
|
||||
className="relative my-2 flex w-full cursor-pointer flex-col gap-2 rounded-xl border border-border-light px-3 pb-4 pt-3 text-start align-top text-[15px] shadow-sm transition-all duration-300 ease-in-out hover:bg-surface-tertiary hover:shadow-lg"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-labelledby={`card-title-${name}`}
|
||||
|
|
|
|||
|
|
@ -287,18 +287,18 @@ const PromptForm = () => {
|
|||
{editorMode === PromptsEditorMode.ADVANCED &&
|
||||
(isLoadingPrompts
|
||||
? Array.from({ length: 6 }).map((_, index: number) => (
|
||||
<div key={index} className="my-2">
|
||||
<Skeleton className="h-[72px] w-full" />
|
||||
</div>
|
||||
))
|
||||
<div key={index} className="my-2">
|
||||
<Skeleton className="h-[72px] w-full" />
|
||||
</div>
|
||||
))
|
||||
: prompts.length > 0 && (
|
||||
<PromptVersions
|
||||
group={group}
|
||||
prompts={prompts}
|
||||
selectionIndex={selectionIndex}
|
||||
setSelectionIndex={setSelectionIndex}
|
||||
/>
|
||||
))}
|
||||
<PromptVersions
|
||||
group={group}
|
||||
prompts={prompts}
|
||||
selectionIndex={selectionIndex}
|
||||
setSelectionIndex={setSelectionIndex}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { useEffect } from 'react';
|
|||
import { useRecoilState } from 'recoil';
|
||||
import type { TMessage } from 'librechat-data-provider';
|
||||
import type { TMessageProps } from '~/common';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
|
||||
import Message from './Message';
|
||||
import store from '~/store';
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export default function ImageVision() {
|
|||
{...field}
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
className="relative float-left mr-2 inline-flex h-4 w-4 cursor-pointer"
|
||||
className="relative float-left mr-2 inline-flex h-4 w-4 cursor-pointer"
|
||||
value={field.value?.toString()}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -135,10 +135,9 @@ export default function ShareAgent({
|
|||
'btn btn-neutral border-token-border-light relative h-9 rounded-lg font-medium',
|
||||
removeFocusOutlines,
|
||||
)}
|
||||
aria-label={localize(
|
||||
'com_ui_share_var',
|
||||
{ 0: agentName != null && agentName !== '' ? `"${agentName}"` : localize('com_ui_agent') },
|
||||
)}
|
||||
aria-label={localize('com_ui_share_var', {
|
||||
0: agentName != null && agentName !== '' ? `"${agentName}"` : localize('com_ui_agent'),
|
||||
})}
|
||||
type="button"
|
||||
>
|
||||
<div className="flex items-center justify-center gap-2 text-blue-500">
|
||||
|
|
@ -148,10 +147,9 @@ export default function ShareAgent({
|
|||
</OGDialogTrigger>
|
||||
<OGDialogContent className="w-11/12 md:max-w-xl">
|
||||
<OGDialogTitle>
|
||||
{localize(
|
||||
'com_ui_share_var',
|
||||
{ 0: agentName != null && agentName !== '' ? `"${agentName}"` : localize('com_ui_agent') },
|
||||
)}
|
||||
{localize('com_ui_share_var', {
|
||||
0: agentName != null && agentName !== '' ? `"${agentName}"` : localize('com_ui_agent'),
|
||||
})}
|
||||
</OGDialogTitle>
|
||||
<form
|
||||
className="p-2"
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ const BookmarkTableRow: React.FC<BookmarkTableRowProps> = ({ row, moveRow, posit
|
|||
accept: 'bookmark',
|
||||
drop: handleDrop,
|
||||
hover(item: DragItem) {
|
||||
if (!ref.current || item.index === position) {return;}
|
||||
if (!ref.current || item.index === position) {
|
||||
return;
|
||||
}
|
||||
moveRow(item.index, position);
|
||||
item.index = position;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -33,9 +33,7 @@ export default function ActionsAuth({ disableOAuth }: { disableOAuth?: boolean }
|
|||
</label>
|
||||
</div>
|
||||
<div className="border-token-border-medium flex rounded-lg border text-sm hover:cursor-pointer">
|
||||
<div className="h-9 grow px-3 py-2">
|
||||
{localize(getAuthLocalizationKey(type))}
|
||||
</div>
|
||||
<div className="h-9 grow px-3 py-2">{localize(getAuthLocalizationKey(type))}</div>
|
||||
<div className="bg-token-border-medium w-px"></div>
|
||||
<button type="button" color="neutral" className="flex items-center gap-2 px-3">
|
||||
<svg
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export default function Code({ version }: { version: number | string }) {
|
|||
{...field}
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
className="relative float-left mr-2 inline-flex h-4 w-4 cursor-pointer"
|
||||
className="relative float-left mr-2 inline-flex h-4 w-4 cursor-pointer"
|
||||
value={field.value.toString()}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export default function ImageVision() {
|
|||
{...field}
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
className="relative float-left mr-2 inline-flex h-4 w-4 cursor-pointer"
|
||||
className="relative float-left mr-2 inline-flex h-4 w-4 cursor-pointer"
|
||||
value={field.value.toString()}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ function DynamicCheckbox({
|
|||
htmlFor={`${settingKey}-dynamic-checkbox`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}{' '}
|
||||
{labelCode ? (localize(label as TranslationKeys) ?? label) : label || settingKey}{' '}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default')}:{' '}
|
||||
|
|
@ -81,7 +81,11 @@ function DynamicCheckbox({
|
|||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
description={
|
||||
descriptionCode
|
||||
? (localize(description as TranslationKeys) ?? description)
|
||||
: description
|
||||
}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ function DynamicCombobox({
|
|||
htmlFor={`${settingKey}-dynamic-combobox`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}
|
||||
{labelCode ? (localize(label as TranslationKeys) ?? label) : label || settingKey}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default')}: {defaultValue})
|
||||
|
|
@ -97,10 +97,14 @@ function DynamicCombobox({
|
|||
<ControlCombobox
|
||||
displayValue={selectedValue}
|
||||
selectPlaceholder={
|
||||
selectPlaceholderCode === true ? localize(selectPlaceholder as TranslationKeys) : selectPlaceholder
|
||||
selectPlaceholderCode === true
|
||||
? localize(selectPlaceholder as TranslationKeys)
|
||||
: selectPlaceholder
|
||||
}
|
||||
searchPlaceholder={
|
||||
searchPlaceholderCode === true ? localize(searchPlaceholder as TranslationKeys) : searchPlaceholder
|
||||
searchPlaceholderCode === true
|
||||
? localize(searchPlaceholder as TranslationKeys)
|
||||
: searchPlaceholder
|
||||
}
|
||||
isCollapsed={isCollapsed}
|
||||
ariaLabel={settingKey}
|
||||
|
|
@ -112,7 +116,11 @@ function DynamicCombobox({
|
|||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
description={
|
||||
descriptionCode
|
||||
? (localize(description as TranslationKeys) ?? description)
|
||||
: description
|
||||
}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ function DynamicDropdown({
|
|||
htmlFor={`${settingKey}-dynamic-dropdown`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}
|
||||
{labelCode ? (localize(label as TranslationKeys) ?? label) : label || settingKey}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default')}: {defaultValue})
|
||||
|
|
@ -96,12 +96,20 @@ function DynamicDropdown({
|
|||
availableValues={options}
|
||||
containerClassName="w-full"
|
||||
id={`${settingKey}-dynamic-dropdown`}
|
||||
placeholder={placeholderCode ? localize(placeholder as TranslationKeys) ?? placeholder : placeholder}
|
||||
placeholder={
|
||||
placeholderCode
|
||||
? (localize(placeholder as TranslationKeys) ?? placeholder)
|
||||
: placeholder
|
||||
}
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
description={
|
||||
descriptionCode
|
||||
? (localize(description as TranslationKeys) ?? description)
|
||||
: description
|
||||
}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -60,20 +60,26 @@ function DynamicSlider({
|
|||
|
||||
const enumToNumeric = useMemo(() => {
|
||||
if (isEnum && options) {
|
||||
return options.reduce((acc, mapping, index) => {
|
||||
acc[mapping] = index;
|
||||
return acc;
|
||||
}, {} as Record<string, number>);
|
||||
return options.reduce(
|
||||
(acc, mapping, index) => {
|
||||
acc[mapping] = index;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, number>,
|
||||
);
|
||||
}
|
||||
return {};
|
||||
}, [isEnum, options]);
|
||||
|
||||
const valueToEnumOption = useMemo(() => {
|
||||
if (isEnum && options) {
|
||||
return options.reduce((acc, option, index) => {
|
||||
acc[index] = option;
|
||||
return acc;
|
||||
}, {} as Record<number, string>);
|
||||
return options.reduce(
|
||||
(acc, option, index) => {
|
||||
acc[index] = option;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<number, string>,
|
||||
);
|
||||
}
|
||||
return {};
|
||||
}, [isEnum, options]);
|
||||
|
|
@ -117,7 +123,7 @@ function DynamicSlider({
|
|||
htmlFor={`${settingKey}-dynamic-setting`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}{' '}
|
||||
{labelCode ? (localize(label as TranslationKeys) ?? label) : label || settingKey}{' '}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default')}: {defaultValue})
|
||||
|
|
@ -132,7 +138,7 @@ function DynamicSlider({
|
|||
onChange={(value) => setInputValue(Number(value))}
|
||||
max={range ? range.max : (options?.length ?? 0) - 1}
|
||||
min={range ? range.min : 0}
|
||||
step={range ? range.step ?? 1 : 1}
|
||||
step={range ? (range.step ?? 1) : 1}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
|
|
@ -164,19 +170,23 @@ function DynamicSlider({
|
|||
value={[
|
||||
isEnum
|
||||
? enumToNumeric[(selectedValue as number) ?? '']
|
||||
: (inputValue as number) ?? (defaultValue as number),
|
||||
: ((inputValue as number) ?? (defaultValue as number)),
|
||||
]}
|
||||
onValueChange={(value) => handleValueChange(value[0])}
|
||||
onDoubleClick={() => setInputValue(defaultValue as string | number)}
|
||||
max={max}
|
||||
min={range ? range.min : 0}
|
||||
step={range ? range.step ?? 1 : 1}
|
||||
step={range ? (range.step ?? 1) : 1}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
description={
|
||||
descriptionCode
|
||||
? (localize(description as TranslationKeys) ?? description)
|
||||
: description
|
||||
}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ function DynamicTextarea({
|
|||
htmlFor={`${settingKey}-dynamic-textarea`}
|
||||
className="text-left text-sm font-medium"
|
||||
>
|
||||
{labelCode ? localize(label as TranslationKeys) ?? label : label || settingKey}{' '}
|
||||
{labelCode ? (localize(label as TranslationKeys) ?? label) : label || settingKey}{' '}
|
||||
{showDefault && (
|
||||
<small className="opacity-40">
|
||||
(
|
||||
|
|
@ -75,7 +75,11 @@ function DynamicTextarea({
|
|||
disabled={readonly}
|
||||
value={inputValue ?? ''}
|
||||
onChange={setInputValue}
|
||||
placeholder={placeholderCode ? localize(placeholder as TranslationKeys) ?? placeholder : placeholder}
|
||||
placeholder={
|
||||
placeholderCode
|
||||
? (localize(placeholder as TranslationKeys) ?? placeholder)
|
||||
: placeholder
|
||||
}
|
||||
className={cn(
|
||||
// TODO: configurable max height
|
||||
'flex max-h-[138px] min-h-[100px] w-full resize-none rounded-lg bg-surface-secondary px-3 py-2 focus:outline-none',
|
||||
|
|
@ -84,7 +88,11 @@ function DynamicTextarea({
|
|||
</HoverCardTrigger>
|
||||
{description && (
|
||||
<OptionHover
|
||||
description={descriptionCode ? localize(description as TranslationKeys) ?? description : description}
|
||||
description={
|
||||
descriptionCode
|
||||
? (localize(description as TranslationKeys) ?? description)
|
||||
: description
|
||||
}
|
||||
side={ESide.Left}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ export default function AppleIcon() {
|
|||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import { cn } from '~/utils/';
|
||||
|
||||
export default function AzureMinimalIcon({
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const AccordionTrigger = React.forwardRef<
|
|||
{...props}
|
||||
>
|
||||
{children}
|
||||
<ChevronDownIcon className="text-muted-foreground h-4 w-4 shrink-0 transition-transform duration-200" />
|
||||
<ChevronDownIcon className="h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200" />
|
||||
</AccordionPrimitive.Trigger>
|
||||
</AccordionPrimitive.Header>
|
||||
));
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ const AnimatedSearchInput = ({
|
|||
<div className="absolute left-3 top-1/2 z-50 -translate-y-1/2">
|
||||
<Search
|
||||
className={cn(
|
||||
`
|
||||
h-4 w-4 transition-all duration-500 ease-in-out`,
|
||||
`h-4 w-4 transition-all duration-500 ease-in-out`,
|
||||
isSearching && hasValue ? 'text-blue-400' : 'text-gray-400',
|
||||
)}
|
||||
/>
|
||||
|
|
@ -37,31 +36,17 @@ const AnimatedSearchInput = ({
|
|||
value={value}
|
||||
onChange={onChange}
|
||||
placeholder={placeholder}
|
||||
className={`
|
||||
peer relative z-20 w-full rounded-lg bg-surface-secondary px-10
|
||||
py-2 outline-none ring-0 backdrop-blur-sm transition-all
|
||||
duration-500 ease-in-out placeholder:text-gray-400
|
||||
focus:outline-none focus:ring-0
|
||||
`}
|
||||
className={`peer relative z-20 w-full rounded-lg bg-surface-secondary px-10 py-2 outline-none ring-0 backdrop-blur-sm transition-all duration-500 ease-in-out placeholder:text-gray-400 focus:outline-none focus:ring-0`}
|
||||
/>
|
||||
|
||||
{/* Gradient overlay */}
|
||||
<div
|
||||
className={`
|
||||
pointer-events-none absolute inset-0 z-20 rounded-lg
|
||||
bg-gradient-to-r from-blue-500/20 via-purple-500/20 to-blue-500/20
|
||||
transition-all duration-500 ease-in-out
|
||||
${isSearching && hasValue ? 'opacity-100 blur-sm' : 'opacity-0 blur-none'}
|
||||
`}
|
||||
className={`pointer-events-none absolute inset-0 z-20 rounded-lg bg-gradient-to-r from-blue-500/20 via-purple-500/20 to-blue-500/20 transition-all duration-500 ease-in-out ${isSearching && hasValue ? 'opacity-100 blur-sm' : 'opacity-0 blur-none'} `}
|
||||
/>
|
||||
|
||||
{/* Animated loading indicator */}
|
||||
<div
|
||||
className={`
|
||||
absolute right-3 top-1/2 z-20 -translate-y-1/2
|
||||
transition-all duration-500 ease-in-out
|
||||
${isSearching && hasValue ? 'scale-100 opacity-100' : 'scale-0 opacity-0'}
|
||||
`}
|
||||
className={`absolute right-3 top-1/2 z-20 -translate-y-1/2 transition-all duration-500 ease-in-out ${isSearching && hasValue ? 'scale-100 opacity-100' : 'scale-0 opacity-0'} `}
|
||||
>
|
||||
<div className="relative h-2 w-2">
|
||||
<div className="absolute inset-0 animate-ping rounded-full bg-blue-500/60" />
|
||||
|
|
@ -73,36 +58,19 @@ const AnimatedSearchInput = ({
|
|||
|
||||
{/* Outer glow effect */}
|
||||
<div
|
||||
className={`
|
||||
absolute -inset-8 -z-10
|
||||
transition-all duration-700 ease-in-out
|
||||
${isSearching && hasValue ? 'scale-105 opacity-100' : 'scale-100 opacity-0'}
|
||||
`}
|
||||
className={`absolute -inset-8 -z-10 transition-all duration-700 ease-in-out ${isSearching && hasValue ? 'scale-105 opacity-100' : 'scale-100 opacity-0'} `}
|
||||
>
|
||||
<div className="absolute inset-0">
|
||||
<div
|
||||
className={`
|
||||
bg-gradient-radial absolute inset-0 from-blue-500/10 to-transparent
|
||||
transition-opacity duration-700 ease-in-out
|
||||
${isSearching && hasValue ? 'animate-pulse-slow opacity-100' : 'opacity-0'}
|
||||
`}
|
||||
className={`bg-gradient-radial absolute inset-0 from-blue-500/10 to-transparent transition-opacity duration-700 ease-in-out ${isSearching && hasValue ? 'animate-pulse-slow opacity-100' : 'opacity-0'} `}
|
||||
/>
|
||||
<div
|
||||
className={`
|
||||
absolute inset-0 bg-gradient-to-r from-purple-500/5 via-blue-500/5 to-purple-500/5
|
||||
blur-xl transition-all duration-700 ease-in-out
|
||||
${isSearching && hasValue ? 'animate-gradient-x opacity-100' : 'opacity-0'}
|
||||
`}
|
||||
className={`absolute inset-0 bg-gradient-to-r from-purple-500/5 via-blue-500/5 to-purple-500/5 blur-xl transition-all duration-700 ease-in-out ${isSearching && hasValue ? 'animate-gradient-x opacity-100' : 'opacity-0'} `}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`
|
||||
absolute inset-0 -z-20 scale-100 bg-gradient-to-r from-blue-500/10
|
||||
via-purple-500/10 to-blue-500/10 opacity-0 blur-xl
|
||||
transition-all duration-500 ease-in-out
|
||||
peer-focus:scale-105 peer-focus:opacity-100
|
||||
`}
|
||||
className={`absolute inset-0 -z-20 scale-100 bg-gradient-to-r from-blue-500/10 via-purple-500/10 to-blue-500/10 opacity-0 blur-xl transition-all duration-500 ease-in-out peer-focus:scale-105 peer-focus:opacity-100`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react';
|
||||
import { Slot } from '@radix-ui/react-slot';
|
||||
import { ChevronRight, MoreHorizontal } from 'lucide-react';
|
||||
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
|
||||
const Breadcrumb = React.forwardRef<
|
||||
|
|
@ -17,7 +17,7 @@ const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWi
|
|||
<ol
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'text-muted-foreground flex flex-wrap items-center gap-1.5 break-words text-sm sm:gap-2.5',
|
||||
'flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -44,7 +44,7 @@ const BreadcrumbLink = React.forwardRef<
|
|||
return (
|
||||
<Comp
|
||||
ref={ref}
|
||||
className={cn('hover:text-foreground transition-colors', className)}
|
||||
className={cn('transition-colors hover:text-foreground', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
|
@ -58,7 +58,7 @@ const BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentPropsWit
|
|||
role="link"
|
||||
aria-disabled="true"
|
||||
aria-current="page"
|
||||
className={cn('text-foreground font-normal', className)}
|
||||
className={cn('font-normal text-foreground', className)}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
|
|
@ -77,18 +77,22 @@ const BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentP
|
|||
);
|
||||
BreadcrumbSeparator.displayName = 'BreadcrumbSeparator';
|
||||
|
||||
const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<'span'>) => (
|
||||
<span
|
||||
role="presentation"
|
||||
aria-hidden="true"
|
||||
className={cn('flex h-9 w-9 items-center justify-center', className)}
|
||||
{...props}
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">More</span>
|
||||
</span>
|
||||
);
|
||||
BreadcrumbEllipsis.displayName = 'BreadcrumbElipssis';
|
||||
const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<'span'>) => {
|
||||
const localize = useLocalize();
|
||||
return (
|
||||
<span
|
||||
role="presentation"
|
||||
aria-hidden="true"
|
||||
className={cn('flex h-9 w-9 items-center justify-center', className)}
|
||||
{...props}
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">{localize('com_ui_more')}</span>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
BreadcrumbEllipsis.displayName = 'BreadcrumbEllipsis';
|
||||
|
||||
export {
|
||||
Breadcrumb,
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ export default function ComboboxComponent({
|
|||
isCollapsed
|
||||
? 'flex h-9 w-9 shrink-0 items-center justify-center p-0 [&>span]:w-auto [&>svg]:hidden'
|
||||
: '',
|
||||
'bg-white text-black hover:bg-gray-50 focus-visible:ring-2 focus-visible:ring-gray-500 dark:bg-gray-850 dark:text-white ',
|
||||
'bg-white text-black hover:bg-gray-50 focus-visible:ring-2 focus-visible:ring-gray-500 dark:bg-gray-850 dark:text-white',
|
||||
)}
|
||||
>
|
||||
<SelectValue placeholder={selectPlaceholder}>
|
||||
|
|
@ -93,7 +93,7 @@ export default function ComboboxComponent({
|
|||
style={{ userSelect: 'none' }}
|
||||
>
|
||||
{selectedValue
|
||||
? displayValue ?? selectedValue
|
||||
? (displayValue ?? selectedValue)
|
||||
: selectPlaceholder && selectPlaceholder}
|
||||
</span>
|
||||
</SelectValue>
|
||||
|
|
@ -140,7 +140,7 @@ export default function ComboboxComponent({
|
|||
<RadixSelect.Item key={value} value={`${value ?? ''}`} asChild>
|
||||
<ComboboxItem
|
||||
className={cn(
|
||||
'focus:bg-accent focus:text-accent-foreground relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
'relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
'rounded-lg hover:bg-gray-100/50 hover:bg-gray-50 dark:text-white dark:hover:bg-gray-600',
|
||||
)}
|
||||
/** Hacky fix for radix-ui Android issue: https://github.com/radix-ui/primitives/issues/1658 */
|
||||
|
|
@ -155,8 +155,8 @@ export default function ComboboxComponent({
|
|||
</RadixSelect.ItemIndicator>
|
||||
</span>
|
||||
<RadixSelect.ItemText>
|
||||
<div className="[&_svg]:text-foreground flex items-center justify-center gap-3 dark:text-white [&_svg]:h-4 [&_svg]:w-4 [&_svg]:shrink-0">
|
||||
<div className="assistant-item overflow-hidden rounded-full ">
|
||||
<div className="flex items-center justify-center gap-3 dark:text-white [&_svg]:h-4 [&_svg]:w-4 [&_svg]:shrink-0 [&_svg]:text-foreground">
|
||||
<div className="assistant-item overflow-hidden rounded-full">
|
||||
{icon && icon}
|
||||
</div>
|
||||
{label}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export function DataTableColumnHeader<TData, TValue>({
|
|||
<div className={cn('flex items-center space-x-2', className)}>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="sm" className="data-[state=open]:bg-accent -ml-3 h-8">
|
||||
<Button variant="ghost" size="sm" className="-ml-3 h-8 data-[state=open]:bg-accent">
|
||||
<span>{title}</span>
|
||||
{column.getIsSorted() === 'desc' ? (
|
||||
<ArrowDownIcon className="ml-2 h-4 w-4" />
|
||||
|
|
@ -42,16 +42,16 @@ export function DataTableColumnHeader<TData, TValue>({
|
|||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start" className="z-[1001]">
|
||||
<DropdownMenuItem onClick={() => column.toggleSorting(false)}>
|
||||
<ArrowUpIcon className="text-muted-foreground/70 mr-2 h-3.5 w-3.5" />
|
||||
<ArrowUpIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||||
Asc
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => column.toggleSorting(true)}>
|
||||
<ArrowDownIcon className="text-muted-foreground/70 mr-2 h-3.5 w-3.5" />
|
||||
<ArrowDownIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||||
Desc
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={() => column.toggleVisibility(false)}>
|
||||
<EyeNoneIcon className="text-muted-foreground/70 mr-2 h-3.5 w-3.5" />
|
||||
<EyeNoneIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
|
||||
Hide
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ const Dropdown: FC<DropdownProps> = ({
|
|||
typeof option === 'string' ? option : option?.value;
|
||||
|
||||
const getDisplay = (option?: string | Option) =>
|
||||
typeof option === 'string' ? option : option?.label ?? option?.value;
|
||||
typeof option === 'string' ? option : (option?.label ?? option?.value);
|
||||
|
||||
const isEqual = (a: string | Option, b: string | Option): boolean => getValue(a) === getValue(b);
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ const InputWithDropdown = React.forwardRef<HTMLInputElement, InputWithDropdownPr
|
|||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="text-tertiary hover:text-secondary absolute inset-y-0 right-0 flex items-center rounded-md px-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring-primary"
|
||||
className="text-tertiary absolute inset-y-0 right-0 flex items-center rounded-md px-2 hover:text-secondary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring-primary"
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
aria-label={isOpen ? 'Close dropdown' : 'Open dropdown'}
|
||||
>
|
||||
|
|
@ -127,7 +127,7 @@ const InputWithDropdown = React.forwardRef<HTMLInputElement, InputWithDropdownPr
|
|||
'cursor-pointer rounded-md px-3 py-2',
|
||||
'focus:bg-surface-tertiary focus:outline-none focus:ring-1 focus:ring-inset focus:ring-ring-primary',
|
||||
index === highlightedIndex
|
||||
? 'text-primary bg-surface-active'
|
||||
? 'bg-surface-active text-primary'
|
||||
: 'text-secondary hover:bg-surface-tertiary',
|
||||
)}
|
||||
onClick={() => handleSelect(option)}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export default function MultiSearch({
|
|||
<button
|
||||
className={cn(
|
||||
'relative flex h-5 w-5 items-center justify-end rounded-md text-text-secondary-alt',
|
||||
value?.length ?? 0 ? 'cursor-pointer opacity-100' : 'hidden',
|
||||
(value?.length ?? 0) ? 'cursor-pointer opacity-100' : 'hidden',
|
||||
)}
|
||||
aria-label={'Clear search'}
|
||||
onClick={clearSearch}
|
||||
|
|
@ -63,7 +63,7 @@ export default function MultiSearch({
|
|||
aria-hidden={'true'}
|
||||
className={cn(
|
||||
'text-text-secondary-alt',
|
||||
value?.length ?? 0 ? 'cursor-pointer opacity-100' : 'opacity-0',
|
||||
(value?.length ?? 0) ? 'cursor-pointer opacity-100' : 'opacity-0',
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ function MultiSelectDropDown({
|
|||
viewBox="0 0 24 24"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="h-4 w-4 text-gray-400"
|
||||
className="h-4 w-4 text-gray-400"
|
||||
height="1em"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
|
|||
|
|
@ -54,14 +54,14 @@ function MultiSelectPop({
|
|||
<button
|
||||
data-testid="select-dropdown-button"
|
||||
className={cn(
|
||||
'relative flex flex-col rounded-md border border-black/10 bg-white py-2 pl-3 pr-10 text-left focus:outline-none focus:ring-0 focus:ring-offset-0 dark:border-gray-700 dark:bg-gray-800 dark:bg-gray-800 sm:text-sm',
|
||||
'relative flex flex-col rounded-md border border-black/10 bg-white py-2 pl-3 pr-10 text-left focus:outline-none focus:ring-0 focus:ring-offset-0 dark:border-gray-700 dark:bg-gray-800 sm:text-sm',
|
||||
'pointer-cursor font-normal',
|
||||
'hover:bg-gray-50 radix-state-open:bg-gray-50 dark:hover:bg-gray-700 dark:radix-state-open:bg-gray-700',
|
||||
)}
|
||||
>
|
||||
{' '}
|
||||
{showLabel && (
|
||||
<label className="block text-xs text-gray-700 dark:text-gray-500 ">{title}</label>
|
||||
<label className="block text-xs text-gray-700 dark:text-gray-500">{title}</label>
|
||||
)}
|
||||
<span className="inline-flex" id={excludeIds[2]}>
|
||||
<span
|
||||
|
|
@ -73,7 +73,7 @@ function MultiSelectPop({
|
|||
{/* {!showLabel && title.length > 0 && (
|
||||
<span className="text-xs text-gray-700 dark:text-gray-500">{title}:</span>
|
||||
)} */}
|
||||
<span className="flex items-center gap-1 ">
|
||||
<span className="flex items-center gap-1">
|
||||
<div className="flex gap-1">
|
||||
{value.length === 0 && 'None selected'}
|
||||
{value.map((v, i) => (
|
||||
|
|
@ -98,7 +98,7 @@ function MultiSelectPop({
|
|||
viewBox="0 0 24 24"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="h-4 w-4 text-gray-400"
|
||||
className="h-4 w-4 text-gray-400"
|
||||
height="1em"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export default function Prompt({ title, prompt }: { title: string; prompt: strin
|
|||
return (
|
||||
<div
|
||||
// onclick="selectPromptTemplate(0)"
|
||||
className="flex w-full flex-col gap-2 rounded-md bg-gray-50 p-4 text-left hover:bg-gray-200 dark:bg-white/5 "
|
||||
className="flex w-full flex-col gap-2 rounded-md bg-gray-50 p-4 text-left hover:bg-gray-200 dark:bg-white/5"
|
||||
>
|
||||
<h2 className="m-auto flex items-center gap-3 text-lg font-normal md:flex-col md:gap-2">
|
||||
{title}
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@ const ResizableHandle = ({
|
|||
}) => (
|
||||
<ResizablePrimitive.PanelResizeHandle
|
||||
className={cn(
|
||||
'bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
|
||||
'relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{withHandle && (
|
||||
<div className="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-sm border">
|
||||
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
|
||||
<GripVertical className="h-2.5 w-2.5" />
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -46,13 +46,13 @@ const ResizableHandleAlt = ({
|
|||
}) => (
|
||||
<ResizablePrimitive.PanelResizeHandle
|
||||
className={cn(
|
||||
'bg-border focus-visible:ring-ring group relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
|
||||
'group relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{withHandle && (
|
||||
<div className="bg-border invisible z-10 flex h-4 w-3 items-center justify-center rounded-sm border group-hover:visible group-active:visible">
|
||||
<div className="invisible z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border group-hover:visible group-active:visible">
|
||||
<GripVertical className="h-2.5 w-2.5" />
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -5,22 +5,22 @@ import { cn } from '~/utils';
|
|||
const Slider = React.forwardRef<
|
||||
React.ElementRef<typeof SliderPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> & { onDoubleClick?: () => void }
|
||||
>(({ className, onDoubleClick, ...props }, ref) => (
|
||||
<SliderPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'relative flex w-full cursor-pointer touch-none select-none items-center',
|
||||
className,
|
||||
)}
|
||||
onDoubleClick={onDoubleClick}
|
||||
{...props}
|
||||
>
|
||||
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary">
|
||||
<SliderPrimitive.Range className="absolute h-full bg-primary" />
|
||||
</SliderPrimitive.Track>
|
||||
<SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" />
|
||||
</SliderPrimitive.Root>
|
||||
));
|
||||
>(({ className, onDoubleClick, ...props }, ref) => (
|
||||
<SliderPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'relative flex w-full cursor-pointer touch-none select-none items-center',
|
||||
className,
|
||||
)}
|
||||
onDoubleClick={onDoubleClick}
|
||||
{...props}
|
||||
>
|
||||
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary">
|
||||
<SliderPrimitive.Range className="absolute h-full bg-primary" />
|
||||
</SliderPrimitive.Track>
|
||||
<SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" />
|
||||
</SliderPrimitive.Root>
|
||||
));
|
||||
Slider.displayName = SliderPrimitive.Root.displayName;
|
||||
|
||||
export { Slider };
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ const TableFooter = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<tfoot
|
||||
ref={ref}
|
||||
className={cn('bg-muted/50 border-t font-medium [&>tr]:last:border-b-0', className)}
|
||||
className={cn('border-t bg-muted/50 font-medium [&>tr]:last:border-b-0', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
|
@ -43,7 +43,7 @@ const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTML
|
|||
<tr
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'hover:bg-muted/50 data-[state=selected]:bg-muted border-b border-border-light transition-colors',
|
||||
'border-b border-border-light transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -59,7 +59,7 @@ const TableHead = React.forwardRef<
|
|||
<th
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'text-muted-foreground h-12 px-4 text-left align-middle font-medium [&:has([role=checkbox])]:pr-0',
|
||||
'h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
@ -83,7 +83,7 @@ const TableCaption = React.forwardRef<
|
|||
HTMLTableCaptionElement,
|
||||
React.HTMLAttributes<HTMLTableCaptionElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<caption ref={ref} className={cn('text-muted-foreground mt-4 text-sm', className)} {...props} />
|
||||
<caption ref={ref} className={cn('mt-4 text-sm text-muted-foreground', className)} {...props} />
|
||||
));
|
||||
TableCaption.displayName = 'TableCaption';
|
||||
|
||||
|
|
|
|||
|
|
@ -30,17 +30,17 @@ const TagPrimitiveRoot = React.forwardRef<HTMLDivElement, TagProps>(
|
|||
{CancelButton
|
||||
? CancelButton
|
||||
: onRemove && (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onRemove(e);
|
||||
}}
|
||||
className="rounded-full bg-green-600/50"
|
||||
aria-label={`Remove ${label}`}
|
||||
>
|
||||
<X className="m-[1.5px] p-1" />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onRemove(e);
|
||||
}}
|
||||
className="rounded-full bg-green-600/50"
|
||||
aria-label={`Remove ${label}`}
|
||||
>
|
||||
<X className="m-[1.5px] p-1" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ const TermsAndConditionsModal = ({
|
|||
main={
|
||||
<section
|
||||
// Motivation: This is a dialog, so its content should be focusable
|
||||
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
||||
|
||||
tabIndex={0}
|
||||
className="max-h-[60vh] overflow-y-auto p-4"
|
||||
aria-label={localize('com_ui_terms_and_conditions')}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export default function useAddedHelpers({
|
|||
store.messagesSiblingIdxFamily(latestMessage?.parentMessageId ?? null),
|
||||
);
|
||||
|
||||
const queryParam = paramId === 'new' ? paramId : conversation?.conversationId ?? paramId ?? '';
|
||||
const queryParam = paramId === 'new' ? paramId : (conversation?.conversationId ?? paramId ?? '');
|
||||
|
||||
const setMessages = useCallback(
|
||||
(messages: TMessage[]) => {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ function useDebouncedInput<T = unknown>({
|
|||
typeof e !== 'object'
|
||||
? e
|
||||
: ((e as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>).target
|
||||
.value as unknown as T);
|
||||
.value as unknown as T);
|
||||
if (numeric === true) {
|
||||
newValue = Number(newValue) as unknown as T;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,10 +48,11 @@ export default function useExportConversation({
|
|||
const { conversationId: paramId } = useParams();
|
||||
|
||||
const getMessageTree = useCallback(() => {
|
||||
const queryParam = paramId === 'new' ? paramId : conversation?.conversationId ?? paramId ?? '';
|
||||
const queryParam =
|
||||
paramId === 'new' ? paramId : (conversation?.conversationId ?? paramId ?? '');
|
||||
const messages = queryClient.getQueryData<TMessage[]>([QueryKeys.messages, queryParam]) ?? [];
|
||||
const dataTree = buildTree({ messages });
|
||||
return dataTree?.length === 0 ? null : dataTree ?? null;
|
||||
return dataTree?.length === 0 ? null : (dataTree ?? null);
|
||||
}, [paramId, conversation?.conversationId, queryClient]);
|
||||
|
||||
const getMessageText = (message: TMessage | undefined, format = 'text') => {
|
||||
|
|
|
|||
|
|
@ -113,11 +113,11 @@ export const useEndpoints = ({
|
|||
hasModels,
|
||||
icon: Icon
|
||||
? React.createElement(Icon, {
|
||||
size: 20,
|
||||
className: 'text-text-primary shrink-0 icon-md',
|
||||
iconURL: endpointIconURL,
|
||||
endpoint: ep,
|
||||
})
|
||||
size: 20,
|
||||
className: 'text-text-primary shrink-0 icon-md',
|
||||
iconURL: endpointIconURL,
|
||||
endpoint: ep,
|
||||
})
|
||||
: null,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,8 @@ export default function useContentHandler({ setMessages, getMessages }: TUseCont
|
|||
|
||||
const _messages = getMessages();
|
||||
const messages =
|
||||
_messages
|
||||
?.filter((m) => m.messageId !== messageId)
|
||||
.map((msg) => ({ ...msg, thread_id })) ?? [];
|
||||
_messages?.filter((m) => m.messageId !== messageId).map((msg) => ({ ...msg, thread_id })) ??
|
||||
[];
|
||||
const userMessage = messages[messages.length - 1] as TMessage | undefined;
|
||||
|
||||
const { initialResponse } = submission;
|
||||
|
|
|
|||
|
|
@ -46,4 +46,4 @@ describe('i18next translation tests', () => {
|
|||
i18n.changeLanguage('fr');
|
||||
expect(i18n.t('com_endpoint_default_with_num', { 0: 'Marie' })).toBe('par défaut : Marie');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -948,5 +948,8 @@
|
|||
"com_ui_yes": "Yes",
|
||||
"com_ui_zoom": "Zoom",
|
||||
"com_user_message": "You",
|
||||
"com_warning_resubmit_unsupported": "Resubmitting the AI message is not supported for this endpoint."
|
||||
"com_warning_resubmit_unsupported": "Resubmitting the AI message is not supported for this endpoint.",
|
||||
"com_ui_add_anything": "Add anything",
|
||||
"com_ui_add_anything_description": "Drop any file here to add it to the conversation",
|
||||
"com_ui_more": "More"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-nocheck
|
||||
import { EModelEndpoint, ImageDetail } from 'librechat-data-provider';
|
||||
import type { ConversationData } from 'librechat-data-provider';
|
||||
|
|
@ -98,7 +97,7 @@ export const convoData: ConversationData = {
|
|||
promptPrefix: null,
|
||||
resendFiles: false,
|
||||
temperature: 1,
|
||||
title: 'Write Einstein\'s Famous Equation in LaTeX',
|
||||
title: "Write Einstein's Famous Equation in LaTeX",
|
||||
top_p: 1,
|
||||
updatedAt,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import { processLaTeX, preprocessLaTeX } from './latex';
|
||||
|
||||
describe('processLaTeX', () => {
|
||||
|
|
|
|||
|
|
@ -40,4 +40,4 @@ jest.mock('react-i18next', () => {
|
|||
init: jest.fn(),
|
||||
},
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue