style: automatically omit table cell content based on width (#1646)

* style: automatically omit cell content based on width

* fix: cell tooltips are only displayed when the width is exceeded

* chore: multiple select ellipsis in table collection

* fix: no automatic thumbnail when table column content exceeds width

* refactor: table ellipsis

* refactor: isOverflowTooltip
This commit is contained in:
katherinehhh 2023-04-22 10:36:21 +08:00 committed by GitHub
parent 3c884cdd36
commit 564fe24c8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 90 additions and 36 deletions

View File

@ -58,16 +58,6 @@ const InternalField: React.FC = (props) => {
const originalProps = compile(uiSchema['x-component-props']) || {};
const componentProps = merge(originalProps, field.componentProps || {});
field.component = [component, componentProps];
// if (interfaceType === 'input') {
// field.componentProps.ellipsis = true;
// } else if (interfaceType === 'textarea') {
// field.componentProps.ellipsis = true;
// } else if (interfaceType === 'markdown') {
// field.componentProps.ellipsis = true;
// } else if (interfaceType === 'attachment') {
// field.componentProps.size = 'small';
// }
}, [JSON.stringify(uiSchema)]);
if (!uiSchema) {
return null;

View File

@ -1,3 +1,4 @@
import { ISchema } from '@formily/react';
import { defaultProps, operators } from './properties';
import { IField } from './types';
@ -23,4 +24,10 @@ export const checkbox: IField = {
filterable: {
operators: operators.boolean,
},
schemaInitialize(schema: ISchema, { block }) {
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
},
};

View File

@ -1,3 +1,4 @@
import { ISchema } from '@formily/react';
import { dataSource, defaultProps, operators } from './properties';
import { IField } from './types';
@ -17,7 +18,7 @@ export const checkboxGroup: IField = {
'x-component': 'Checkbox.Group',
},
},
availableTypes:['array'],
availableTypes: ['array'],
hasDefaultValue: true,
properties: {
...defaultProps,
@ -26,4 +27,10 @@ export const checkboxGroup: IField = {
filterable: {
operators: operators.array,
},
schemaInitialize(schema: ISchema, { block }) {
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
},
};

View File

@ -56,9 +56,13 @@ export const createdBy: IField = {
},
],
},
schemaInitialize(schema: ISchema, { readPretty }) {
schemaInitialize(schema: ISchema, { block }) {
schema['properties'] = {
viewer: cloneDeep(recordPickerViewer),
};
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
},
};

View File

@ -1,3 +1,4 @@
import { ISchema } from '@formily/react';
import { defaultProps, operators, unique } from './properties';
import { IField } from './types';
@ -18,7 +19,7 @@ export const email: IField = {
'x-validator': 'email',
},
},
availableTypes:['string'],
availableTypes: ['string'],
hasDefaultValue: true,
properties: {
...defaultProps,
@ -27,4 +28,10 @@ export const email: IField = {
filterable: {
operators: operators.string,
},
schemaInitialize(schema: ISchema, { block }) {
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
},
};

View File

@ -1,3 +1,4 @@
import { ISchema } from '@formily/react';
import { dataSource, defaultProps, operators } from './properties';
import { IField } from './types';
@ -21,7 +22,7 @@ export const multipleSelect: IField = {
enum: [],
},
},
availableTypes:['array'],
availableTypes: ['array'],
hasDefaultValue: true,
properties: {
...defaultProps,
@ -30,4 +31,10 @@ export const multipleSelect: IField = {
filterable: {
operators: operators.array,
},
schemaInitialize(schema: ISchema, { block }) {
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
},
};

View File

@ -1,3 +1,4 @@
import { ISchema } from '@formily/react';
import { dataSource, defaultProps, operators } from './properties';
import { IField } from './types';
@ -27,4 +28,10 @@ export const select: IField = {
filterable: {
operators: operators.enumType,
},
schemaInitialize(schema: ISchema, { block }) {
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
},
};

View File

@ -55,9 +55,13 @@ export const updatedBy: IField = {
},
],
},
schemaInitialize(schema: ISchema, { readPretty }) {
schemaInitialize(schema: ISchema, { block }) {
schema['properties'] = {
viewer: cloneDeep(recordPickerViewer),
};
if (['Table', 'Kanban'].includes(block)) {
schema['x-component-props'] = schema['x-component-props'] || {};
schema['x-component-props']['ellipsis'] = true;
}
},
};

View File

@ -5,6 +5,7 @@ import { Checkbox as AntdCheckbox, Tag } from 'antd';
import type { CheckboxGroupProps, CheckboxProps } from 'antd/lib/checkbox';
import uniq from 'lodash/uniq';
import React from 'react';
import { EllipsisWithTooltip } from '../input/EllipsisWithTooltip';
type ComposedCheckbox = React.FC<CheckboxProps> & {
Group?: React.FC<CheckboxGroupProps>;
@ -18,12 +19,10 @@ export const Checkbox: ComposedCheckbox = connect(
};
return <AntdCheckbox {...props} onChange={changeHandler} />;
},
mapProps(
{
value: 'checked',
onInput: 'onChange',
},
),
mapProps({
value: 'checked',
onInput: 'onChange',
}),
mapReadPretty((props) => {
if (props.value) {
return <CheckOutlined style={{ color: '#52c41a' }} />;
@ -36,21 +35,18 @@ Checkbox.__ANT_CHECKBOX = true;
Checkbox.Group = connect(
AntdCheckbox.Group,
mapProps(
{
dataSource: 'options',
},
),
mapProps({
dataSource: 'options',
}),
mapReadPretty((props) => {
if (!isValid(props.value)) {
return null;
}
const { options = [] } = props;
const field = useField<any>();
const dataSource = field.dataSource || [];
const value = uniq(field.value ? field.value : []);
return (
<div>
<EllipsisWithTooltip ellipsis={props.ellipsis}>
{dataSource
.filter((option) => value.includes(option.value))
.map((option, key) => (
@ -58,7 +54,7 @@ Checkbox.Group = connect(
{option.label}
</Tag>
))}
</div>
</EllipsisWithTooltip>
);
}),
);

View File

@ -1,6 +1,14 @@
import { Popover } from 'antd';
import React, { CSSProperties, forwardRef, useImperativeHandle, useState } from 'react';
import React, { CSSProperties, forwardRef, useImperativeHandle, useState, useRef } from 'react';
const getContentWidth = (element) => {
if (element) {
const range = document.createRange();
range.selectNodeContents(element);
const contentWidth = range.getBoundingClientRect().width;
return contentWidth;
}
};
const ellipsisDefaultStyle: CSSProperties = {
overflow: 'hidden',
overflowWrap: 'break-word',
@ -14,9 +22,11 @@ interface IEllipsisWithTooltipProps {
popoverContent: unknown;
children: any;
}
export const EllipsisWithTooltip = forwardRef((props: Partial<IEllipsisWithTooltipProps>, ref: any) => {
const [ellipsis, setEllipsis] = useState(false);
const [visible, setVisible] = useState(false);
const elRef: any = useRef();
useImperativeHandle(ref, () => {
return {
setPopoverVisible: setVisible,
@ -26,6 +36,13 @@ export const EllipsisWithTooltip = forwardRef((props: Partial<IEllipsisWithToolt
return <>{props.children}</>;
}
const { popoverContent } = props;
const isOverflowTooltip = () => {
const contentWidth = getContentWidth(elRef.current);
const offsetWidth = elRef.current?.offsetWidth;
return contentWidth > offsetWidth;
};
return (
<Popover
visible={ellipsis && visible}
@ -44,10 +61,14 @@ export const EllipsisWithTooltip = forwardRef((props: Partial<IEllipsisWithToolt
}
>
<div
ref={elRef}
style={{ ...ellipsisDefaultStyle }}
onMouseEnter={(e) => {
const el = e.target as any;
setEllipsis(el.scrollWidth > el.clientWidth);
const isShowTooltips = isOverflowTooltip();
if (isShowTooltips) {
setEllipsis(el.scrollWidth >= el.clientWidth);
}
}}
>
{props.children}

View File

@ -5,6 +5,7 @@ import { Tag } from 'antd';
import React from 'react';
import { useCompile } from '../../hooks';
import { defaultFieldNames, getCurrentOptions } from './shared';
import { EllipsisWithTooltip } from '../input/EllipsisWithTooltip';
type Composed = {
Select?: React.FC<any>;
@ -24,13 +25,16 @@ export const ReadPretty = observer((props: any) => {
}
const dataSource = field.dataSource || props.options || [];
const options = getCurrentOptions(field.value, dataSource, fieldNames);
return (
<div>
{options.map((option, key) => (
<Tag key={key} color={option[fieldNames.color]} icon={option.icon}>
{compile(option[fieldNames.label])}
</Tag>
))}
<EllipsisWithTooltip ellipsis={props.ellipsis}>
{options.map((option, key) => (
<Tag key={key} color={option[fieldNames.color]} icon={option.icon}>
{compile(option[fieldNames.label])}
</Tag>
))}
</EllipsisWithTooltip>
</div>
);
});