fix(client): ellipsis with tooltip
This commit is contained in:
		
							parent
							
								
									d7a9608663
								
							
						
					
					
						commit
						60a915b50c
					
				@ -10,7 +10,7 @@ import { useCollectionField } from './hooks';
 | 
			
		||||
const InternalField: React.FC = (props) => {
 | 
			
		||||
  const field = useField<Field>();
 | 
			
		||||
  const fieldSchema = useFieldSchema();
 | 
			
		||||
  const { uiSchema } = useCollectionField();
 | 
			
		||||
  const { name, uiSchema } = useCollectionField();
 | 
			
		||||
  const component = useComponent(uiSchema?.['x-component']);
 | 
			
		||||
  const compile = useCompile();
 | 
			
		||||
  const setFieldProps = (key, value) => {
 | 
			
		||||
@ -34,9 +34,10 @@ const InternalField: React.FC = (props) => {
 | 
			
		||||
    setRequired();
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    field.dataSource = uiSchema.enum;
 | 
			
		||||
    const originalProps = compile(uiSchema['x-component-props']);
 | 
			
		||||
    const componentProps = field.componentProps;
 | 
			
		||||
    field.component = [component, merge(originalProps, componentProps)];
 | 
			
		||||
    const originalProps = compile(uiSchema['x-component-props']) || {};
 | 
			
		||||
    const componentProps = merge(originalProps, field.componentProps || {});
 | 
			
		||||
    field.component = [component, componentProps];
 | 
			
		||||
    // console.log('componentProps', uiSchema?.title, field.componentProps);
 | 
			
		||||
  }, [uiSchema?.title, uiSchema?.description, uiSchema?.required]);
 | 
			
		||||
  if (!uiSchema) {
 | 
			
		||||
    return null;
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
@ -1,9 +1,8 @@
 | 
			
		||||
import { usePrefixCls } from '@formily/antd/lib/__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';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { EllipsisWithTooltip } from './EllipsisWithTooltip';
 | 
			
		||||
 | 
			
		||||
type Composed = {
 | 
			
		||||
  Input: React.FC<InputProps & { ellipsis?: any }>;
 | 
			
		||||
@ -15,25 +14,11 @@ 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>
 | 
			
		||||
      <EllipsisWithTooltip ellipsis={props.ellipsis}>{props.value}</EllipsisWithTooltip>
 | 
			
		||||
      {props.suffix}
 | 
			
		||||
      {props.addonAfter}
 | 
			
		||||
    </div>
 | 
			
		||||
@ -41,32 +26,13 @@ ReadPretty.Input = (props) => {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ReadPretty.TextArea = (props) => {
 | 
			
		||||
  console.log('EllipsisWithTooltip', props.ellipsis);
 | 
			
		||||
  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>
 | 
			
		||||
      <EllipsisWithTooltip ellipsis={props.ellipsis}>{props.value}</EllipsisWithTooltip>
 | 
			
		||||
      {props.suffix}
 | 
			
		||||
      {props.addonAfter}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@ -87,6 +87,20 @@ export const components = {
 | 
			
		||||
    row: (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 (
 | 
			
		||||
    <div>
 | 
			
		||||
    <div
 | 
			
		||||
      className={css`
 | 
			
		||||
        .ant-table {
 | 
			
		||||
          overflow-x: auto;
 | 
			
		||||
          overflow-y: hidden;
 | 
			
		||||
        }
 | 
			
		||||
      `}
 | 
			
		||||
    >
 | 
			
		||||
      <ReactDragListView
 | 
			
		||||
        handleSelector={'.drag-handle'}
 | 
			
		||||
        onDragEnd={async (fromIndex, toIndex) => {
 | 
			
		||||
 | 
			
		||||
@ -61,6 +61,28 @@ export const useTableColumnInitializerFields = () => {
 | 
			
		||||
  return fields
 | 
			
		||||
    .filter((field) => field?.interface && field?.interface !== 'subTable')
 | 
			
		||||
    .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) {
 | 
			
		||||
        return {
 | 
			
		||||
          field,
 | 
			
		||||
@ -73,13 +95,12 @@ export const useTableColumnInitializerFields = () => {
 | 
			
		||||
            name: field.name,
 | 
			
		||||
            'x-collection-field': `${name}.${field.name}`,
 | 
			
		||||
            'x-component': 'CollectionField',
 | 
			
		||||
            'x-component-props': {
 | 
			
		||||
              ...componentProps,
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        } as SchemaInitializerItemOptions;
 | 
			
		||||
      }
 | 
			
		||||
      const componentProps = {};
 | 
			
		||||
      if (field.interface === 'attachment') {
 | 
			
		||||
        componentProps['size'] = 'small';
 | 
			
		||||
      }
 | 
			
		||||
      return {
 | 
			
		||||
        type: 'item',
 | 
			
		||||
        title: field?.uiSchema?.title || field.name,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user