feat: 图标支持快捷搜索, 悬浮提示 (#743)

![image](/attachments/24bd3a25-990d-431c-8682-a7e034d7826d)

Co-authored-by: sealday <zhanglin@daoyoucloud.com>
Reviewed-on: daoyoucloud/tachycode#743
Co-authored-by: bai.zixv <bai.zixv@foxmail.com>
Co-committed-by: bai.zixv <bai.zixv@foxmail.com>
This commit is contained in:
bai.zixv 2024-04-17 13:56:39 +08:00 committed by sealday
parent 8d9fc95977
commit e3f23fa7b1
4 changed files with 74 additions and 20 deletions

View File

@ -57,7 +57,7 @@ CACHE_MEMORY_MAX=2000
################# STORAGE (Initialization only) ################# ################# STORAGE (Initialization only) #################
INIT_LANG=en-US INIT_LANG=en-US
INIT_ROOT_EMAIL=admin@nocobase.com INIT_ROOT_EMAIL=admin@tachybase.com
INIT_ROOT_PASSWORD=admin123 INIT_ROOT_PASSWORD=!Admin123.
INIT_ROOT_NICKNAME=Super Admin INIT_ROOT_NICKNAME=Super Admin
INIT_ROOT_USERNAME=nocobase INIT_ROOT_USERNAME=tachybase

View File

@ -0,0 +1,13 @@
import { Input } from 'antd';
import _ from 'lodash';
import React from 'react';
export const IconFilter = (props) => {
const { changeFilterKey } = props;
const onChange = _.debounce((e) => {
const inputValue = e.target.value;
changeFilterKey(inputValue);
}, 100);
return <Input allowClear placeholder={`antd的key,例如"ApiOutlined",忽略大小写`} onChange={onChange} />;
};

View File

@ -0,0 +1,47 @@
import React, { useMemo, useState } from 'react';
import { Icon, icons } from '../../../icon';
import { Tooltip } from 'antd';
export const IconList = (props) => {
const { filterKey, onChange, changePop } = props;
const iconKeysByFilter = useMemo(() => {
if (!filterKey) {
return icons;
}
const filterIcons = new Map();
for (const key of icons.keys()) {
if (key.toLowerCase().includes(filterKey.toLowerCase())) {
filterIcons.set(key, icons.get(key));
}
}
return filterIcons;
}, [filterKey]);
return (
<div style={{ width: '26em', maxHeight: '20em', overflowY: 'auto' }}>
{[...iconKeysByFilter.keys()].map((key) => (
<span key={key} style={{ fontSize: 18, marginRight: 10, cursor: 'pointer' }}>
<Tooltip
destroyTooltipOnHide
mouseEnterDelay={0.3}
mouseLeaveDelay={0.3}
placement="top"
title={key}
arrow={{
pointAtCenter: true,
}}
>
<Icon
onClick={() => {
onChange(key);
changePop(false);
}}
type={key}
/>
</Tooltip>
</span>
))}
</div>
);
};

View File

@ -3,16 +3,20 @@ import { useFormLayout } from '@formily/antd-v5';
import { connect, mapProps, mapReadPretty } from '@nocobase/schema'; import { connect, mapProps, mapReadPretty } from '@nocobase/schema';
import { isValid } from '@nocobase/schema'; import { isValid } from '@nocobase/schema';
import { Button, Space } from 'antd'; import { Button, Space } from 'antd';
import React, { useState } from 'react'; import React, { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Icon, hasIcon, icons } from '../../../icon'; import { Icon, hasIcon, icons } from '../../../icon';
import { StablePopover } from '../popover'; import { StablePopover } from '../popover';
import { IconFilter } from './IconFilter';
import { IconList } from './IconList';
function IconField(props: any) { function IconField(props: any) {
const layout = useFormLayout();
const { value, onChange, disabled } = props; const { value, onChange, disabled } = props;
const [visible, setVisible] = useState(false);
const { t } = useTranslation(); const { t } = useTranslation();
const layout = useFormLayout();
const [visible, setVisible] = useState(false);
const [filterKey, setFilterKey] = useState('');
return ( return (
<div> <div>
<Space.Compact> <Space.Compact>
@ -26,20 +30,10 @@ function IconField(props: any) {
setVisible(val); setVisible(val);
}} }}
content={ content={
<div style={{ width: '26em', maxHeight: '20em', overflowY: 'auto' }}> <>
{[...icons.keys()].map((key) => ( <IconFilter changeFilterKey={setFilterKey} />
<span <IconList filterKey={filterKey} onChange={onChange} changePop={setVisible} />
key={key} </>
style={{ fontSize: 18, marginRight: 10, cursor: 'pointer' }}
onClick={() => {
onChange(key);
setVisible(false);
}}
>
<Icon type={key} />
</span>
))}
</div>
} }
title={t('Icon')} title={t('Icon')}
trigger="click" trigger="click"