fix(client): ellipsis with tooltip

This commit is contained in:
chenos 2022-03-08 16:56:57 +08:00
parent d7a9608663
commit 60a915b50c
5 changed files with 97 additions and 48 deletions

View File

@ -10,7 +10,7 @@ import { useCollectionField } from './hooks';
const InternalField: React.FC = (props) => { const InternalField: React.FC = (props) => {
const field = useField<Field>(); const field = useField<Field>();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const { uiSchema } = useCollectionField(); const { name, uiSchema } = useCollectionField();
const component = useComponent(uiSchema?.['x-component']); const component = useComponent(uiSchema?.['x-component']);
const compile = useCompile(); const compile = useCompile();
const setFieldProps = (key, value) => { const setFieldProps = (key, value) => {
@ -34,9 +34,10 @@ const InternalField: React.FC = (props) => {
setRequired(); setRequired();
// @ts-ignore // @ts-ignore
field.dataSource = uiSchema.enum; field.dataSource = uiSchema.enum;
const originalProps = compile(uiSchema['x-component-props']); const originalProps = compile(uiSchema['x-component-props']) || {};
const componentProps = field.componentProps; const componentProps = merge(originalProps, field.componentProps || {});
field.component = [component, merge(originalProps, componentProps)]; field.component = [component, componentProps];
// console.log('componentProps', uiSchema?.title, field.componentProps);
}, [uiSchema?.title, uiSchema?.description, uiSchema?.required]); }, [uiSchema?.title, uiSchema?.description, uiSchema?.required]);
if (!uiSchema) { if (!uiSchema) {
return null; return null;

View File

@ -0,0 +1,40 @@
import { Popover } from 'antd';
import React, { CSSProperties, useState } from 'react';
const ellipsisDefaultStyle: CSSProperties = {
overflow: 'hidden',
overflowWrap: 'break-word',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
wordBreak: 'break-all',
};
export const EllipsisWithTooltip = (props) => {
const [ellipsis, setEllipsis] = useState(false);
const [visible, setVisible] = useState(false);
if (!props.ellipsis) {
return <>{props.children}</>;
}
return (
<Popover
visible={ellipsis && visible}
onVisibleChange={(visible) => {
setVisible(ellipsis && visible);
}}
content={props.children}
overlayStyle={{
width: 300,
}}
>
<div
style={{ ...ellipsisDefaultStyle }}
onMouseEnter={(e) => {
const el = e.target as any;
setEllipsis(el.scrollWidth > el.clientWidth);
}}
>
{props.children}
</div>
</Popover>
);
};

View File

@ -1,9 +1,8 @@
import { usePrefixCls } from '@formily/antd/lib/__builtins__'; import { usePrefixCls } from '@formily/antd/lib/__builtins__';
import { Popover } from 'antd';
import { InputProps, TextAreaProps } from 'antd/lib/input'; import { InputProps, TextAreaProps } from 'antd/lib/input';
import cls from 'classnames'; import cls from 'classnames';
import React, { useEffect, useState } from 'react'; import React from 'react';
import { useCompile } from '../../hooks/useCompile'; import { EllipsisWithTooltip } from './EllipsisWithTooltip';
type Composed = { type Composed = {
Input: React.FC<InputProps & { ellipsis?: any }>; Input: React.FC<InputProps & { ellipsis?: any }>;
@ -15,25 +14,11 @@ export const ReadPretty: Composed = () => null;
ReadPretty.Input = (props) => { ReadPretty.Input = (props) => {
const prefixCls = usePrefixCls('description-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 ( return (
<div className={cls(prefixCls, props.className)} style={props.style}> <div className={cls(prefixCls, props.className)} style={props.style}>
{props.addonBefore} {props.addonBefore}
{props.prefix} {props.prefix}
<span ref={domRef}>{ellipsis ? ellipsisContent : content}</span> <EllipsisWithTooltip ellipsis={props.ellipsis}>{props.value}</EllipsisWithTooltip>
{props.suffix} {props.suffix}
{props.addonAfter} {props.addonAfter}
</div> </div>
@ -41,32 +26,13 @@ ReadPretty.Input = (props) => {
}; };
ReadPretty.TextArea = (props) => { ReadPretty.TextArea = (props) => {
console.log('EllipsisWithTooltip', props.ellipsis);
const prefixCls = usePrefixCls('description-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 ( return (
<div className={cls(prefixCls, props.className)} style={props.style}> <div className={cls(prefixCls, props.className)} style={props.style}>
{props.addonBefore} {props.addonBefore}
{props.prefix} {props.prefix}
<span ref={domRef}>{ellipsis ? ellipsisContent : props.value}</span> <EllipsisWithTooltip ellipsis={props.ellipsis}>{props.value}</EllipsisWithTooltip>
{props.suffix} {props.suffix}
{props.addonAfter} {props.addonAfter}
</div> </div>

View File

@ -87,6 +87,20 @@ export const components = {
row: (props) => { row: (props) => {
return <tr {...props} />; return <tr {...props} />;
}, },
cell: (props) => (
<td
{...props}
className={classNames(
props.className,
css`
max-width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`,
)}
/>
),
}, },
}; };
@ -228,7 +242,14 @@ export const TableArray: React.FC<any> = observer((props) => {
}; };
return ( return (
<div> <div
className={css`
.ant-table {
overflow-x: auto;
overflow-y: hidden;
}
`}
>
<ReactDragListView <ReactDragListView
handleSelector={'.drag-handle'} handleSelector={'.drag-handle'}
onDragEnd={async (fromIndex, toIndex) => { onDragEnd={async (fromIndex, toIndex) => {

View File

@ -61,6 +61,28 @@ export const useTableColumnInitializerFields = () => {
return fields return fields
.filter((field) => field?.interface && field?.interface !== 'subTable') .filter((field) => field?.interface && field?.interface !== 'subTable')
.map((field) => { .map((field) => {
const componentProps = {};
if (field?.uiSchema['x-component']?.startsWith?.('Input')) {
componentProps['ellipsis'] = true;
}
if (field.interface === 'attachment') {
componentProps['size'] = 'small';
return {
type: 'item',
title: field?.uiSchema?.title || field.name,
component: 'CollectionFieldInitializer',
find: findTableColumn,
remove: removeTableColumn,
schema: {
name: field.name,
'x-collection-field': `${name}.${field.name}`,
'x-component': 'CollectionField',
'x-component-props': {
...componentProps,
},
},
} as SchemaInitializerItemOptions;
}
if (field.target) { if (field.target) {
return { return {
field, field,
@ -73,13 +95,12 @@ export const useTableColumnInitializerFields = () => {
name: field.name, name: field.name,
'x-collection-field': `${name}.${field.name}`, 'x-collection-field': `${name}.${field.name}`,
'x-component': 'CollectionField', 'x-component': 'CollectionField',
'x-component-props': {
...componentProps,
},
}, },
} as SchemaInitializerItemOptions; } as SchemaInitializerItemOptions;
} }
const componentProps = {};
if (field.interface === 'attachment') {
componentProps['size'] = 'small';
}
return { return {
type: 'item', type: 'item',
title: field?.uiSchema?.title || field.name, title: field?.uiSchema?.title || field.name,