feat: add input into schema component (#158)
* feat: add Input Component to schema compoennt * code cleanup Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
e40565e90a
commit
150deb28c1
@ -6,4 +6,5 @@ export * from './dnd-context';
|
||||
export * from './form';
|
||||
export * from './form-item';
|
||||
export * from './grid';
|
||||
export * from './input';
|
||||
export * from './radio';
|
||||
|
28
packages/client/src/schema-component/antd/input/Input.tsx
Normal file
28
packages/client/src/schema-component/antd/input/Input.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { Input as AntdInput } from 'antd';
|
||||
import { InputProps, TextAreaProps } from 'antd/lib/input';
|
||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { ReadPretty } from './ReadPretty';
|
||||
|
||||
type ComposedInput = React.FC<InputProps> & {
|
||||
TextArea?: React.FC<TextAreaProps>;
|
||||
URL?: React.FC<InputProps>;
|
||||
DesignableBar?: React.FC<any>;
|
||||
};
|
||||
|
||||
export const Input: ComposedInput = connect(
|
||||
AntdInput,
|
||||
mapProps((props, field) => {
|
||||
return {
|
||||
...props,
|
||||
suffix: <span>{field?.['loading'] || field?.['validating'] ? <LoadingOutlined /> : props.suffix}</span>,
|
||||
};
|
||||
}),
|
||||
mapReadPretty(ReadPretty.Input),
|
||||
);
|
||||
|
||||
Input.TextArea = connect(AntdInput.TextArea, mapReadPretty(ReadPretty.TextArea));
|
||||
Input.URL = connect(AntdInput, mapReadPretty(ReadPretty.URL));
|
||||
|
||||
export default Input;
|
@ -0,0 +1,92 @@
|
||||
import { usePrefixCls } from '@formily/antd/esm/__builtins__';
|
||||
import { Popover } from 'antd';
|
||||
import { InputProps, TextAreaProps } from 'antd/lib/input';
|
||||
import cls from 'classnames';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
type Composed = {
|
||||
Input: React.FC<InputProps & { ellipsis?: any }>;
|
||||
URL: React.FC<InputProps>;
|
||||
TextArea: React.FC<TextAreaProps & { ellipsis?: any; text?: any; addonBefore?: any; suffix?: any; addonAfter?: any }>;
|
||||
};
|
||||
|
||||
export const ReadPretty: Composed = () => null;
|
||||
|
||||
ReadPretty.Input = (props) => {
|
||||
const prefixCls = usePrefixCls('description-input', props);
|
||||
const domRef = React.useRef<HTMLInputElement>(null);
|
||||
const compile = useCompile();
|
||||
const [ellipsis, setEllipsis] = useState(false);
|
||||
const content = compile(props.value);
|
||||
const ellipsisContent = (
|
||||
<Popover content={content} style={{ width: 100 }}>
|
||||
<span className={'input-ellipsis'}>{content}</span>
|
||||
</Popover>
|
||||
);
|
||||
useEffect(() => {
|
||||
if (domRef.current?.scrollWidth > domRef.current?.clientWidth) {
|
||||
setEllipsis(true);
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<div className={cls(prefixCls, props.className)} style={props.style}>
|
||||
{props.addonBefore}
|
||||
{props.prefix}
|
||||
<span ref={domRef}>{ellipsis ? ellipsisContent : content}</span>
|
||||
{props.suffix}
|
||||
{props.addonAfter}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ReadPretty.TextArea = (props) => {
|
||||
const prefixCls = usePrefixCls('description-textarea', props);
|
||||
const domRef = React.useRef<HTMLInputElement>(null);
|
||||
const [ellipsis, setEllipsis] = useState(false);
|
||||
const ellipsisProp = props.ellipsis === true ? {} : props.ellipsis;
|
||||
const ellipsisContent = (
|
||||
<Popover content={props.value}>
|
||||
<span
|
||||
className={'input-ellipsis'}
|
||||
style={{
|
||||
...ellipsisProp,
|
||||
}}
|
||||
>
|
||||
{props.text || props.value}
|
||||
</span>
|
||||
</Popover>
|
||||
);
|
||||
useEffect(() => {
|
||||
if (domRef.current?.scrollWidth > domRef.current?.clientWidth) {
|
||||
setEllipsis(true);
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<div className={cls(prefixCls, props.className)} style={props.style}>
|
||||
{props.addonBefore}
|
||||
{props.prefix}
|
||||
<span ref={domRef}>{ellipsis ? ellipsisContent : props.value}</span>
|
||||
{props.suffix}
|
||||
{props.addonAfter}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ReadPretty.URL = (props) => {
|
||||
const prefixCls = usePrefixCls('description-url', props);
|
||||
const content = props.value && (
|
||||
<a target={'_blank'} href={props.value as any}>
|
||||
{props.value}
|
||||
</a>
|
||||
);
|
||||
return (
|
||||
<div className={cls(prefixCls, props.className)} style={props.style}>
|
||||
{props.addonBefore}
|
||||
{props.prefix}
|
||||
{content}
|
||||
{props.suffix}
|
||||
{props.addonAfter}
|
||||
</div>
|
||||
);
|
||||
};
|
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* title: Input
|
||||
*/
|
||||
import { FormItem } from '@formily/antd';
|
||||
import { Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
|
||||
const schema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
input: {
|
||||
type: 'boolean',
|
||||
title: `Editable`,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
'x-reactions': {
|
||||
target: 'read',
|
||||
fulfill: {
|
||||
state: {
|
||||
value: '{{$self.value}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
read: {
|
||||
type: 'boolean',
|
||||
title: `Read pretty`,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<SchemaComponentProvider components={{ Input, FormItem }}>
|
||||
<SchemaComponent schema={schema} />
|
||||
</SchemaComponentProvider>
|
||||
);
|
||||
};
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* title: Textarea
|
||||
*/
|
||||
import { FormItem } from '@formily/antd';
|
||||
import { Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
|
||||
const schema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
input: {
|
||||
interface: 'string',
|
||||
type: 'string',
|
||||
title: `Editable`,
|
||||
name: 'name1',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input.TextArea',
|
||||
'x-reactions': {
|
||||
target: '*(read1,read2)',
|
||||
fulfill: {
|
||||
state: {
|
||||
value: '{{$self.value}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
read1: {
|
||||
interface: 'string',
|
||||
type: 'string',
|
||||
title: `Read pretty`,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input.TextArea',
|
||||
},
|
||||
read2: {
|
||||
interface: 'string',
|
||||
type: 'string',
|
||||
title: `Read pretty(ellipsis)`,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input.TextArea',
|
||||
'x-component-props': {
|
||||
ellipsis: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<SchemaComponentProvider components={{ Input, FormItem }}>
|
||||
<SchemaComponent schema={schema} />
|
||||
</SchemaComponentProvider>
|
||||
);
|
||||
};
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* title: URL
|
||||
*/
|
||||
import { FormItem } from '@formily/antd';
|
||||
import { Input, SchemaComponent, SchemaComponentProvider } from '@nocobase/client';
|
||||
import React from 'react';
|
||||
|
||||
const schema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
input: {
|
||||
type: 'string',
|
||||
title: `Editable`,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input.URL',
|
||||
'x-validator': 'url',
|
||||
'x-reactions': {
|
||||
target: 'read',
|
||||
fulfill: {
|
||||
state: {
|
||||
value: '{{$self.value}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
read: {
|
||||
type: 'string',
|
||||
title: `Read pretty`,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input.URL',
|
||||
'x-validator': 'url',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<SchemaComponentProvider components={{ Input, FormItem }}>
|
||||
<SchemaComponent schema={schema} />
|
||||
</SchemaComponentProvider>
|
||||
);
|
||||
};
|
@ -6,3 +6,23 @@ group:
|
||||
---
|
||||
|
||||
# Input
|
||||
|
||||
## Nodes
|
||||
|
||||
- Input
|
||||
- Input.TextArea
|
||||
- Input.URL
|
||||
|
||||
## Examples
|
||||
|
||||
### Input
|
||||
|
||||
<code src="./demos/demo1.tsx" />
|
||||
|
||||
### Textarea
|
||||
|
||||
<code src="./demos/demo2.tsx" />
|
||||
|
||||
### URL
|
||||
|
||||
<code src="./demos/demo3.tsx" />
|
||||
|
1
packages/client/src/schema-component/antd/input/index.ts
Normal file
1
packages/client/src/schema-component/antd/input/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './Input';
|
Loading…
Reference in New Issue
Block a user