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:
parent
3c884cdd36
commit
564fe24c8a
@ -58,16 +58,6 @@ const InternalField: React.FC = (props) => {
|
|||||||
const originalProps = compile(uiSchema['x-component-props']) || {};
|
const originalProps = compile(uiSchema['x-component-props']) || {};
|
||||||
const componentProps = merge(originalProps, field.componentProps || {});
|
const componentProps = merge(originalProps, field.componentProps || {});
|
||||||
field.component = [component, 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)]);
|
}, [JSON.stringify(uiSchema)]);
|
||||||
if (!uiSchema) {
|
if (!uiSchema) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ISchema } from '@formily/react';
|
||||||
import { defaultProps, operators } from './properties';
|
import { defaultProps, operators } from './properties';
|
||||||
import { IField } from './types';
|
import { IField } from './types';
|
||||||
|
|
||||||
@ -23,4 +24,10 @@ export const checkbox: IField = {
|
|||||||
filterable: {
|
filterable: {
|
||||||
operators: operators.boolean,
|
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;
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ISchema } from '@formily/react';
|
||||||
import { dataSource, defaultProps, operators } from './properties';
|
import { dataSource, defaultProps, operators } from './properties';
|
||||||
import { IField } from './types';
|
import { IField } from './types';
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ export const checkboxGroup: IField = {
|
|||||||
'x-component': 'Checkbox.Group',
|
'x-component': 'Checkbox.Group',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
availableTypes:['array'],
|
availableTypes: ['array'],
|
||||||
hasDefaultValue: true,
|
hasDefaultValue: true,
|
||||||
properties: {
|
properties: {
|
||||||
...defaultProps,
|
...defaultProps,
|
||||||
@ -26,4 +27,10 @@ export const checkboxGroup: IField = {
|
|||||||
filterable: {
|
filterable: {
|
||||||
operators: operators.array,
|
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;
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -56,9 +56,13 @@ export const createdBy: IField = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
schemaInitialize(schema: ISchema, { readPretty }) {
|
schemaInitialize(schema: ISchema, { block }) {
|
||||||
schema['properties'] = {
|
schema['properties'] = {
|
||||||
viewer: cloneDeep(recordPickerViewer),
|
viewer: cloneDeep(recordPickerViewer),
|
||||||
};
|
};
|
||||||
|
if (['Table', 'Kanban'].includes(block)) {
|
||||||
|
schema['x-component-props'] = schema['x-component-props'] || {};
|
||||||
|
schema['x-component-props']['ellipsis'] = true;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ISchema } from '@formily/react';
|
||||||
import { defaultProps, operators, unique } from './properties';
|
import { defaultProps, operators, unique } from './properties';
|
||||||
import { IField } from './types';
|
import { IField } from './types';
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ export const email: IField = {
|
|||||||
'x-validator': 'email',
|
'x-validator': 'email',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
availableTypes:['string'],
|
availableTypes: ['string'],
|
||||||
hasDefaultValue: true,
|
hasDefaultValue: true,
|
||||||
properties: {
|
properties: {
|
||||||
...defaultProps,
|
...defaultProps,
|
||||||
@ -27,4 +28,10 @@ export const email: IField = {
|
|||||||
filterable: {
|
filterable: {
|
||||||
operators: operators.string,
|
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;
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ISchema } from '@formily/react';
|
||||||
import { dataSource, defaultProps, operators } from './properties';
|
import { dataSource, defaultProps, operators } from './properties';
|
||||||
import { IField } from './types';
|
import { IField } from './types';
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ export const multipleSelect: IField = {
|
|||||||
enum: [],
|
enum: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
availableTypes:['array'],
|
availableTypes: ['array'],
|
||||||
hasDefaultValue: true,
|
hasDefaultValue: true,
|
||||||
properties: {
|
properties: {
|
||||||
...defaultProps,
|
...defaultProps,
|
||||||
@ -30,4 +31,10 @@ export const multipleSelect: IField = {
|
|||||||
filterable: {
|
filterable: {
|
||||||
operators: operators.array,
|
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;
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ISchema } from '@formily/react';
|
||||||
import { dataSource, defaultProps, operators } from './properties';
|
import { dataSource, defaultProps, operators } from './properties';
|
||||||
import { IField } from './types';
|
import { IField } from './types';
|
||||||
|
|
||||||
@ -27,4 +28,10 @@ export const select: IField = {
|
|||||||
filterable: {
|
filterable: {
|
||||||
operators: operators.enumType,
|
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;
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -55,9 +55,13 @@ export const updatedBy: IField = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
schemaInitialize(schema: ISchema, { readPretty }) {
|
schemaInitialize(schema: ISchema, { block }) {
|
||||||
schema['properties'] = {
|
schema['properties'] = {
|
||||||
viewer: cloneDeep(recordPickerViewer),
|
viewer: cloneDeep(recordPickerViewer),
|
||||||
};
|
};
|
||||||
|
if (['Table', 'Kanban'].includes(block)) {
|
||||||
|
schema['x-component-props'] = schema['x-component-props'] || {};
|
||||||
|
schema['x-component-props']['ellipsis'] = true;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@ import { Checkbox as AntdCheckbox, Tag } from 'antd';
|
|||||||
import type { CheckboxGroupProps, CheckboxProps } from 'antd/lib/checkbox';
|
import type { CheckboxGroupProps, CheckboxProps } from 'antd/lib/checkbox';
|
||||||
import uniq from 'lodash/uniq';
|
import uniq from 'lodash/uniq';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { EllipsisWithTooltip } from '../input/EllipsisWithTooltip';
|
||||||
|
|
||||||
type ComposedCheckbox = React.FC<CheckboxProps> & {
|
type ComposedCheckbox = React.FC<CheckboxProps> & {
|
||||||
Group?: React.FC<CheckboxGroupProps>;
|
Group?: React.FC<CheckboxGroupProps>;
|
||||||
@ -18,12 +19,10 @@ export const Checkbox: ComposedCheckbox = connect(
|
|||||||
};
|
};
|
||||||
return <AntdCheckbox {...props} onChange={changeHandler} />;
|
return <AntdCheckbox {...props} onChange={changeHandler} />;
|
||||||
},
|
},
|
||||||
mapProps(
|
mapProps({
|
||||||
{
|
value: 'checked',
|
||||||
value: 'checked',
|
onInput: 'onChange',
|
||||||
onInput: 'onChange',
|
}),
|
||||||
},
|
|
||||||
),
|
|
||||||
mapReadPretty((props) => {
|
mapReadPretty((props) => {
|
||||||
if (props.value) {
|
if (props.value) {
|
||||||
return <CheckOutlined style={{ color: '#52c41a' }} />;
|
return <CheckOutlined style={{ color: '#52c41a' }} />;
|
||||||
@ -36,21 +35,18 @@ Checkbox.__ANT_CHECKBOX = true;
|
|||||||
|
|
||||||
Checkbox.Group = connect(
|
Checkbox.Group = connect(
|
||||||
AntdCheckbox.Group,
|
AntdCheckbox.Group,
|
||||||
mapProps(
|
mapProps({
|
||||||
{
|
dataSource: 'options',
|
||||||
dataSource: 'options',
|
}),
|
||||||
},
|
|
||||||
),
|
|
||||||
mapReadPretty((props) => {
|
mapReadPretty((props) => {
|
||||||
if (!isValid(props.value)) {
|
if (!isValid(props.value)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const { options = [] } = props;
|
|
||||||
const field = useField<any>();
|
const field = useField<any>();
|
||||||
const dataSource = field.dataSource || [];
|
const dataSource = field.dataSource || [];
|
||||||
const value = uniq(field.value ? field.value : []);
|
const value = uniq(field.value ? field.value : []);
|
||||||
return (
|
return (
|
||||||
<div>
|
<EllipsisWithTooltip ellipsis={props.ellipsis}>
|
||||||
{dataSource
|
{dataSource
|
||||||
.filter((option) => value.includes(option.value))
|
.filter((option) => value.includes(option.value))
|
||||||
.map((option, key) => (
|
.map((option, key) => (
|
||||||
@ -58,7 +54,7 @@ Checkbox.Group = connect(
|
|||||||
{option.label}
|
{option.label}
|
||||||
</Tag>
|
</Tag>
|
||||||
))}
|
))}
|
||||||
</div>
|
</EllipsisWithTooltip>
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
import { Popover } from 'antd';
|
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 = {
|
const ellipsisDefaultStyle: CSSProperties = {
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
overflowWrap: 'break-word',
|
overflowWrap: 'break-word',
|
||||||
@ -14,9 +22,11 @@ interface IEllipsisWithTooltipProps {
|
|||||||
popoverContent: unknown;
|
popoverContent: unknown;
|
||||||
children: any;
|
children: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EllipsisWithTooltip = forwardRef((props: Partial<IEllipsisWithTooltipProps>, ref: any) => {
|
export const EllipsisWithTooltip = forwardRef((props: Partial<IEllipsisWithTooltipProps>, ref: any) => {
|
||||||
const [ellipsis, setEllipsis] = useState(false);
|
const [ellipsis, setEllipsis] = useState(false);
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
|
const elRef: any = useRef();
|
||||||
useImperativeHandle(ref, () => {
|
useImperativeHandle(ref, () => {
|
||||||
return {
|
return {
|
||||||
setPopoverVisible: setVisible,
|
setPopoverVisible: setVisible,
|
||||||
@ -26,6 +36,13 @@ export const EllipsisWithTooltip = forwardRef((props: Partial<IEllipsisWithToolt
|
|||||||
return <>{props.children}</>;
|
return <>{props.children}</>;
|
||||||
}
|
}
|
||||||
const { popoverContent } = props;
|
const { popoverContent } = props;
|
||||||
|
|
||||||
|
const isOverflowTooltip = () => {
|
||||||
|
const contentWidth = getContentWidth(elRef.current);
|
||||||
|
const offsetWidth = elRef.current?.offsetWidth;
|
||||||
|
return contentWidth > offsetWidth;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover
|
||||||
visible={ellipsis && visible}
|
visible={ellipsis && visible}
|
||||||
@ -44,10 +61,14 @@ export const EllipsisWithTooltip = forwardRef((props: Partial<IEllipsisWithToolt
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
ref={elRef}
|
||||||
style={{ ...ellipsisDefaultStyle }}
|
style={{ ...ellipsisDefaultStyle }}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
const el = e.target as any;
|
const el = e.target as any;
|
||||||
setEllipsis(el.scrollWidth > el.clientWidth);
|
const isShowTooltips = isOverflowTooltip();
|
||||||
|
if (isShowTooltips) {
|
||||||
|
setEllipsis(el.scrollWidth >= el.clientWidth);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
@ -5,6 +5,7 @@ import { Tag } from 'antd';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useCompile } from '../../hooks';
|
import { useCompile } from '../../hooks';
|
||||||
import { defaultFieldNames, getCurrentOptions } from './shared';
|
import { defaultFieldNames, getCurrentOptions } from './shared';
|
||||||
|
import { EllipsisWithTooltip } from '../input/EllipsisWithTooltip';
|
||||||
|
|
||||||
type Composed = {
|
type Composed = {
|
||||||
Select?: React.FC<any>;
|
Select?: React.FC<any>;
|
||||||
@ -24,13 +25,16 @@ export const ReadPretty = observer((props: any) => {
|
|||||||
}
|
}
|
||||||
const dataSource = field.dataSource || props.options || [];
|
const dataSource = field.dataSource || props.options || [];
|
||||||
const options = getCurrentOptions(field.value, dataSource, fieldNames);
|
const options = getCurrentOptions(field.value, dataSource, fieldNames);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{options.map((option, key) => (
|
<EllipsisWithTooltip ellipsis={props.ellipsis}>
|
||||||
<Tag key={key} color={option[fieldNames.color]} icon={option.icon}>
|
{options.map((option, key) => (
|
||||||
{compile(option[fieldNames.label])}
|
<Tag key={key} color={option[fieldNames.color]} icon={option.icon}>
|
||||||
</Tag>
|
{compile(option[fieldNames.label])}
|
||||||
))}
|
</Tag>
|
||||||
|
))}
|
||||||
|
</EllipsisWithTooltip>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user