chore: common components

This commit is contained in:
jialin
2024-05-17 17:12:30 +08:00
parent fa522fb89e
commit c948110153
11 changed files with 681 additions and 108 deletions
@@ -1,4 +1,6 @@
:local(.wrapper) {
@wrapheight: 54px;
@inputheight: 32px;
position: relative;
display: flex;
flex-direction: column;
@@ -10,6 +12,31 @@
border-radius: 28px;
padding-inline: 12px;
padding-block: 20px 0;
&.seal-input-wrapper-disabled {
background-color: var(--ant-color-bg-container-disabled);
cursor: not-allowed;
&:hover {
border-color: var(--ant-color-border);
}
}
&.seal-textarea-wrapper {
height: auto;
padding-bottom: 10px;
padding-right: 10px;
}
&.validate-status-error {
border-width: var(--ant-line-width);
border-style: var(--ant-line-type);
border-color: var(--ant-color-error);
&:hover {
border-color: var(--ant-color-error-border-hover);
}
&:focus-within {
border-color: var(--ant-color-error);
}
}
&:hover {
border-color: var(--ant-input-hover-border-color);
transition: all 0.2s ease;
@@ -37,13 +64,92 @@
transition: all 0.2s var(--seal-transition-func);
}
}
:global(.ant-input) {
// ==================== select ==================
:global(.ant-select) {
display: flex;
align-items: center;
border: none;
box-shadow: none;
height: @inputheight;
}
:global(.ant-select-selector) {
border: none !important;
padding-block: 5px;
padding-inline: 12px;
box-shadow: none !important;
}
:global(.ant-select-selection-item) {
height: @inputheight;
}
:global(
.ant-select-outlined.ant-select-disabled:not(.ant-select-customize-input)
.ant-select-selector
) {
background-color: transparent;
}
// ==================== input ====================
:global(.ant-input),
:global(.ant-input-password) {
display: flex;
align-items: center;
border: none;
box-shadow: none;
padding-block: 5px;
padding-inline: 12px;
height: 32px;
height: @inputheight;
}
:global(.ant-input-number) {
display: flex;
align-items: center;
border: none;
box-shadow: none;
padding: 0;
height: @inputheight;
}
:global(.ant-input-outlined) {
&.seal-textarea {
min-height: 100px !important;
}
}
:global(.ant-input.ant-input-disabled) {
background-color: transparent;
}
:global(input.ant-input-number-input) {
height: @inputheight;
padding-block: 5px;
padding-inline: 12px;
}
:global(.ant-input-group) {
position: static;
}
:global(.ant-input-group-addon) {
inset-inline-start: unset !important;
border-radius: 0 28px 28px 0;
width: 30px;
background-color: transparent;
}
:global(.ant-input-group-addon:hover) {
background-color: transparent !important;
}
:global(.ant-input-group-wrapper-disabled .ant-input-group-addon) {
background-color: transparent;
}
:global(.ant-input-group-wrapper-disabled .ant-input-group-addon:hover) {
background-color: transparent !important;
}
:global(.ant-input-search-button) {
position: absolute;
top: -20px;
right: -11px;
border-radius: 0 28px 28px 0 !important;
overflow: hidden;
border: none;
height: 52px;
border-left: var(--ant-line-width) var(--ant-line-type)
var(--ant-color-border);
}
:global(.ant-input-number-handler-wrap) {
top: -20px;
height: @wrapheight - 2px;
}
}
@@ -4,6 +4,9 @@ interface WrapperProps {
children: React.ReactNode;
label: string;
isFocus: boolean;
status?: string;
className?: string;
disabled?: boolean;
onClick?: () => void;
}
@@ -11,10 +14,21 @@ const Wrapper: React.FC<WrapperProps> = ({
children,
label,
isFocus,
status,
className,
disabled,
onClick
}) => {
return (
<div className={wrapperStyle.wrapper} onClick={onClick}>
<div
className={classNames(
wrapperStyle.wrapper,
wrapperStyle[`validate-status-${status}`],
disabled ? wrapperStyle['seal-input-wrapper-disabled'] : '',
className ? wrapperStyle[className] : ''
)}
onClick={onClick}
>
<label
onClick={onClick}
className={classNames(
+68
View File
@@ -0,0 +1,68 @@
import type { InputNumberProps } from 'antd';
import { Form, InputNumber } from 'antd';
import { useEffect, useRef, useState } from 'react';
import Wrapper from './components/wrapper';
import { SealFormItemProps } from './types';
const SealInputNumber: React.FC<InputNumberProps & SealFormItemProps> = (
props
) => {
const { label, placeholder, ...rest } = props;
const [isFocus, setIsFocus] = useState(false);
const inputRef = useRef<any>(null);
const { status } = Form.Item.useStatus();
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?.value) {
setIsFocus(false);
props.onBlur?.(e);
}
};
const handleInput = (e: any) => {
props.onInput?.(e);
};
return (
<Wrapper
status={status}
label={label || (placeholder as string)}
isFocus={isFocus}
disabled={props.disabled}
onClick={handleClickWrapper}
>
<InputNumber
{...rest}
ref={inputRef}
onFocus={handleOnFocus}
onBlur={handleOnBlur}
onInput={handleInput}
onChange={(e) => handleChange(e)}
></InputNumber>
</Wrapper>
);
};
export default SealInputNumber;
+77
View File
@@ -0,0 +1,77 @@
import { Form, Input } from 'antd';
import type { SearchProps } from 'antd/es/input/Search';
import { useEffect, useRef, useState } from 'react';
import Wrapper from './components/wrapper';
import { SealFormItemProps } from './types';
type OnSearch = (
value: string,
event?:
| React.ChangeEvent<HTMLInputElement>
| React.MouseEvent<HTMLElement>
| React.KeyboardEvent<HTMLInputElement>,
info?: {
source?: 'clear' | 'input';
}
) => void;
const SealInputSearch: React.FC<SearchProps & SealFormItemProps> = (props) => {
const { label, placeholder, ...rest } = props;
const [isFocus, setIsFocus] = useState(false);
const inputRef = useRef<any>(null);
const { status } = Form.Item.useStatus();
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);
}
};
const handleSearch: OnSearch = (...args) => {
props.onSearch?.(...args);
};
return (
<Wrapper
status={status}
label={label || (placeholder as string)}
isFocus={isFocus}
disabled={props.disabled}
onClick={handleClickWrapper}
>
<Input.Search
{...rest}
ref={inputRef}
onFocus={handleOnFocus}
onBlur={handleOnBlur}
onSearch={handleSearch}
onChange={(e) => handleChange(e)}
></Input.Search>
</Wrapper>
);
};
export default SealInputSearch;
+61
View File
@@ -0,0 +1,61 @@
import type { InputProps } from 'antd';
import { Form, Input } from 'antd';
import { useEffect, useRef, useState } from 'react';
import Wrapper from './components/wrapper';
import { SealFormItemProps } from './types';
const SealPassword: React.FC<InputProps & SealFormItemProps> = (props) => {
const { label, placeholder, ...rest } = props;
const [isFocus, setIsFocus] = useState(false);
const inputRef = useRef<any>(null);
const { status } = Form.Item.useStatus();
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
status={status}
label={label || (placeholder as string)}
isFocus={isFocus}
disabled={props.disabled}
onClick={handleClickWrapper}
>
<Input.Password
{...rest}
ref={inputRef}
onFocus={handleOnFocus}
onBlur={handleOnBlur}
onChange={(e) => handleChange(e)}
></Input.Password>
</Wrapper>
);
};
export default SealPassword;
+84 -18
View File
@@ -1,27 +1,18 @@
import type { InputProps } from 'antd';
import { Input } from 'antd';
import { Form, Input } from 'antd';
import type { TextAreaProps } from 'antd/es/input/TextArea';
import { useEffect, useRef, useState } from 'react';
import Wrapper from './components/wrapper';
import SealInputNumber from './input-number';
import SealInputSearch from './input-search';
import SealPassword from './password';
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>
</Wrapper>
);
};
const SealInput: React.FC<InputProps & SealFormItemProps> = (props) => {
const { label, placeholder, ...rest } = props;
const SealTextArea: React.FC<TextAreaProps & SealFormItemProps> = (props) => {
const { label, placeholder, style, ...rest } = props;
const [isFocus, setIsFocus] = useState(false);
const inputRef = useRef<any>(null);
const { status } = Form.Item.useStatus();
useEffect(() => {
if (props.value) {
@@ -52,15 +43,84 @@ const SealInput: React.FC<InputProps & SealFormItemProps> = (props) => {
}
};
const handleInput = (e: any) => {
props.onInput?.(e);
};
return (
<Wrapper
status={status}
label={label || (placeholder as string)}
isFocus={isFocus}
className="seal-textarea-wrapper"
disabled={props.disabled}
onClick={handleClickWrapper}
>
<Input.TextArea
{...rest}
ref={inputRef}
style={{ minHeight: '80px', ...style }}
className="seal-textarea"
onFocus={handleOnFocus}
onBlur={handleOnBlur}
onInput={handleInput}
onChange={(e) => handleChange(e)}
></Input.TextArea>
</Wrapper>
);
};
const SealInput: React.FC<InputProps & SealFormItemProps> = (props) => {
const { label, placeholder, ...rest } = props;
const [isFocus, setIsFocus] = useState(false);
const inputRef = useRef<any>(null);
const { status } = Form.Item.useStatus();
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);
}
};
const handleInput = (e: any) => {
props.onInput?.(e);
};
return (
<Wrapper
status={status}
label={label || (placeholder as string)}
isFocus={isFocus}
disabled={props.disabled}
onClick={handleClickWrapper}
>
<Input
{...rest}
ref={inputRef}
onInput={handleInput}
onFocus={handleOnFocus}
onBlur={handleOnBlur}
onChange={(e) => handleChange(e)}
@@ -69,4 +129,10 @@ const SealInput: React.FC<InputProps & SealFormItemProps> = (props) => {
);
};
export default { TextArea, Input: SealInput };
export default {
TextArea: SealTextArea,
Input: SealInput,
Password: SealPassword,
Number: SealInputNumber,
Search: SealInputSearch
} as Record<string, React.FC<InputProps & SealFormItemProps>>;
+71
View File
@@ -0,0 +1,71 @@
import { isNotEmptyValue } from '@/utils/index';
import type { SelectProps } from 'antd';
import { Form, Select } from 'antd';
import { useEffect, useRef, useState } from 'react';
import Wrapper from './components/wrapper';
import { SealFormItemProps } from './types';
const SealSelect: React.FC<SelectProps & SealFormItemProps> = (props) => {
const { label, placeholder, children, ...rest } = props;
const [isFocus, setIsFocus] = useState(false);
const inputRef = useRef<any>(null);
const { status } = Form.Item.useStatus();
useEffect(() => {
if (isNotEmptyValue(props.value)) {
setIsFocus(true);
}
}, [props.value]);
const handleClickWrapper = () => {
if (!props.disabled && !isFocus) {
inputRef.current?.focus?.();
setIsFocus(true);
}
};
const handleChange = (val: any, options: any) => {
if (isNotEmptyValue(val)) {
setIsFocus(true);
} else {
setIsFocus(false);
}
props.onChange?.(val, options);
};
const handleOnFocus = (e: any) => {
setIsFocus(true);
props.onFocus?.(e);
};
const handleOnBlur = (e: any) => {
props.onBlur?.(e);
};
const handleOnSearch = (val: any) => {
props.onSearch?.(val);
};
return (
<Wrapper
status={status}
label={label || (placeholder as string)}
isFocus={isFocus}
disabled={props.disabled}
onClick={handleClickWrapper}
>
<Select
{...rest}
ref={inputRef}
onFocus={handleOnFocus}
onBlur={handleOnBlur}
onSearch={handleOnSearch}
onChange={(val, options) => handleChange(val, options)}
>
{children}
</Select>
</Wrapper>
);
};
export default SealSelect;