feat: common components

This commit is contained in:
jialin
2024-05-17 09:23:13 +08:00
parent dcaa5a7baa
commit fa522fb89e
13 changed files with 647 additions and 168 deletions
+27
View File
@@ -0,0 +1,27 @@
:local(.seal_custom_popover) {
position: relative;
padding-top: var(--ant-popover-inner-padding);
border-radius: var(--ant-border-radius-lg);
background-color: var(--color-white-1);
box-shadow: var(--ant-box-shadow-secondary);
overflow: hidden;
padding-top: 80px;
:global(.ant-popover-inner) {
box-shadow: none;
padding-top: 0;
}
:global(.ant-popover-content) {
position: static;
}
:global(.ant-popover-title) {
position: absolute;
top: 0;
padding-block: var(--ant-popover-inner-padding)
var(--ant-popover-title-margin-bottom);
margin-bottom: 0;
background: #fff;
padding-left: var(--ant-popover-inner-padding);
left: 0;
width: 100%;
}
}
+23
View File
@@ -0,0 +1,23 @@
import { Popover } from 'antd';
import type { PopoverProps } from 'antd/lib/popover';
import classNames from 'classnames';
import styles from './index.less';
const SealPopover: React.FC<PopoverProps> = (props) => {
const { className, children, style, ...restProps } = props;
return (
<div className="popover-wrapper">
<Popover
{...restProps}
style={{ ...style }}
data-maxHeight="300px"
overlayClassName={classNames(className, styles.seal_custom_popover)}
>
{children}
</Popover>
</div>
);
};
export default SealPopover;
@@ -0,0 +1,49 @@
:local(.wrapper) {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
height: 54px;
border-width: var(--ant-line-width);
border-style: var(--ant-line-type);
border-color: var(--ant-color-border);
border-radius: 28px;
padding-inline: 12px;
padding-block: 20px 0;
&:hover {
border-color: var(--ant-input-hover-border-color);
transition: all 0.2s ease;
}
&:focus-within {
border-color: var(--ant-input-active-border-color);
box-shadow: var(--ant-input-active-shadow);
outline: 0;
background-color: var(--ant-input-active-bg);
}
.label {
position: absolute;
left: 24px;
color: rgba(0, 0, 0, 0.45);
font-size: var(--font-size-base);
line-height: 1;
pointer-events: all;
z-index: 5;
&.isfoucs-has-value {
top: 8px;
transition: all 0.2s var(--seal-transition-func);
}
&.blur-no-value {
top: 21px;
transition: all 0.2s var(--seal-transition-func);
}
}
:global(.ant-input) {
display: flex;
align-items: center;
border: none;
box-shadow: none;
padding-block: 5px;
padding-inline: 12px;
height: 32px;
}
}
@@ -1,14 +1,34 @@
import classNames from 'classnames';
import wrapperStyle from './wrapper.less';
interface WrapperProps {
children: React.ReactNode;
label: string;
isFocus: boolean;
onClick?: () => void;
}
const Wrapper: React.FC<WrapperProps>= ({ children }) => {
const Wrapper: React.FC<WrapperProps> = ({
children,
label,
isFocus,
onClick
}) => {
return (
<div>
<div className={wrapperStyle.wrapper} onClick={onClick}>
<label
onClick={onClick}
className={classNames(
wrapperStyle['label'],
isFocus
? wrapperStyle['isfoucs-has-value']
: wrapperStyle['blur-no-value']
)}
>
{label}
</label>
{children}
</div>
);
}
};
export default Wrapper;
export default Wrapper;
+58 -10
View File
@@ -1,24 +1,72 @@
import { Input } from 'antd';
import type { InputProps } from 'antd';
import { Input } from 'antd';
import { useEffect, useRef, useState } from 'react';
import Wrapper from './components/wrapper';
import { SealFormItemProps } from './types';
import { SealFormItemProps } from './types';
const TextArea: React.FC<InputProps & SealFormItemProps> = (props) => {
console.log('textarea=========', 121);
return (
<Wrapper label="input">
<Input.TextArea placeholder='send your message' autoSize={{minRows: 1,maxRows: 6}} size="large" variant='borderless'></Input.TextArea>
<Input.TextArea
placeholder="send your message"
autoSize={{ minRows: 1, maxRows: 6 }}
size="large"
variant="borderless"
></Input.TextArea>
</Wrapper>
);
}
};
const SealInput: React.FC<InputProps & SealFormItemProps> = (props) => {
const {label, ...rest} = props;
const { label, placeholder, ...rest } = props;
const [isFocus, setIsFocus] = useState(false);
const inputRef = useRef<any>(null);
useEffect(() => {
if (props.value) {
setIsFocus(true);
}
}, [props.value]);
const handleClickWrapper = () => {
if (!props.disabled && !isFocus) {
inputRef.current?.focus?.();
setIsFocus(true);
}
};
const handleChange = (e: any) => {
props.onChange?.(e);
};
const handleOnFocus = (e: any) => {
setIsFocus(true);
props.onFocus?.(e);
};
const handleOnBlur = (e: any) => {
if (!inputRef.current?.input?.value) {
setIsFocus(false);
props.onBlur?.(e);
}
};
return (
<Wrapper label="input">
<Input {...rest} placeholder='send your message'></Input>
<Wrapper
label={label || (placeholder as string)}
isFocus={isFocus}
onClick={handleClickWrapper}
>
<Input
{...rest}
ref={inputRef}
onFocus={handleOnFocus}
onBlur={handleOnBlur}
onChange={(e) => handleChange(e)}
></Input>
</Wrapper>
);
}
};
export default {TextArea,Input: SealInput};
export default { TextArea, Input: SealInput };
+6
View File
@@ -1 +1,7 @@
export const DEFAULT_NAME = 'Umi Max';
export const INPUT_WIDTH = {
default: 500,
large: 600,
small: 400
};
+25 -12
View File
@@ -1,4 +1,4 @@
html{
html {
--color-fill-1: rgba(0, 0, 0, 0.04);
--color-fill-2: #fff;
--color-fill-3: #f3f6fa;
@@ -10,23 +10,37 @@ html{
--color-text-1: #1d2129;
--color-bg-light-1: #f0fff6;
--font-size-base: 12px;
--ant-input-active-shadow: 0 0 0 2px rgba(5, 255, 105, 0.06);
--ant-input-active-border-color: #2fbf85;
--ant-color-fill-secondary: rgba(0, 0, 0, 0.06);
// --color-text-1: #000;
--seal-transition-func: cubic-bezier(0, 0, 1, 1);
// ======== input ============
--ant-input-active-shadow: 0 0 0 2px rgba(5, 255, 105, 0.06);
--ant-input-active-border-color: #2fbf85;
--ant-input-hover-border-color: #54cc98;
.css-var-rf {
--ant-font-size: var(--font-size-base);
--ant-font-size: var(--font-size-base);
}
.css-var-r0 {
// --ant-control-height: 36px;
--ant-font-size-sm: var(--font-size-base);
--ant-font-size-lg: var(--font-size-base);
--ant-font-size-sm: var(--font-size-base);
--ant-font-size-lg: var(--font-size-base);
--ant-font-size-xl: 20px;
--ant-padding-sm: 14px;
&.ant-popover {
--ant-popover-inner-padding: 26px;
--ant-popover-title-margin-bottom: 22px;
}
&.ant-btn {
--ant-button-content-font-size-lg: 13px;
--ant-button-content-font-size: 13px;
--ant-button-content-font-size-sm: 13px;
}
}
.css-var-rf.ant-menu-css-var {
--ant-menu-item-height: 46px;
--ant-menu-item-selected-bg: var(--color-white-1);
@@ -39,12 +53,12 @@ html{
.css-var-r0.ant-input-css-var {
--ant-input-input-font-size: var(--font-size-base);
--ant-input-input-font-size-lg: var(--font-size-base);
--ant-input-input-font-size-sm:var(--font-size-base);
--ant-input-input-font-size-sm: var(--font-size-base);
}
.css-var-r0.ant-select-css-var {
--ant-select-option-active-bg: var(--color-fill-1);
--ant-select-option-font-size: var(--font-size-base);
}
}
}
body * {
font-weight: var(--font-weight-normal);
@@ -59,7 +73,6 @@ body * {
}
.ant-layout {
min-height: 100vh;
}
.ant-pro-layout-container {
background-color: var(--color-fill-2);
@@ -84,4 +97,4 @@ body * {
}
// ======== menu style end ============
@import url('src/assets/styles/menu.less');
@import url('src/assets/styles/menu.less');
@@ -1,13 +1,142 @@
import { Form } from 'antd';
import { useState } from 'react';
import SealInput from '@/components/seal-form/seal-input';
import { INPUT_WIDTH } from '@/constants';
import { Button, Form, Space } from 'antd';
type ParamsSettingsProps = {
seed?: number;
stopSequence?: number;
temperature?: number;
topK?: number;
topP?: number;
repeatPenalty?: number;
repeatLastN?: number;
tfsZ?: number;
contextLength?: number;
maxTokens?: number;
};
const ParamsSettings: React.FC = () => {
const [params, setParams] = useState({
name: 'jack',
age: 18,
});
const initialValues = {
seed: 1,
stopSequence: 1,
temperature: 1,
topK: 1,
topP: 1,
repeatPenalty: 1,
repeatLastN: 1,
tfsZ: 1,
contextLength: 256,
maxTokens: 256
};
const [form] = Form.useForm();
return <Form></Form>;
const handleOnFinish = (values: any) => {
console.log('handleOnFinish', values);
};
const handleOnFinishFailed = (errorInfo: any) => {
console.log('handleOnFinishFailed', errorInfo);
};
return (
<Form
name="modelparams"
form={form}
onFinish={handleOnFinish}
onFinishFailed={handleOnFinishFailed}
>
<Form.Item<ParamsSettingsProps> name="seed" rules={[{ required: true }]}>
<SealInput.Input
label="Seed"
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item>
<Form.Item<ParamsSettingsProps>
name="stopSequence"
rules={[{ required: true }]}
>
<SealInput.Input
label="Stop Sequence"
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item>
<Form.Item<ParamsSettingsProps>
name="temperature"
rules={[{ required: true }]}
>
<SealInput.Input
label="Temperature"
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item>
<Form.Item<ParamsSettingsProps> name="topK" rules={[{ required: true }]}>
<SealInput.Input
label="TopK"
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item>
<Form.Item<ParamsSettingsProps> name="topP" rules={[{ required: true }]}>
<SealInput.Input
label="TopP"
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item>
<Form.Item<ParamsSettingsProps>
name="repeatPenalty"
rules={[{ required: true }]}
>
<SealInput.Input
label="Repeat Penalty"
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item>
<Form.Item<ParamsSettingsProps>
name="repeatLastN"
rules={[{ required: true }]}
>
<SealInput.Input
label="Repeat Last N"
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item>
<Form.Item<ParamsSettingsProps> name="tfsZ" rules={[{ required: true }]}>
<SealInput.Input
label="TFSZ"
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item>
<Form.Item<ParamsSettingsProps>
name="contextLength"
rules={[{ required: true }]}
>
<SealInput.Input
label="Context Length"
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item>
<Form.Item<ParamsSettingsProps>
name="maxTokens"
rules={[{ required: true }]}
>
<SealInput.Input
label="Max Tokens"
style={{ width: INPUT_WIDTH.default }}
></SealInput.Input>
</Form.Item>
<Form.Item noStyle>
<Space
size={20}
align="end"
style={{ width: '100%', display: 'flex', justifyContent: 'end' }}
>
<Button>Cancel</Button>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Space>
</Form.Item>
</Form>
);
};
export default ParamsSettings;
+14 -5
View File
@@ -1,10 +1,11 @@
import SealInput from '@/components/seal-form/seal-input';
import SealPopover from '@/components/popover';
import { ControlOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { Button, Popover, Select, Space } from 'antd';
import { Button, Select, Space } from 'antd';
import { useEffect, useState } from 'react';
import ChatContent from './components/chatContent';
import MessageInput from './components/messageInput';
import ParamsSettings from './components/params-settings';
const dataList = [
{ value: 'llama3:latest', label: 'llama3:latest' },
@@ -23,6 +24,7 @@ const Playground: React.FC = () => {
const getMessageList = () => {
// fetch message list from server
console.log('getModelList');
setMessageList(['1']);
};
@@ -43,13 +45,21 @@ const Playground: React.FC = () => {
onChange={handleSelectChange}
variant="filled"
></Select>
<Popover content="ssd" title="Title" trigger="click">
<SealPopover
content={<ParamsSettings></ParamsSettings>}
destroyTooltipOnHide={true}
title="Params Settings"
trigger="click"
arrow={false}
overlayInnerStyle={{ maxHeight: '500px', overflow: 'auto' }}
placement="bottomRight"
>
<Button
type="primary"
shape="circle"
icon={<ControlOutlined />}
></Button>
</Popover>
</SealPopover>
</Space>
]}
footer={[<MessageInput />]}
@@ -57,7 +67,6 @@ const Playground: React.FC = () => {
<div style={{ display: 'flex', justifyContent: 'center' }}>
<ChatContent messageList={messageList}></ChatContent>
</div>
<SealInput.Input label="test label"></SealInput.Input>
</PageContainer>
);
};