mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-06 06:08:07 +08:00
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 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;
|
||||
|
@ -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;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -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>
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user