feat: add IconPicker component into schema components

This commit is contained in:
semmy 2022-01-20 15:16:12 +08:00
parent d94874d345
commit d04d3d0639
8 changed files with 175 additions and 2 deletions

View File

@ -0,0 +1,51 @@
import * as antIcons from '@ant-design/icons';
import { createFromIconfontCN } from '@ant-design/icons';
import React from 'react';
export const IconFont = createFromIconfontCN({
scriptUrl: ['//at.alicdn.com/t/font_2261954_u9jzwc44ug.js'],
});
export const icons = new Map<string, any>();
export function registerIcon(type: string, icon: any = IconFont) {
icons.set(type.toLowerCase(), icon);
}
export function hasIcon(type: string) {
if (!type) {
return false;
}
return icons.has(type.toLowerCase());
}
export function registerIcons(components) {
Object.keys(components).forEach((type) => {
registerIcon(type, components[type]);
});
}
Object.keys(antIcons).forEach((name) => {
if (name.endsWith('Outlined')) {
registerIcon(name, antIcons[name]);
}
});
interface IconProps {
type: string;
[key: string]: any;
}
export function Icon(props: IconProps) {
const { type = '', ...restProps } = props;
if (type && icons.has(type.toLowerCase())) {
const IconComponent = icons.get(type.toLowerCase());
if (IconComponent === IconFont) {
return <IconFont type={type} />;
}
return <IconComponent {...restProps} />;
}
return null;
}
export default Icon;

View File

@ -0,0 +1 @@
export * from './Icon';

View File

@ -0,0 +1 @@
export * from './icon';

View File

@ -0,0 +1,71 @@
import { CloseOutlined, LoadingOutlined } from '@ant-design/icons';
import { connect, mapProps, mapReadPretty } from '@formily/react';
import { isValid } from '@formily/shared';
import { Button, Input, Popover } from 'antd';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { hasIcon, Icon, icons } from '../../../components/icon';
function IconField(props: any) {
const { value, onChange } = props;
const [visible, setVisible] = useState(false);
const { t } = useTranslation();
return (
<div>
<Input.Group compact>
<Popover
placement={'bottom'}
visible={visible}
onVisibleChange={(val) => {
setVisible(val);
}}
content={
<div style={{ width: '26em', maxHeight: '20em', overflowY: 'auto' }}>
{[...icons.keys()].map((key) => (
<span
style={{ fontSize: 18, marginRight: 10, cursor: 'pointer' }}
onClick={() => {
onChange(key);
setVisible(false);
}}
>
<Icon type={key} />
</span>
))}
</div>
}
title={t('Icon')}
trigger="click"
>
<Button>{hasIcon(value) ? <Icon type={value} /> : t('Select icon')}</Button>
</Popover>
{value && (
<Button
icon={<CloseOutlined />}
onClick={(e) => {
onChange(null);
}}
></Button>
)}
</Input.Group>
</div>
);
}
export const IconPicker = connect(
IconField,
mapProps((props, field) => {
return {
...props,
suffix: <span>{field?.['loading'] || field?.['validating'] ? <LoadingOutlined /> : props.suffix}</span>,
};
}),
mapReadPretty((props) => {
if (!isValid(props.value)) {
return <div></div>;
}
return <Icon type={props.value} />;
}),
);
export default IconPicker;

View File

@ -0,0 +1,41 @@
/**
* title: IconPicker
*/
import { FormItem } from '@formily/antd';
import { IconPicker, SchemaComponent, SchemaComponentProvider } from '@nocobase/client';
import React from 'react';
const schema = {
type: 'object',
properties: {
input: {
type: 'boolean',
title: `Editable`,
'x-decorator': 'FormItem',
'x-component': 'IconPicker',
'x-reactions': {
target: 'read',
fulfill: {
state: {
value: '{{$self.value}}',
},
},
},
},
read: {
type: 'boolean',
title: `Read pretty`,
'x-read-pretty': true,
'x-decorator': 'FormItem',
'x-component': 'IconPicker',
},
},
};
export default () => {
return (
<SchemaComponentProvider components={{ IconPicker, FormItem }}>
<SchemaComponent schema={schema} />
</SchemaComponentProvider>
);
};

View File

@ -6,3 +6,9 @@ group:
---
# IconPicker
## Examples
### IconPicker usage
<code src="./demos/demo1.tsx" />

View File

@ -0,0 +1 @@
export * from './IconPicker';

View File

@ -7,9 +7,10 @@ export * from './dnd-context';
export * from './form';
export * from './form-item';
export * from './grid';
export * from './icon-picker';
export * from './input';
export * from './input-number';
export * from './password';
export * from './radio';
export * from './menu';
export * from './page';
export * from './password';
export * from './radio';