Unverified Commit 150deb28 authored by SemmyWong's avatar SemmyWong Committed by GitHub
Browse files

feat: add input into schema component (#158)


* feat: add Input Component to schema compoennt

* code cleanup
Co-authored-by: default avatarchenos <chenlinxh@gmail.com>
parent e40565e9
Showing with 281 additions and 0 deletions
+281 -0
......@@ -6,4 +6,5 @@ export * from './dnd-context';
export * from './form';
export * from './form-item';
export * from './grid';
export * from './input';
export * from './radio';
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;
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>
);
};
/**
* 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>
);
};
/**
* 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>
);
};
/**
* 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" />
export * from './Input';
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment