mirror of
https://github.com/coaidev/coai.git
synced 2025-05-24 07:20:15 +09:00
select scrollable in mobile device
This commit is contained in:
parent
3860ea7785
commit
ace6a1581c
@ -11,33 +11,34 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-alert-dialog": "^1.0.4",
|
||||
"@radix-ui/react-context-menu": "^2.1.4",
|
||||
"@radix-ui/react-dialog": "^1.0.4",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.5",
|
||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||
"@radix-ui/react-context-menu": "^2.1.5",
|
||||
"@radix-ui/react-dialog": "^1.0.5",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-scroll-area": "^1.0.5",
|
||||
"@radix-ui/react-select": "^2.0.0",
|
||||
"@radix-ui/react-separator": "^1.0.3",
|
||||
"@radix-ui/react-slot": "^1.0.2",
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-toast": "^1.1.4",
|
||||
"@radix-ui/react-toast": "^1.1.5",
|
||||
"@radix-ui/react-toggle": "^1.0.3",
|
||||
"@radix-ui/react-tooltip": "^1.0.6",
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"axios": "^1.5.0",
|
||||
"@radix-ui/react-tooltip": "^1.0.7",
|
||||
"@reduxjs/toolkit": "^1.9.7",
|
||||
"axios": "^1.5.1",
|
||||
"chart.js": "^4.4.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"i18next": "^23.4.6",
|
||||
"i18next": "^23.6.0",
|
||||
"localforage": "^1.10.0",
|
||||
"lucide-react": "^0.289.0",
|
||||
"match-sorter": "^6.3.1",
|
||||
"react": "^18.2.0",
|
||||
"react-chartjs-2": "^5.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^13.2.2",
|
||||
"react-i18next": "^13.3.1",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-redux": "^8.1.2",
|
||||
"react-redux": "^8.1.3",
|
||||
"react-router-dom": "^6.17.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"rehype-katex": "^6.0.3",
|
||||
@ -49,25 +50,25 @@
|
||||
"workbox-window": "^7.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.5.9",
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@types/react-syntax-highlighter": "^15.5.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"autoprefixer": "^10.4.15",
|
||||
"eslint": "^8.45.0",
|
||||
"@types/node": "^20.8.9",
|
||||
"@types/react": "^18.2.33",
|
||||
"@types/react-dom": "^18.2.14",
|
||||
"@types/react-syntax-highlighter": "^15.5.9",
|
||||
"@typescript-eslint/eslint-plugin": "^6.9.0",
|
||||
"@typescript-eslint/parser": "^6.9.0",
|
||||
"@vitejs/plugin-react-swc": "^3.4.0",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"eslint": "^8.52.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.3",
|
||||
"less": "^4.2.0",
|
||||
"less-loader": "^11.1.3",
|
||||
"postcss": "^8.4.29",
|
||||
"postcss": "^8.4.31",
|
||||
"prettier": "^3.0.3",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.4.5",
|
||||
"tailwindcss": "^3.3.5",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^4.5.0",
|
||||
"vite-plugin-html": "^3.2.0",
|
||||
"vite-plugin-pwa": "^0.16.4"
|
||||
"vite-plugin-pwa": "^0.16.5"
|
||||
}
|
||||
}
|
||||
|
1525
app/pnpm-lock.yaml
generated
1525
app/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -71,3 +71,8 @@
|
||||
background: rgb(255, 231, 145) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.model-select-group {
|
||||
transform: translateX(-26px) !important;
|
||||
width: calc(100vw - 72px) !important;
|
||||
}
|
||||
|
@ -26,6 +26,10 @@ type SelectGroupProps = {
|
||||
list: SelectItemProps[];
|
||||
onChange?: (select: string) => void;
|
||||
maxElements?: number;
|
||||
className?: string;
|
||||
classNameDesktop?: string;
|
||||
classNameMobile?: string;
|
||||
side?: "left" | "right" | "top" | "bottom";
|
||||
};
|
||||
|
||||
function GroupSelectItem(props: SelectItemProps) {
|
||||
@ -80,7 +84,7 @@ function SelectGroupDesktop(props: SelectGroupProps) {
|
||||
</span>
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectContent className={`${props.className} ${props.classNameDesktop}`}>
|
||||
{hidden.map((select: SelectItemProps, idx: number) => (
|
||||
<SelectItem key={idx} value={select.name}>
|
||||
<GroupSelectItem {...select} />
|
||||
@ -105,7 +109,7 @@ function SelectGroupMobile(props: SelectGroupProps) {
|
||||
<SelectTrigger className="select-group mobile">
|
||||
<SelectValue placeholder={props.current.value} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectContent position={`item-aligned`} side={props.side} className={`${props.className} ${props.classNameMobile}`}>
|
||||
{props.list.map((select: SelectItemProps, idx: number) => (
|
||||
<SelectItem key={idx} value={select.name}>
|
||||
<GroupSelectItem {...select} />
|
||||
|
@ -227,7 +227,7 @@ function ChatWrapper() {
|
||||
</Button>
|
||||
</div>
|
||||
<div className={`input-options`}>
|
||||
<ModelSelector />
|
||||
<ModelSelector side={`bottom`} />
|
||||
</div>
|
||||
<div className={`version`}>
|
||||
<svg className={`app`} onClick={triggerInstallApp} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" strokeWidth="2" stroke="currentColor" fill="none" strokeLinecap="round" strokeLinejoin="round">
|
||||
|
@ -14,7 +14,12 @@ function GetModel(name: string): Model {
|
||||
return supportModels.find((model) => model.id === name) as Model;
|
||||
}
|
||||
|
||||
function ModelSelector() {
|
||||
type ModelSelectorProps = {
|
||||
side?: "left" | "right" | "top" | "bottom";
|
||||
}
|
||||
|
||||
|
||||
function ModelSelector(props: ModelSelectorProps) {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const { toast } = useToast();
|
||||
@ -24,7 +29,8 @@ function ModelSelector() {
|
||||
const subscription = useSelector(isSubscribedSelector);
|
||||
|
||||
useEffect(() => {
|
||||
if (auth && model === "GPT-3.5") dispatch(setModel("GPT-3.5-16k"));
|
||||
if (auth && model === "gpt-3.5-turbo-0613")
|
||||
dispatch(setModel("gpt-3.5-turbo-16k-0613"));
|
||||
}, [auth]);
|
||||
|
||||
modelEvent.bind((target: string) => {
|
||||
@ -54,6 +60,8 @@ function ModelSelector() {
|
||||
current={list.find((item) => item.name === model) as SelectItemProps}
|
||||
list={list}
|
||||
maxElements={6}
|
||||
side={props.side}
|
||||
classNameMobile={`model-select-group`}
|
||||
onChange={(value: string) => {
|
||||
const model = GetModel(value);
|
||||
console.debug(`[model] select model: ${model.name} (id: ${model.id})`);
|
||||
|
51
app/src/components/ui/scroll-area.tsx
Normal file
51
app/src/components/ui/scroll-area.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
import * as React from "react"
|
||||
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
|
||||
|
||||
import { cn } from "./lib/utils"
|
||||
|
||||
const ScrollArea = React.forwardRef<
|
||||
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<ScrollAreaPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn("relative overflow-hidden", className)}
|
||||
{...props}
|
||||
>
|
||||
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
|
||||
{children}
|
||||
</ScrollAreaPrimitive.Viewport>
|
||||
<ScrollBar />
|
||||
<ScrollAreaPrimitive.Corner />
|
||||
</ScrollAreaPrimitive.Root>
|
||||
))
|
||||
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
|
||||
|
||||
const ScrollBar = React.forwardRef<
|
||||
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||
>(({ className, orientation = "vertical", ...props }, ref) => (
|
||||
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
||||
ref={ref}
|
||||
orientation={orientation}
|
||||
className={cn(
|
||||
"flex touch-none select-none transition-colors",
|
||||
orientation === "vertical" &&
|
||||
"h-full w-2.5 border-l border-l-transparent p-[1px]",
|
||||
orientation === "horizontal" &&
|
||||
"h-2.5 flex-col border-t border-t-transparent p-[1px]",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<ScrollAreaPrimitive.ScrollAreaThumb
|
||||
className={cn(
|
||||
"relative rounded-full bg-border",
|
||||
orientation === "vertical" && "flex-1"
|
||||
)}
|
||||
/>
|
||||
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
||||
))
|
||||
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
|
||||
|
||||
export { ScrollArea, ScrollBar }
|
@ -36,6 +36,7 @@ const SelectContent = React.forwardRef<
|
||||
>(({ className, children, position = "popper", ...props }) => (
|
||||
<SelectPrimitive.Portal>
|
||||
<SelectPrimitive.Content
|
||||
avoidCollisions={true}
|
||||
ref={(ref) => {
|
||||
if (!ref) return
|
||||
ref.ontouchend = (e) => {
|
||||
@ -45,14 +46,15 @@ const SelectContent = React.forwardRef<
|
||||
}}
|
||||
className={cn(
|
||||
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
position === "popper" &&
|
||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
||||
position === "popper" ?
|
||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1":
|
||||
"w-[80vw] max-w-[30rem] max-h-[80vh]",
|
||||
className,
|
||||
)}
|
||||
position={position}
|
||||
{...props}
|
||||
>
|
||||
<SelectPrimitive.ScrollUpButton className={`flex items-center justify-center h-[25px] bg-white text-violet11 cursor-default`}>
|
||||
<SelectPrimitive.ScrollUpButton className={`flex items-center justify-center h-[25px] cursor-pointer`}>
|
||||
<ChevronUp />
|
||||
</SelectPrimitive.ScrollUpButton>
|
||||
<SelectPrimitive.Viewport
|
||||
@ -64,7 +66,7 @@ const SelectContent = React.forwardRef<
|
||||
>
|
||||
{children}
|
||||
</SelectPrimitive.Viewport>
|
||||
<SelectPrimitive.ScrollDownButton className={`flex items-center justify-center h-[25px] bg-white text-violet11 cursor-default`}>
|
||||
<SelectPrimitive.ScrollDownButton className={`flex items-center justify-center h-[25px] cursor-pointer`}>
|
||||
<ChevronDown />
|
||||
</SelectPrimitive.ScrollDownButton>
|
||||
</SelectPrimitive.Content>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import axios from "axios";
|
||||
import { Model } from "./conversation/types.ts";
|
||||
|
||||
export const version = "3.5.15";
|
||||
export const version = "3.5.16";
|
||||
export const dev: boolean = window.location.hostname === "localhost";
|
||||
export const deploy: boolean = true;
|
||||
export let rest_api: string = "http://localhost:8094";
|
||||
@ -15,8 +15,8 @@ if (deploy) {
|
||||
export const tokenField = deploy ? "token" : "token-dev";
|
||||
export const supportModels: Model[] = [
|
||||
// openai models
|
||||
{ id: "gpt-3.5-turbo", name: "GPT-3.5", free: true, auth: false },
|
||||
{ id: "gpt-3.5-turbo-16k", name: "GPT-3.5-16k", free: true, auth: true },
|
||||
{ id: "gpt-3.5-turbo-0613", name: "GPT-3.5", free: true, auth: false },
|
||||
{ id: "gpt-3.5-turbo-16k-0613", name: "GPT-3.5-16k", free: true, auth: true },
|
||||
{ id: "gpt-4", name: "GPT-4", free: false, auth: true },
|
||||
{ id: "gpt-4-32k", name: "GPT-4-32k", free: false, auth: true },
|
||||
|
||||
|
@ -147,7 +147,7 @@ function Wrapper({ onSend }: WrapperProps) {
|
||||
</Button>
|
||||
</div>
|
||||
<div className={`model-box`}>
|
||||
<ModelSelector />
|
||||
<ModelSelector side={`bottom`} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
1
app/src/types/ui.d.ts
vendored
Normal file
1
app/src/types/ui.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
declare module '@radix-ui/react-select-area';
|
@ -10,7 +10,7 @@ window.addEventListener("resize", () => {
|
||||
|
||||
|
||||
window.addEventListener('beforeinstallprompt', (e: Event) => {
|
||||
e.preventDefault();
|
||||
// e.preventDefault();
|
||||
event = (e as BeforeInstallPromptEvent);
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user