chore: add model api
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { Cascader, Input, Popover } from 'antd';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
|
||||
const { Panel } = Cascader;
|
||||
|
||||
const options = [
|
||||
{
|
||||
value: 'fruit',
|
||||
label: 'Fruit',
|
||||
children: [
|
||||
{ value: 'apple', label: 'Apple' },
|
||||
{ value: 'banana', label: 'Banana' }
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'vegetable',
|
||||
label: 'Vegetable',
|
||||
children: [
|
||||
{ value: 'carrot', label: 'Carrot' },
|
||||
{ value: 'potato', label: 'Potato' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const CustomCascader: React.FC = () => {
|
||||
const [value, setValue] = useState<string>('');
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [inputWidth, setInputWidth] = useState<number>(0);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (inputRef.current) {
|
||||
setInputWidth(inputRef.current.offsetWidth);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleCascaderChange = (selectedValues: string[]) => {
|
||||
setValue(selectedValues.join(' / '));
|
||||
setVisible(false);
|
||||
};
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setValue(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover
|
||||
overlayStyle={{ minWidth: inputWidth }}
|
||||
content={
|
||||
<div style={{ width: '100%' }}>
|
||||
<Panel
|
||||
options={options}
|
||||
onChange={handleCascaderChange}
|
||||
changeOnSelect
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
arrow={false}
|
||||
placement="bottomLeft"
|
||||
trigger="click"
|
||||
open={visible}
|
||||
onOpenChange={setVisible}
|
||||
>
|
||||
<Input
|
||||
ref={inputRef}
|
||||
placeholder="Select or type..."
|
||||
value={value}
|
||||
onChange={handleInputChange}
|
||||
onClick={() => setVisible(true)}
|
||||
/>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
export default CustomCascader;
|
||||
@@ -262,7 +262,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
:global(.ant-select.ant-cascader .ant-select-selection-search) {
|
||||
:global(
|
||||
.ant-select.ant-select-multiple.ant-cascader .ant-select-selection-search
|
||||
) {
|
||||
top: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,78 @@
|
||||
import { isNotEmptyValue } from '@/utils/index';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import type { CascaderAutoProps } from 'antd';
|
||||
import { Cascader, Form } from 'antd';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Cascader, Empty, Form } from 'antd';
|
||||
import _, { cloneDeep } from 'lodash';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import AutoTooltip from '../auto-tooltip';
|
||||
import Wrapper from './components/wrapper';
|
||||
import { SealFormItemProps } from './types';
|
||||
|
||||
const SealCascader: React.FC<CascaderAutoProps & SealFormItemProps> = (
|
||||
props
|
||||
) => {
|
||||
const tag = (props: any) => {
|
||||
if (props.isMaxTag) {
|
||||
return props.label;
|
||||
}
|
||||
const parent = _.split(props.value, '__RC_CASCADER_SPLIT__')?.[0];
|
||||
return `${parent} / ${props?.label}`;
|
||||
};
|
||||
|
||||
const renderTag = (props: any) => {
|
||||
return (
|
||||
<AutoTooltip
|
||||
className="m-r-4"
|
||||
closable={props.closable}
|
||||
onClose={props.onClose}
|
||||
maxWidth={240}
|
||||
>
|
||||
{tag(props)}
|
||||
</AutoTooltip>
|
||||
);
|
||||
};
|
||||
|
||||
const OptionNodes = (props: {
|
||||
data: any;
|
||||
optionNode: React.FC<{ data: any }>;
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const { data, optionNode: OptionNode } = props;
|
||||
if (data.value === '__EMPTY__') {
|
||||
return (
|
||||
<Empty
|
||||
image={false}
|
||||
style={{
|
||||
height: 100,
|
||||
alignSelf: 'center',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
description={intl.formatMessage({
|
||||
id: 'common.search.empty'
|
||||
})}
|
||||
></Empty>
|
||||
);
|
||||
}
|
||||
let width: any = {
|
||||
maxWidth: 140,
|
||||
minWidth: 140
|
||||
};
|
||||
if (!data.parent) {
|
||||
width = undefined;
|
||||
}
|
||||
if (data.parent) {
|
||||
return (
|
||||
<AutoTooltip ghost {...width}>
|
||||
{data.label}
|
||||
</AutoTooltip>
|
||||
);
|
||||
}
|
||||
return OptionNode ? <OptionNode data={data}></OptionNode> : data.label;
|
||||
};
|
||||
|
||||
const SealCascader: React.FC<
|
||||
CascaderAutoProps &
|
||||
SealFormItemProps & { optionNode?: React.FC<{ data: any }> }
|
||||
> = (props) => {
|
||||
const {
|
||||
label,
|
||||
placeholder,
|
||||
@@ -19,6 +82,8 @@ const SealCascader: React.FC<CascaderAutoProps & SealFormItemProps> = (
|
||||
options,
|
||||
allowNull,
|
||||
isInFormItems = true,
|
||||
optionNode,
|
||||
tagRender,
|
||||
...rest
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
@@ -100,6 +165,14 @@ const SealCascader: React.FC<CascaderAutoProps & SealFormItemProps> = (
|
||||
>
|
||||
<Cascader
|
||||
{...rest}
|
||||
optionRender={
|
||||
optionNode
|
||||
? (data) => (
|
||||
<OptionNodes data={data} optionNode={optionNode}></OptionNodes>
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
tagRender={tagRender ?? renderTag}
|
||||
ref={inputRef}
|
||||
options={children ? null : _options}
|
||||
onFocus={handleOnFocus}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
border-radius: 20px;
|
||||
min-width: 76px;
|
||||
width: max-content;
|
||||
height: 26px;
|
||||
height: 24px;
|
||||
font-size: var(--font-size-base);
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user