feat: typography add enterEnterIcon triggerType
parent
f1384d16a5
commit
e777bc1743
|
@ -52,6 +52,7 @@ export interface EditConfig {
|
||||||
onEnd?: () => void;
|
onEnd?: () => void;
|
||||||
maxlength?: number;
|
maxlength?: number;
|
||||||
autoSize?: boolean | AutoSizeType;
|
autoSize?: boolean | AutoSizeType;
|
||||||
|
triggerType?: ('icon' | 'text')[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EllipsisConfig {
|
export interface EllipsisConfig {
|
||||||
|
@ -99,7 +100,7 @@ const Base = defineComponent<InternalBlockProps>({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
emits: ['update:content'],
|
emits: ['update:content'],
|
||||||
setup(props, { slots, attrs, emit }) {
|
setup(props, { slots, attrs, emit }) {
|
||||||
const { prefixCls } = useConfigInject('typography', props);
|
const { prefixCls, direction } = useConfigInject('typography', props);
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
edit: false,
|
edit: false,
|
||||||
|
@ -362,12 +363,12 @@ const Base = defineComponent<InternalBlockProps>({
|
||||||
function renderEdit() {
|
function renderEdit() {
|
||||||
if (!props.editable) return;
|
if (!props.editable) return;
|
||||||
|
|
||||||
const { tooltip } = props.editable as EditConfig;
|
const { tooltip, triggerType = ['icon'] } = props.editable as EditConfig;
|
||||||
const icon = slots.editableIcon ? slots.editableIcon() : <EditOutlined role="button" />;
|
const icon = slots.editableIcon ? slots.editableIcon() : <EditOutlined role="button" />;
|
||||||
const title = slots.editableTooltip ? slots.editableTooltip() : state.editStr;
|
const title = slots.editableTooltip ? slots.editableTooltip() : state.editStr;
|
||||||
const ariaLabel = typeof title === 'string' ? title : '';
|
const ariaLabel = typeof title === 'string' ? title : '';
|
||||||
|
|
||||||
return (
|
return triggerType.indexOf('icon') !== -1 ? (
|
||||||
<Tooltip key="edit" title={tooltip === false ? '' : title}>
|
<Tooltip key="edit" title={tooltip === false ? '' : title}>
|
||||||
<TransButton
|
<TransButton
|
||||||
ref={editIcon}
|
ref={editIcon}
|
||||||
|
@ -378,7 +379,7 @@ const Base = defineComponent<InternalBlockProps>({
|
||||||
{icon}
|
{icon}
|
||||||
</TransButton>
|
</TransButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderCopy() {
|
function renderCopy() {
|
||||||
|
@ -428,6 +429,8 @@ const Base = defineComponent<InternalBlockProps>({
|
||||||
onChange={onContentChange}
|
onChange={onContentChange}
|
||||||
onCancel={onEditCancel}
|
onCancel={onEditCancel}
|
||||||
onEnd={onEnd}
|
onEnd={onEnd}
|
||||||
|
direction={direction.value}
|
||||||
|
v-slots={{ enterIcon: slots.editableEnterIcon }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -437,7 +440,7 @@ const Base = defineComponent<InternalBlockProps>({
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const { editing } = editable.value;
|
const { editing, triggerType = ['icon'] } = editable.value;
|
||||||
const children =
|
const children =
|
||||||
props.ellipsis || props.editable
|
props.ellipsis || props.editable
|
||||||
? props.content !== undefined
|
? props.content !== undefined
|
||||||
|
@ -538,7 +541,7 @@ const Base = defineComponent<InternalBlockProps>({
|
||||||
[`${prefixCls.value}-${type}`]: type,
|
[`${prefixCls.value}-${type}`]: type,
|
||||||
[`${prefixCls.value}-disabled`]: disabled,
|
[`${prefixCls.value}-disabled`]: disabled,
|
||||||
[`${prefixCls.value}-ellipsis`]: rows,
|
[`${prefixCls.value}-ellipsis`]: rows,
|
||||||
[`${prefixCls.value}-single-line`]: rows === 1,
|
[`${prefixCls.value}-single-line`]: rows === 1 && !state.isEllipsis,
|
||||||
[`${prefixCls.value}-ellipsis-single-line`]: cssTextOverflow,
|
[`${prefixCls.value}-ellipsis-single-line`]: cssTextOverflow,
|
||||||
[`${prefixCls.value}-ellipsis-multiple-line`]: cssLineClamp,
|
[`${prefixCls.value}-ellipsis-multiple-line`]: cssLineClamp,
|
||||||
},
|
},
|
||||||
|
@ -549,6 +552,8 @@ const Base = defineComponent<InternalBlockProps>({
|
||||||
WebkitLineClamp: cssLineClamp ? rows : undefined,
|
WebkitLineClamp: cssLineClamp ? rows : undefined,
|
||||||
}}
|
}}
|
||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
|
direction={direction.value}
|
||||||
|
onClick={triggerType.indexOf('text') !== -1 ? onEditClick : () => {}}
|
||||||
{...textProps}
|
{...textProps}
|
||||||
>
|
>
|
||||||
{showTooltip ? (
|
{showTooltip ? (
|
||||||
|
|
|
@ -2,7 +2,9 @@ import KeyCode from '../_util/KeyCode';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import TextArea from '../input/TextArea';
|
import TextArea from '../input/TextArea';
|
||||||
import EnterOutlined from '@ant-design/icons-vue/EnterOutlined';
|
import EnterOutlined from '@ant-design/icons-vue/EnterOutlined';
|
||||||
import { defineComponent, ref, reactive, watch, onMounted } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
|
import { defineComponent, ref, reactive, watch, onMounted, computed } from 'vue';
|
||||||
|
import type { Direction } from '../config-provider';
|
||||||
|
|
||||||
const Editable = defineComponent({
|
const Editable = defineComponent({
|
||||||
name: 'Editable',
|
name: 'Editable',
|
||||||
|
@ -16,9 +18,10 @@ const Editable = defineComponent({
|
||||||
onEnd: PropTypes.func,
|
onEnd: PropTypes.func,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
originContent: PropTypes.string,
|
originContent: PropTypes.string,
|
||||||
|
direction: String as PropType<Direction>,
|
||||||
},
|
},
|
||||||
emits: ['save', 'cancel', 'end', 'change'],
|
emits: ['save', 'cancel', 'end', 'change'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit, slots }) {
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
current: props.value || '',
|
current: props.value || '',
|
||||||
lastKeyCode: undefined,
|
lastKeyCode: undefined,
|
||||||
|
@ -102,9 +105,13 @@ const Editable = defineComponent({
|
||||||
function confirmChange() {
|
function confirmChange() {
|
||||||
emit('save', state.current.trim());
|
emit('save', state.current.trim());
|
||||||
}
|
}
|
||||||
|
const textAreaClassName = computed(() => ({
|
||||||
|
[`${props.prefixCls}`]: true,
|
||||||
|
[`${props.prefixCls}-edit-content`]: true,
|
||||||
|
[`${props.prefixCls}-rtl`]: props.direction === 'rtl',
|
||||||
|
}));
|
||||||
return () => (
|
return () => (
|
||||||
<div class={`${props.prefixCls} ${props.prefixCls}-edit-content`}>
|
<div class={textAreaClassName.value}>
|
||||||
<TextArea
|
<TextArea
|
||||||
ref={saveTextAreaRef}
|
ref={saveTextAreaRef}
|
||||||
maxlength={props.maxlength}
|
maxlength={props.maxlength}
|
||||||
|
@ -117,7 +124,11 @@ const Editable = defineComponent({
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
autoSize={props.autoSize === undefined || props.autoSize}
|
autoSize={props.autoSize === undefined || props.autoSize}
|
||||||
/>
|
/>
|
||||||
<EnterOutlined class={`${props.prefixCls}-edit-content-confirm`} />
|
{slots.enterIcon ? (
|
||||||
|
slots.enterIcon({ className: `${props.prefixCls}-edit-content-confirm` })
|
||||||
|
) : (
|
||||||
|
<EnterOutlined class={`${props.prefixCls}-edit-content-confirm`} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,8 +3,10 @@ import type { HTMLAttributes } from 'vue';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import useConfigInject from '../_util/hooks/useConfigInject';
|
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||||
import classNames from '../_util/classNames';
|
import classNames from '../_util/classNames';
|
||||||
|
import type { Direction } from '../config-provider';
|
||||||
|
|
||||||
export interface TypographyProps extends HTMLAttributes {
|
export interface TypographyProps extends HTMLAttributes {
|
||||||
|
direction?: Direction;
|
||||||
prefixCls?: string;
|
prefixCls?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,16 +18,24 @@ const Typography = defineComponent<InternalTypographyProps>({
|
||||||
name: 'ATypography',
|
name: 'ATypography',
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
setup(props, { slots, attrs }) {
|
setup(props, { slots, attrs }) {
|
||||||
const { prefixCls } = useConfigInject('typography', props);
|
const { prefixCls, direction } = useConfigInject('typography', props);
|
||||||
return () => {
|
return () => {
|
||||||
const {
|
const {
|
||||||
prefixCls: _prefixCls,
|
prefixCls: _prefixCls,
|
||||||
class: _className,
|
class: _className,
|
||||||
|
direction: _direction,
|
||||||
component: Component = 'article' as any,
|
component: Component = 'article' as any,
|
||||||
...restProps
|
...restProps
|
||||||
} = { ...props, ...attrs };
|
} = { ...props, ...attrs };
|
||||||
return (
|
return (
|
||||||
<Component class={classNames(prefixCls.value, attrs.class)} {...restProps}>
|
<Component
|
||||||
|
class={classNames(
|
||||||
|
prefixCls.value,
|
||||||
|
{ [`${prefixCls.value}-rtl`]: direction.value === 'rtl' },
|
||||||
|
attrs.class,
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
{slots.default?.()}
|
{slots.default?.()}
|
||||||
</Component>
|
</Component>
|
||||||
);
|
);
|
||||||
|
|
|
@ -68,7 +68,9 @@ exports[`renders ./components/typography/demo/basic.vue correctly 1`] = `
|
||||||
|
|
||||||
exports[`renders ./components/typography/demo/ellipsis.vue correctly 1`] = `
|
exports[`renders ./components/typography/demo/ellipsis.vue correctly 1`] = `
|
||||||
<button type="button" role="switch" aria-checked="true" class="ant-switch-checked ant-switch">
|
<button type="button" role="switch" aria-checked="true" class="ant-switch-checked ant-switch">
|
||||||
<!----><span class="ant-switch-inner"><!----></span>
|
<div class="ant-switch-handle">
|
||||||
|
<!---->
|
||||||
|
</div><span class="ant-switch-inner"><!----></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="ant-typography ant-typography-ellipsis ant-typography-single-line ant-typography-ellipsis-single-line"> Ant Design, a design language for background applications, is refined by Ant UED Team. Ant
|
<div class="ant-typography ant-typography-ellipsis ant-typography-single-line ant-typography-ellipsis-single-line"> Ant Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||||
|
@ -78,15 +80,14 @@ exports[`renders ./components/typography/demo/ellipsis.vue correctly 1`] = `
|
||||||
Design, a design language for background applications, is refined by Ant UED Team.
|
Design, a design language for background applications, is refined by Ant UED Team.
|
||||||
<!---->
|
<!---->
|
||||||
</div>
|
</div>
|
||||||
<div class="ant-typography ant-typography-ellipsis"><span title="Ant Design, a design language for background applications, is refined by Ant UED Team. Ant
|
<div class="ant-typography ant-typography-ellipsis">Ant Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||||
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
Design, a design language for background applications, is refined by Ant UED Team. Ant
|
||||||
Design, a design language for background applications, is refined by Ant UED Team." aria-hidden="true">...</span>
|
Design, a design language for background applications, is refined by Ant UED Team.
|
||||||
<!----><a class="ant-typography-expand" aria-label="Expand">more</a>
|
<!---->
|
||||||
</div><span class="ant-typography ant-typography-ellipsis ant-typography-single-line" style="width: 100px;"><!----><span><span title="Ant Design, a design language for background applications, is refined by Ant UED Team." aria-hidden="true">...</span>
|
</div><span class="ant-typography ant-typography-ellipsis ant-typography-single-line" style="width: 100px;">Ant Design, a design language for background applications, is refined by Ant UED Team.<!----></span>
|
||||||
<!----></span></span>
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/typography/demo/interactive.vue correctly 1`] = `
|
exports[`renders ./components/typography/demo/interactive.vue correctly 1`] = `
|
||||||
|
@ -99,6 +100,21 @@ exports[`renders ./components/typography/demo/interactive.vue correctly 1`] = `
|
||||||
<!---->
|
<!---->
|
||||||
<!---->
|
<!---->
|
||||||
<div role="button" tabindex="0" class="ant-typography-edit" aria-label="" style="padding: 0px; line-height: inherit; display: inline-block; border: 0px; background: transparent;"><span role="img" aria-label="highlight" class="anticon anticon-highlight"><svg focusable="false" class="" data-icon="highlight" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M957.6 507.4L603.2 158.2a7.9 7.9 0 00-11.2 0L353.3 393.4a8.03 8.03 0 00-.1 11.3l.1.1 40 39.4-117.2 115.3a8.03 8.03 0 00-.1 11.3l.1.1 39.5 38.9-189.1 187H72.1c-4.4 0-8.1 3.6-8.1 8V860c0 4.4 3.6 8 8 8h344.9c2.1 0 4.1-.8 5.6-2.3l76.1-75.6 40.4 39.8a7.9 7.9 0 0011.2 0l117.1-115.6 40.1 39.5a7.9 7.9 0 0011.2 0l238.7-235.2c3.4-3 3.4-8 .3-11.2zM389.8 796.2H229.6l134.4-133 80.1 78.9-54.3 54.1zm154.8-62.1L373.2 565.2l68.6-67.6 171.4 168.9-68.6 67.6zM713.1 658L450.3 399.1 597.6 254l262.8 259-147.3 145z"></path></svg></span></div>
|
<div role="button" tabindex="0" class="ant-typography-edit" aria-label="" style="padding: 0px; line-height: inherit; display: inline-block; border: 0px; background: transparent;"><span role="img" aria-label="highlight" class="anticon anticon-highlight"><svg focusable="false" class="" data-icon="highlight" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M957.6 507.4L603.2 158.2a7.9 7.9 0 00-11.2 0L353.3 393.4a8.03 8.03 0 00-.1 11.3l.1.1 40 39.4-117.2 115.3a8.03 8.03 0 00-.1 11.3l.1.1 39.5 38.9-189.1 187H72.1c-4.4 0-8.1 3.6-8.1 8V860c0 4.4 3.6 8 8 8h344.9c2.1 0 4.1-.8 5.6-2.3l76.1-75.6 40.4 39.8a7.9 7.9 0 0011.2 0l117.1-115.6 40.1 39.5a7.9 7.9 0 0011.2 0l238.7-235.2c3.4-3 3.4-8 .3-11.2zM389.8 796.2H229.6l134.4-133 80.1 78.9-54.3 54.1zm154.8-62.1L373.2 565.2l68.6-67.6 171.4 168.9-68.6 67.6zM713.1 658L450.3 399.1 597.6 254l262.8 259-147.3 145z"></path></svg></span></div>
|
||||||
|
</div> Trigger edit with: <div class="ant-radio-group ant-radio-group-outline ant-radio-group-default"><label class="ant-radio-wrapper ant-radio-wrapper-checked"><span class="ant-radio ant-radio-checked"><input type="radio" class="ant-radio-input" value="icon"><span class="ant-radio-inner"></span></span><span>icon</span></label><label class="ant-radio-wrapper"><span class="ant-radio"><input type="radio" class="ant-radio-input" value="text"><span class="ant-radio-inner"></span></span><span>text</span></label><label class="ant-radio-wrapper"><span class="ant-radio"><input type="radio" class="ant-radio-input" value="both"><span class="ant-radio-inner"></span></span><span>both</span></label></div>
|
||||||
|
<div class="ant-typography">Text or icon as trigger - click to start editing.
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
<div role="button" tabindex="0" class="ant-typography-edit" aria-label="" style="padding: 0px; line-height: inherit; display: inline-block; border: 0px; background: transparent;"><span role="img" aria-label="edit" class="anticon anticon-edit"><svg focusable="false" class="" data-icon="edit" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M257.7 752c2 0 4-.2 6-.5L431.9 722c2-.4 3.9-1.3 5.3-2.8l423.9-423.9a9.96 9.96 0 000-14.1L694.9 114.9c-1.9-1.9-4.4-2.9-7.1-2.9s-5.2 1-7.1 2.9L256.8 538.8c-1.5 1.5-2.4 3.3-2.8 5.3l-29.5 168.2a33.5 33.5 0 009.4 29.8c6.6 6.4 14.9 9.9 23.8 9.9zm67.4-174.4L687.8 215l73.3 73.3-362.7 362.6-88.9 15.7 15.6-89zM880 836H144c-17.7 0-32 14.3-32 32v36c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-36c0-17.7-14.3-32-32-32z"></path></svg></span></div>
|
||||||
|
</div>
|
||||||
|
<div class="ant-typography">Editable text with a custom enter icon in edit field.
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
<div role="button" tabindex="0" class="ant-typography-edit" aria-label="" style="padding: 0px; line-height: inherit; display: inline-block; border: 0px; background: transparent;"><span role="img" aria-label="highlight" class="anticon anticon-highlight"><svg focusable="false" class="" data-icon="highlight" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M957.6 507.4L603.2 158.2a7.9 7.9 0 00-11.2 0L353.3 393.4a8.03 8.03 0 00-.1 11.3l.1.1 40 39.4-117.2 115.3a8.03 8.03 0 00-.1 11.3l.1.1 39.5 38.9-189.1 187H72.1c-4.4 0-8.1 3.6-8.1 8V860c0 4.4 3.6 8 8 8h344.9c2.1 0 4.1-.8 5.6-2.3l76.1-75.6 40.4 39.8a7.9 7.9 0 0011.2 0l117.1-115.6 40.1 39.5a7.9 7.9 0 0011.2 0l238.7-235.2c3.4-3 3.4-8 .3-11.2zM389.8 796.2H229.6l134.4-133 80.1 78.9-54.3 54.1zm154.8-62.1L373.2 565.2l68.6-67.6 171.4 168.9-68.6 67.6zM713.1 658L450.3 399.1 597.6 254l262.8 259-147.3 145z"></path></svg></span></div>
|
||||||
|
</div>
|
||||||
|
<div class="ant-typography">Editable text with no enter icon in edit field.
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
<div role="button" tabindex="0" class="ant-typography-edit" aria-label="" style="padding: 0px; line-height: inherit; display: inline-block; border: 0px; background: transparent;"><span role="img" aria-label="highlight" class="anticon anticon-highlight"><svg focusable="false" class="" data-icon="highlight" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M957.6 507.4L603.2 158.2a7.9 7.9 0 00-11.2 0L353.3 393.4a8.03 8.03 0 00-.1 11.3l.1.1 40 39.4-117.2 115.3a8.03 8.03 0 00-.1 11.3l.1.1 39.5 38.9-189.1 187H72.1c-4.4 0-8.1 3.6-8.1 8V860c0 4.4 3.6 8 8 8h344.9c2.1 0 4.1-.8 5.6-2.3l76.1-75.6 40.4 39.8a7.9 7.9 0 0011.2 0l117.1-115.6 40.1 39.5a7.9 7.9 0 0011.2 0l238.7-235.2c3.4-3 3.4-8 .3-11.2zM389.8 796.2H229.6l134.4-133 80.1 78.9-54.3 54.1zm154.8-62.1L373.2 565.2l68.6-67.6 171.4 168.9-68.6 67.6zM713.1 658L450.3 399.1 597.6 254l262.8 259-147.3 145z"></path></svg></span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ant-typography">Hide Edit tooltip.
|
<div class="ant-typography">Hide Edit tooltip.
|
||||||
<!---->
|
<!---->
|
||||||
|
@ -141,7 +157,7 @@ exports[`renders ./components/typography/demo/suffix.vue correctly 1`] = `
|
||||||
<div class="ant-slider-handle" style="left: 0%; transform: translateX(-50%);" role="slider" tabindex="0" aria-valuemin="1" aria-valuemax="10" aria-valuenow="1" aria-disabled="false"></div>
|
<div class="ant-slider-handle" style="left: 0%; transform: translateX(-50%);" role="slider" tabindex="0" aria-valuemin="1" aria-valuemax="10" aria-valuenow="1" aria-disabled="false"></div>
|
||||||
<div class="ant-slider-mark"></div>
|
<div class="ant-slider-mark"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ant-typography ant-typography-ellipsis ant-typography-single-line" title="To be, or not to be, that is a question: Whether it is nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them? To die: to sleep; No more; and by a sleep to say we end The heart-ache and the thousand natural shocks That flesh is heir to, 'tis a consummation Devoutly to be wish'd. To die, to sleep To sleep- perchance to dream: ay, there's the rub! For in that sleep of death what dreams may come When we have shuffled off this mortal coil, Must give us pause. There 's the respect That makes calamity of so long life--William Shakespeare"><span title="To be, or not to be, that is a question: Whether it is nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them? To die: to sleep; No more; and by a sleep to say we end The heart-ache and the thousand natural shocks That flesh is heir to, 'tis a consummation Devoutly to be wish'd. To die, to sleep To sleep- perchance to dream: ay, there's the rub! For in that sleep of death what dreams may come When we have shuffled off this mortal coil, Must give us pause. There 's the respect That makes calamity of so long life--William Shakespeare" aria-hidden="true">...</span>--William Shakespeare<a class="ant-typography-expand" aria-label="Expand">Expand</a></div>
|
<div class="ant-typography ant-typography-ellipsis ant-typography-single-line" title="To be, or not to be, that is a question: Whether it is nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them? To die: to sleep; No more; and by a sleep to say we end The heart-ache and the thousand natural shocks That flesh is heir to, 'tis a consummation Devoutly to be wish'd. To die, to sleep To sleep- perchance to dream: ay, there's the rub! For in that sleep of death what dreams may come When we have shuffled off this mortal coil, Must give us pause. There 's the respect That makes calamity of so long life--William Shakespeare">To be, or not to be, that is a question: Whether it is nobler in the mind to suffer. The slings and arrows of outrageous fortune Or to take arms against a sea of troubles, And by opposing end them? To die: to sleep; No more; and by a sleep to say we end The heart-ache and the thousand natural shocks That flesh is heir to, 'tis a consummation Devoutly to be wish'd. To die, to sleep To sleep- perchance to dream: ay, there's the rub! For in that sleep of death what dreams may come When we have shuffled off this mortal coil, Must give us pause. There 's the respect That makes calamity of so long life--William Shakespeare</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`renders ./components/typography/demo/text.vue correctly 1`] = `
|
exports[`renders ./components/typography/demo/text.vue correctly 1`] = `
|
||||||
|
|
|
@ -18,19 +18,27 @@ describe('Typography', () => {
|
||||||
|
|
||||||
const LINE_STR_COUNT = 20;
|
const LINE_STR_COUNT = 20;
|
||||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
|
|
||||||
// Mock offsetHeight
|
// Mock offsetHeight
|
||||||
const originOffsetHeight = Object.getOwnPropertyDescriptor(
|
const originOffsetHeight = Object.getOwnPropertyDescriptor(
|
||||||
HTMLElement.prototype,
|
HTMLElement.prototype,
|
||||||
'offsetHeight',
|
'offsetHeight',
|
||||||
).get;
|
).get;
|
||||||
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {
|
const mockGetBoundingClientRect = jest.spyOn(HTMLElement.prototype, 'getBoundingClientRect');
|
||||||
get() {
|
beforeAll(() => {
|
||||||
|
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {
|
||||||
|
get() {
|
||||||
|
let html = this.innerHTML;
|
||||||
|
html = html.replace(/<[^>]*>/g, '');
|
||||||
|
const lines = Math.ceil(html.length / LINE_STR_COUNT);
|
||||||
|
return lines * 16;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
mockGetBoundingClientRect.mockImplementation(function fn() {
|
||||||
let html = this.innerHTML;
|
let html = this.innerHTML;
|
||||||
html = html.replace(/<[^>]*>/g, '');
|
html = html.replace(/<[^>]*>/g, '');
|
||||||
const lines = Math.ceil(html.length / LINE_STR_COUNT);
|
const lines = Math.ceil(html.length / LINE_STR_COUNT);
|
||||||
return lines * 16;
|
return { height: lines * 16 };
|
||||||
},
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mock getComputedStyle
|
// Mock getComputedStyle
|
||||||
|
|
|
@ -20,6 +20,33 @@ Provide additional interactive capacity of editable and copyable.
|
||||||
<template #editableIcon><HighlightOutlined /></template>
|
<template #editableIcon><HighlightOutlined /></template>
|
||||||
<template #editableTooltip>click to edit text</template>
|
<template #editableTooltip>click to edit text</template>
|
||||||
</a-typography-paragraph>
|
</a-typography-paragraph>
|
||||||
|
Trigger edit with:
|
||||||
|
<a-radio-group
|
||||||
|
:value="stateToRadio()"
|
||||||
|
@change="e => (chooseTrigger = radioToState(e.target.value))"
|
||||||
|
>
|
||||||
|
<a-radio value="icon">icon</a-radio>
|
||||||
|
<a-radio value="text">text</a-radio>
|
||||||
|
<a-radio value="both">both</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
<a-typography-paragraph
|
||||||
|
v-model:content="clickTriggerStr"
|
||||||
|
:editable="{ triggerType: chooseTrigger }"
|
||||||
|
>
|
||||||
|
<template #editableTooltip>click to edit text</template>
|
||||||
|
</a-typography-paragraph>
|
||||||
|
<a-typography-paragraph v-model:content="customEnterIconStr" editable>
|
||||||
|
<template #editableIcon><HighlightOutlined /></template>
|
||||||
|
<template #editableTooltip>click to edit text</template>
|
||||||
|
<template #editableEnterIcon="{ className }">
|
||||||
|
<CheckOutlined :class="className" />
|
||||||
|
</template>
|
||||||
|
</a-typography-paragraph>
|
||||||
|
<a-typography-paragraph v-model:content="noEnterIconStr" editable>
|
||||||
|
<template #editableIcon><HighlightOutlined /></template>
|
||||||
|
<template #editableTooltip>click to edit text</template>
|
||||||
|
<template #editableEnterIcon>{{ null }}</template>
|
||||||
|
</a-typography-paragraph>
|
||||||
<a-typography-paragraph v-model:content="hideTooltipStr" :editable="{ tooltip: false }" />
|
<a-typography-paragraph v-model:content="hideTooltipStr" :editable="{ tooltip: false }" />
|
||||||
<a-typography-paragraph
|
<a-typography-paragraph
|
||||||
v-model:content="lengthLimitedStr"
|
v-model:content="lengthLimitedStr"
|
||||||
|
@ -46,24 +73,56 @@ Provide additional interactive capacity of editable and copyable.
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, watch } from 'vue';
|
import { defineComponent, ref, watch } from 'vue';
|
||||||
import { HighlightOutlined, SmileOutlined, SmileFilled } from '@ant-design/icons-vue';
|
import {
|
||||||
|
HighlightOutlined,
|
||||||
|
SmileOutlined,
|
||||||
|
SmileFilled,
|
||||||
|
CheckOutlined,
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
HighlightOutlined,
|
HighlightOutlined,
|
||||||
SmileOutlined,
|
SmileOutlined,
|
||||||
SmileFilled,
|
SmileFilled,
|
||||||
|
CheckOutlined,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const editableStr = ref('This is an editable text.');
|
const editableStr = ref('This is an editable text.');
|
||||||
watch(editableStr, () => {
|
watch(editableStr, () => {
|
||||||
console.log('editableStr', editableStr.value);
|
console.log('editableStr', editableStr.value);
|
||||||
});
|
});
|
||||||
|
const chooseTrigger = ref<('icon' | 'text')[]>(['icon']);
|
||||||
|
|
||||||
|
const radioToState = (input: string): ('icon' | 'text')[] => {
|
||||||
|
switch (input) {
|
||||||
|
case 'text':
|
||||||
|
return ['text'];
|
||||||
|
case 'both':
|
||||||
|
return ['icon', 'text'];
|
||||||
|
case 'icon':
|
||||||
|
default:
|
||||||
|
return ['icon'];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stateToRadio = () => {
|
||||||
|
if (chooseTrigger.value.indexOf('text') !== -1) {
|
||||||
|
return chooseTrigger.value.indexOf('icon') !== -1 ? 'both' : 'text';
|
||||||
|
}
|
||||||
|
return 'icon';
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
|
radioToState,
|
||||||
|
stateToRadio,
|
||||||
editableStr,
|
editableStr,
|
||||||
customIconStr: ref('Custom Edit icon and replace tooltip text.'),
|
customIconStr: ref('Custom Edit icon and replace tooltip text.'),
|
||||||
hideTooltipStr: ref('Hide Edit tooltip.'),
|
hideTooltipStr: ref('Hide Edit tooltip.'),
|
||||||
lengthLimitedStr: ref('This is an editable text with limited length.'),
|
lengthLimitedStr: ref('This is an editable text with limited length.'),
|
||||||
|
clickTriggerStr: ref('Text or icon as trigger - click to start editing.'),
|
||||||
|
chooseTrigger,
|
||||||
|
customEnterIconStr: ref('Editable text with a custom enter icon in edit field.'),
|
||||||
|
noEnterIconStr: ref('Editable text with no enter icon in edit field.'),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -69,6 +69,7 @@ Basic text writing, including headings, body text, lists, and more.
|
||||||
| Name | Description | Property | Default | Version |
|
| Name | Description | Property | Default | Version |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| editableIcon | Custom editable icon | - | <EditOutlined /> | |
|
| editableIcon | Custom editable icon | - | <EditOutlined /> | |
|
||||||
|
| editableEnterIcon | Custom "enter" icon in the edit field | `{className: string}` | `<EnterOutlined />` | 3.0 |
|
||||||
| editableTooltip | Custom tooltip text, hide when `editable.tooltip = false` | - | `Edit` | |
|
| editableTooltip | Custom tooltip text, hide when `editable.tooltip = false` | - | `Edit` | |
|
||||||
| copyableIcon | Custom copy icon | `{ copied: boolean }` | `copied ? <CheckOutlined /> : <CopyOutlined />` | |
|
| copyableIcon | Custom copy icon | `{ copied: boolean }` | `copied ? <CheckOutlined /> : <CopyOutlined />` | |
|
||||||
| copyableTooltip | Custom tooltip text, hide when `copyable.tooltip = false` | `{ copied: boolean }` | `copied ? 'Copied' : 'Copy'` | |
|
| copyableTooltip | Custom tooltip text, hide when `copyable.tooltip = false` | `{ copied: boolean }` | `copied ? 'Copied' : 'Copy'` | |
|
||||||
|
@ -103,6 +104,7 @@ Basic text writing, including headings, body text, lists, and more.
|
||||||
onChange: function(string),
|
onChange: function(string),
|
||||||
onCancel: function,
|
onCancel: function,
|
||||||
onEnd: function,
|
onEnd: function,
|
||||||
|
triggerType: ('icon' | 'text')[],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -118,6 +120,7 @@ Basic text writing, including headings, body text, lists, and more.
|
||||||
| onStart | Called when enter editable state | function | - | |
|
| onStart | Called when enter editable state | function | - | |
|
||||||
| onCancel | Called when type ESC to exit editable state | function | - | |
|
| onCancel | Called when type ESC to exit editable state | function | - | |
|
||||||
| onEnd | Called when type ENTER to exit editable state | function | - | |
|
| onEnd | Called when type ENTER to exit editable state | function | - | |
|
||||||
|
| triggerType | Edit mode trigger - icon, text or both (not specifying icon as trigger hides it) | Array<`icon`\|`text`> | \[`icon`] | |
|
||||||
|
|
||||||
### ellipsis
|
### ellipsis
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/GOM1KQ24O/Typography.svg
|
||||||
| 名称 | 说明 | 参数 | 默认值 | 版本 |
|
| 名称 | 说明 | 参数 | 默认值 | 版本 |
|
||||||
| --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- |
|
||||||
| editableIcon | 自定义编辑图标 | - | <EditOutlined /> | |
|
| editableIcon | 自定义编辑图标 | - | <EditOutlined /> | |
|
||||||
|
| enterEnterIcon | 在编辑段中自定义“enter”图标 | `{className: string}` | `<EnterOutlined />` | 3.0 |
|
||||||
| editableTooltip | 自定义提示文本,当 `editable.tooltip = false` 时关闭 | - | `编辑` | |
|
| editableTooltip | 自定义提示文本,当 `editable.tooltip = false` 时关闭 | - | `编辑` | |
|
||||||
| copyableIcon | 自定义拷贝图标 | `{ copied: boolean }` | `copied ? <CheckOutlined /> : <CopyOutlined />` | |
|
| copyableIcon | 自定义拷贝图标 | `{ copied: boolean }` | `copied ? <CheckOutlined /> : <CopyOutlined />` | |
|
||||||
| copyableTooltip | 自定义提示文案,当 `copyable.tooltip = false` 时关闭 | `{ copied: boolean }` | `copied ? '复制成功' : '复制'` | |
|
| copyableTooltip | 自定义提示文案,当 `copyable.tooltip = false` 时关闭 | `{ copied: boolean }` | `copied ? '复制成功' : '复制'` | |
|
||||||
|
@ -104,6 +105,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/GOM1KQ24O/Typography.svg
|
||||||
onChange: function(string),
|
onChange: function(string),
|
||||||
onCancel: function,
|
onCancel: function,
|
||||||
onEnd: function,
|
onEnd: function,
|
||||||
|
triggerType: ('icon' | 'text')[],
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -119,6 +121,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/GOM1KQ24O/Typography.svg
|
||||||
| onStart | 进入编辑中状态时触发 | function | - | |
|
| onStart | 进入编辑中状态时触发 | function | - | |
|
||||||
| onCancel | 按 ESC 退出编辑状态时触发 | function | - | |
|
| onCancel | 按 ESC 退出编辑状态时触发 | function | - | |
|
||||||
| onEnd | 按 ENTER 结束编辑状态时触发 | function | - | |
|
| onEnd | 按 ENTER 结束编辑状态时触发 | function | - | |
|
||||||
|
| triggerType | Edit mode trigger - icon, text or both (not specifying icon as trigger hides it) | Array<`icon`\|`text`> | \[`icon`] | |
|
||||||
|
|
||||||
### ellipsis
|
### ellipsis
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
&&-danger {
|
&&-danger {
|
||||||
color: @error-color;
|
color: @error-color;
|
||||||
|
|
||||||
a&:active,
|
a&:active,
|
||||||
a&:focus,
|
a&:focus,
|
||||||
a&:hover {
|
a&:hover {
|
||||||
|
@ -45,18 +46,22 @@
|
||||||
h1 {
|
h1 {
|
||||||
.typography-title-1();
|
.typography-title-1();
|
||||||
}
|
}
|
||||||
|
|
||||||
h2&,
|
h2&,
|
||||||
h2 {
|
h2 {
|
||||||
.typography-title-2();
|
.typography-title-2();
|
||||||
}
|
}
|
||||||
|
|
||||||
h3&,
|
h3&,
|
||||||
h3 {
|
h3 {
|
||||||
.typography-title-3();
|
.typography-title-3();
|
||||||
}
|
}
|
||||||
|
|
||||||
h4&,
|
h4&,
|
||||||
h4 {
|
h4 {
|
||||||
.typography-title-4();
|
.typography-title-4();
|
||||||
}
|
}
|
||||||
|
|
||||||
h5&,
|
h5&,
|
||||||
h5 {
|
h5 {
|
||||||
.typography-title-5();
|
.typography-title-5();
|
||||||
|
@ -93,6 +98,7 @@
|
||||||
a&-ellipsis,
|
a&-ellipsis,
|
||||||
span&-ellipsis {
|
span&-ellipsis {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
a&,
|
a&,
|
||||||
|
@ -184,7 +190,6 @@
|
||||||
div& {
|
div& {
|
||||||
left: -@input-padding-horizontal - 1px;
|
left: -@input-padding-horizontal - 1px;
|
||||||
margin-top: -@input-padding-vertical-base - 1px;
|
margin-top: -@input-padding-vertical-base - 1px;
|
||||||
// stylelint-disable-next-line function-calc-no-invalid
|
|
||||||
margin-bottom: calc(1em - @input-padding-vertical-base - 1px);
|
margin-bottom: calc(1em - @input-padding-vertical-base - 1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,6 +203,7 @@
|
||||||
|
|
||||||
// Fix Editable Textarea flash in Firefox
|
// Fix Editable Textarea flash in Firefox
|
||||||
textarea {
|
textarea {
|
||||||
|
/* stylelint-disable-next-line property-no-vendor-prefix */
|
||||||
-moz-transition: none;
|
-moz-transition: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,7 +211,7 @@
|
||||||
// list
|
// list
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
margin: 0 0 1em 0;
|
margin: 0 0 1em;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
@ -275,9 +281,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&-ellipsis-multiple-line {
|
&-ellipsis-multiple-line {
|
||||||
|
/* stylelint-disable-next-line value-no-vendor-prefix */
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-line-clamp: 3;
|
-webkit-line-clamp: 3;
|
||||||
|
|
||||||
/*! autoprefixer: ignore next */
|
/*! autoprefixer: ignore next */
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,6 @@ const wrapperStyle: CSSProperties = {
|
||||||
lineHeight: 'inherit',
|
lineHeight: 'inherit',
|
||||||
};
|
};
|
||||||
|
|
||||||
function pxToNumber(value: string | null) {
|
|
||||||
if (!value) return 0;
|
|
||||||
|
|
||||||
const match = value.match(/^\d*(\.\d*)?/);
|
|
||||||
|
|
||||||
return match ? Number(match[0]) : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function styleToString(style: CSSStyleDeclaration) {
|
function styleToString(style: CSSStyleDeclaration) {
|
||||||
// There are some different behavior between Firefox & Chrome.
|
// There are some different behavior between Firefox & Chrome.
|
||||||
// We have to handle this ourself.
|
// We have to handle this ourself.
|
||||||
|
@ -38,8 +30,43 @@ function styleToString(style: CSSStyleDeclaration) {
|
||||||
return styleNames.map(name => `${name}: ${style.getPropertyValue(name)};`).join('');
|
return styleNames.map(name => `${name}: ${style.getPropertyValue(name)};`).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetDomStyles(target: HTMLElement, origin: HTMLElement) {
|
||||||
|
target.setAttribute('aria-hidden', 'true');
|
||||||
|
const originStyle = window.getComputedStyle(origin);
|
||||||
|
const originCSS = styleToString(originStyle);
|
||||||
|
// Set shadow
|
||||||
|
target.setAttribute('style', originCSS);
|
||||||
|
target.style.position = 'fixed';
|
||||||
|
target.style.left = '0';
|
||||||
|
target.style.height = 'auto';
|
||||||
|
target.style.minHeight = 'auto';
|
||||||
|
target.style.maxHeight = 'auto';
|
||||||
|
target.style.paddingTop = '0';
|
||||||
|
target.style.paddingBottom = '0';
|
||||||
|
target.style.borderTopWidth = '0';
|
||||||
|
target.style.borderBottomWidth = '0';
|
||||||
|
target.style.top = '-999999px';
|
||||||
|
target.style.zIndex = '-1000';
|
||||||
|
// clean up css overflow
|
||||||
|
target.style.textOverflow = 'clip';
|
||||||
|
target.style.whiteSpace = 'normal';
|
||||||
|
(target.style as any).webkitLineClamp = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRealLineHeight(originElement: HTMLElement) {
|
||||||
|
const heightContainer = document.createElement('div');
|
||||||
|
resetDomStyles(heightContainer, originElement);
|
||||||
|
heightContainer.appendChild(document.createTextNode('text'));
|
||||||
|
document.body.appendChild(heightContainer);
|
||||||
|
// The element real height is always less than multiple of line-height
|
||||||
|
// Use getBoundingClientRect to get actual single row height of the element
|
||||||
|
const realHeight = heightContainer.getBoundingClientRect().height;
|
||||||
|
document.body.removeChild(heightContainer);
|
||||||
|
return realHeight;
|
||||||
|
}
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
originEle: HTMLElement,
|
originElement: HTMLElement,
|
||||||
option: Option,
|
option: Option,
|
||||||
content: string,
|
content: string,
|
||||||
fixedContent: VNodeTypes[],
|
fixedContent: VNodeTypes[],
|
||||||
|
@ -56,30 +83,10 @@ export default (
|
||||||
}
|
}
|
||||||
|
|
||||||
const { rows, suffix = '' } = option;
|
const { rows, suffix = '' } = option;
|
||||||
// Get origin style
|
const lineHeight = getRealLineHeight(originElement);
|
||||||
const originStyle = window.getComputedStyle(originEle);
|
const maxHeight = Math.round(lineHeight * rows * 100) / 100;
|
||||||
const originCSS = styleToString(originStyle);
|
|
||||||
const lineHeight = pxToNumber(originStyle.lineHeight);
|
|
||||||
const maxHeight = Math.round(
|
|
||||||
lineHeight * (rows + 1) +
|
|
||||||
pxToNumber(originStyle.paddingTop) +
|
|
||||||
pxToNumber(originStyle.paddingBottom),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set shadow
|
resetDomStyles(ellipsisContainer, originElement);
|
||||||
ellipsisContainer.setAttribute('style', originCSS);
|
|
||||||
ellipsisContainer.style.position = 'fixed';
|
|
||||||
ellipsisContainer.style.left = '0';
|
|
||||||
ellipsisContainer.style.height = 'auto';
|
|
||||||
ellipsisContainer.style.minHeight = 'auto';
|
|
||||||
ellipsisContainer.style.maxHeight = 'auto';
|
|
||||||
ellipsisContainer.style.top = '-999999px';
|
|
||||||
ellipsisContainer.style.zIndex = '-1000';
|
|
||||||
|
|
||||||
// clean up css overflow
|
|
||||||
ellipsisContainer.style.textOverflow = 'clip';
|
|
||||||
ellipsisContainer.style.whiteSpace = 'normal';
|
|
||||||
ellipsisContainer.style.webkitLineClamp = 'none';
|
|
||||||
|
|
||||||
// Render in the fake container
|
// Render in the fake container
|
||||||
const vm = createApp({
|
const vm = createApp({
|
||||||
|
@ -100,7 +107,8 @@ export default (
|
||||||
|
|
||||||
// Check if ellipsis in measure div is height enough for content
|
// Check if ellipsis in measure div is height enough for content
|
||||||
function inRange() {
|
function inRange() {
|
||||||
return ellipsisContainer.offsetHeight < maxHeight;
|
const currentHeight = Math.round(ellipsisContainer.getBoundingClientRect().height * 100) / 100;
|
||||||
|
return currentHeight - 0.1 <= maxHeight; // -.1 for firefox
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip ellipsis if already match
|
// Skip ellipsis if already match
|
||||||
|
|
Loading…
Reference in New Issue