UNPKG

@aplus-frontend/antdv

Version:

Vue basic component library maintained based on ant-design-vue

530 lines (529 loc) 18.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.baseProps = void 0; var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2")); var _vue = require("vue"); var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _LocaleReceiver = _interopRequireDefault(require("../locale-provider/LocaleReceiver")); var _warning = _interopRequireDefault(require("../_util/warning")); var _transButton = _interopRequireDefault(require("../_util/transButton")); var _raf = _interopRequireDefault(require("../_util/raf")); var _styleChecker = require("../_util/styleChecker"); var _Editable = _interopRequireDefault(require("./Editable")); var _util = _interopRequireDefault(require("./util")); var _Typography = _interopRequireDefault(require("./Typography")); var _vcResizeObserver = _interopRequireDefault(require("../vc-resize-observer")); var _tooltip = _interopRequireDefault(require("../tooltip")); var _copyToClipboard = _interopRequireDefault(require("../_util/copy-to-clipboard")); var _CheckOutlined = _interopRequireDefault(require("@ant-design/icons-vue/lib/icons/CheckOutlined")); var _CopyOutlined = _interopRequireDefault(require("@ant-design/icons-vue/lib/icons/CopyOutlined")); var _EditOutlined = _interopRequireDefault(require("@ant-design/icons-vue/lib/icons/EditOutlined")); var _useConfigInject = _interopRequireDefault(require("../config-provider/hooks/useConfigInject")); var _omit = _interopRequireDefault(require("../_util/omit")); var _useMergedState = _interopRequireDefault(require("../_util/hooks/useMergedState")); var _propsUtil = require("../_util/props-util"); var __rest = void 0 && (void 0).__rest || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; const isLineClampSupport = (0, _styleChecker.isStyleSupport)('webkitLineClamp'); const isTextOverflowSupport = (0, _styleChecker.isStyleSupport)('textOverflow'); const ELLIPSIS_STR = '...'; const baseProps = () => ({ editable: { type: [Boolean, Object], default: undefined }, copyable: { type: [Boolean, Object], default: undefined }, prefixCls: String, component: String, type: String, disabled: { type: Boolean, default: undefined }, ellipsis: { type: [Boolean, Object], default: undefined }, code: { type: Boolean, default: undefined }, mark: { type: Boolean, default: undefined }, underline: { type: Boolean, default: undefined }, delete: { type: Boolean, default: undefined }, strong: { type: Boolean, default: undefined }, keyboard: { type: Boolean, default: undefined }, content: String, 'onUpdate:content': Function }); exports.baseProps = baseProps; const Base = (0, _vue.defineComponent)({ compatConfig: { MODE: 3 }, name: 'TypographyBase', inheritAttrs: false, props: baseProps(), // emits: ['update:content'], setup(props, _ref) { let { slots, attrs, emit } = _ref; const { prefixCls, direction } = (0, _useConfigInject.default)('typography', props); const state = (0, _vue.reactive)({ copied: false, ellipsisText: '', ellipsisContent: null, isEllipsis: false, expanded: false, clientRendered: false, //locale expandStr: '', copyStr: '', copiedStr: '', editStr: '', copyId: undefined, rafId: undefined, prevProps: undefined, originContent: '' }); const contentRef = (0, _vue.ref)(); const editIcon = (0, _vue.ref)(); const ellipsis = (0, _vue.computed)(() => { const ellipsis = props.ellipsis; if (!ellipsis) return {}; return (0, _extends2.default)({ rows: 1, expandable: false }, typeof ellipsis === 'object' ? ellipsis : null); }); (0, _vue.onMounted)(() => { state.clientRendered = true; syncEllipsis(); }); (0, _vue.onBeforeUnmount)(() => { clearTimeout(state.copyId); _raf.default.cancel(state.rafId); }); (0, _vue.watch)([() => ellipsis.value.rows, () => props.content], () => { (0, _vue.nextTick)(() => { resizeOnNextFrame(); }); }, { flush: 'post', deep: true }); (0, _vue.watchEffect)(() => { if (props.content === undefined) { (0, _warning.default)(!props.editable, 'Typography', 'When `editable` is enabled, please use `content` instead of children'); (0, _warning.default)(!props.ellipsis, 'Typography', 'When `ellipsis` is enabled, please use `content` instead of children'); } }); function getChildrenText() { var _a; return props.ellipsis || props.editable ? props.content : (_a = (0, _propsUtil.findDOMNode)(contentRef.value)) === null || _a === void 0 ? void 0 : _a.innerText; } // =============== Expand =============== function onExpandClick(e) { const { onExpand } = ellipsis.value; state.expanded = true; onExpand === null || onExpand === void 0 ? void 0 : onExpand(e); } // ================ Edit ================ function onEditClick(e) { e.preventDefault(); state.originContent = props.content; triggerEdit(true); } function onEditChange(value) { onContentChange(value); triggerEdit(false); } function onContentChange(value) { const { onChange } = editable.value; if (value !== props.content) { emit('update:content', value); onChange === null || onChange === void 0 ? void 0 : onChange(value); } } function onEditCancel() { var _a, _b; (_b = (_a = editable.value).onCancel) === null || _b === void 0 ? void 0 : _b.call(_a); triggerEdit(false); } // ================ Copy ================ function onCopyClick(e) { e.preventDefault(); e.stopPropagation(); const { copyable } = props; const copyConfig = (0, _extends2.default)({}, typeof copyable === 'object' ? copyable : null); if (copyConfig.text === undefined) { copyConfig.text = getChildrenText(); } (0, _copyToClipboard.default)(copyConfig.text || ''); state.copied = true; (0, _vue.nextTick)(() => { if (copyConfig.onCopy) { copyConfig.onCopy(e); } state.copyId = setTimeout(() => { state.copied = false; }, 3000); }); } const editable = (0, _vue.computed)(() => { const editable = props.editable; if (!editable) return { editing: false }; return (0, _extends2.default)({}, typeof editable === 'object' ? editable : null); }); const [editing, setEditing] = (0, _useMergedState.default)(false, { value: (0, _vue.computed)(() => { return editable.value.editing; }) }); function triggerEdit(edit) { const { onStart } = editable.value; if (edit && onStart) { onStart(); } setEditing(edit); } (0, _vue.watch)(editing, val => { var _a; if (!val) { (_a = editIcon.value) === null || _a === void 0 ? void 0 : _a.focus(); } }, { flush: 'post' }); // ============== Ellipsis ============== function resizeOnNextFrame(sizeInfo) { if (sizeInfo) { const { width, height } = sizeInfo; if (!width || !height) return; } _raf.default.cancel(state.rafId); state.rafId = (0, _raf.default)(() => { // Do not bind `syncEllipsis`. It need for test usage on prototype syncEllipsis(); }); } const canUseCSSEllipsis = (0, _vue.computed)(() => { const { rows, expandable, suffix, onEllipsis, tooltip } = ellipsis.value; if (suffix || tooltip) return false; // Can't use css ellipsis since we need to provide the place for button if (props.editable || props.copyable || expandable || onEllipsis) { return false; } if (rows === 1) { return isTextOverflowSupport; } return isLineClampSupport; }); const syncEllipsis = () => { const { ellipsisText, isEllipsis } = state; const { rows, suffix, onEllipsis } = ellipsis.value; if (!rows || rows < 0 || !(0, _propsUtil.findDOMNode)(contentRef.value) || state.expanded || props.content === undefined) return; // Do not measure if css already support ellipsis if (canUseCSSEllipsis.value) return; const { content, text, ellipsis: ell } = (0, _util.default)((0, _propsUtil.findDOMNode)(contentRef.value), { rows, suffix }, props.content, renderOperations(true), ELLIPSIS_STR); if (ellipsisText !== text || state.isEllipsis !== ell) { state.ellipsisText = text; state.ellipsisContent = content; state.isEllipsis = ell; if (isEllipsis !== ell && onEllipsis) { onEllipsis(ell); } } }; function wrapperDecorations(_ref2, content) { let { mark, code, underline, delete: del, strong, keyboard } = _ref2; let currentContent = content; function wrap(needed, Tag) { if (!needed) return; const _currentContent = function () { return currentContent; }(); currentContent = (0, _vue.createVNode)(Tag, null, { default: () => [_currentContent] }); } wrap(strong, 'strong'); wrap(underline, 'u'); wrap(del, 'del'); wrap(code, 'code'); wrap(mark, 'mark'); wrap(keyboard, 'kbd'); return currentContent; } function renderExpand(forceRender) { const { expandable, symbol } = ellipsis.value; if (!expandable) return null; // force render expand icon for measure usage or it will cause dead loop if (!forceRender && (state.expanded || !state.isEllipsis)) return null; const expandContent = (slots.ellipsisSymbol ? slots.ellipsisSymbol() : symbol) || state.expandStr; return (0, _vue.createVNode)("a", { "key": "expand", "class": `${prefixCls.value}-expand`, "onClick": onExpandClick, "aria-label": state.expandStr }, [expandContent]); } function renderEdit() { if (!props.editable) return; const { tooltip, triggerType = ['icon'] } = props.editable; const icon = slots.editableIcon ? slots.editableIcon() : (0, _vue.createVNode)(_EditOutlined.default, { "role": "button" }, null); const title = slots.editableTooltip ? slots.editableTooltip() : state.editStr; const ariaLabel = typeof title === 'string' ? title : ''; return triggerType.indexOf('icon') !== -1 ? (0, _vue.createVNode)(_tooltip.default, { "key": "edit", "title": tooltip === false ? '' : title }, { default: () => [(0, _vue.createVNode)(_transButton.default, { "ref": editIcon, "class": `${prefixCls.value}-edit`, "onClick": onEditClick, "aria-label": ariaLabel }, { default: () => [icon] })] }) : null; } function renderCopy() { if (!props.copyable) return; const { tooltip } = props.copyable; const defaultTitle = state.copied ? state.copiedStr : state.copyStr; const title = slots.copyableTooltip ? slots.copyableTooltip({ copied: state.copied }) : defaultTitle; const ariaLabel = typeof title === 'string' ? title : ''; const defaultIcon = state.copied ? (0, _vue.createVNode)(_CheckOutlined.default, null, null) : (0, _vue.createVNode)(_CopyOutlined.default, null, null); const icon = slots.copyableIcon ? slots.copyableIcon({ copied: !!state.copied }) : defaultIcon; return (0, _vue.createVNode)(_tooltip.default, { "key": "copy", "title": tooltip === false ? '' : title }, { default: () => [(0, _vue.createVNode)(_transButton.default, { "class": [`${prefixCls.value}-copy`, { [`${prefixCls.value}-copy-success`]: state.copied }], "onClick": onCopyClick, "aria-label": ariaLabel }, { default: () => [icon] })] }); } function renderEditInput() { const { class: className, style } = attrs; const { maxlength, autoSize, onEnd } = editable.value; return (0, _vue.createVNode)(_Editable.default, { "class": className, "style": style, "prefixCls": prefixCls.value, "value": props.content, "originContent": state.originContent, "maxlength": maxlength, "autoSize": autoSize, "onSave": onEditChange, "onChange": onContentChange, "onCancel": onEditCancel, "onEnd": onEnd, "direction": direction.value, "component": props.component }, { enterIcon: slots.editableEnterIcon }); } function renderOperations(forceRenderExpanded) { return [renderExpand(forceRenderExpanded), renderEdit(), renderCopy()].filter(node => node); } return () => { var _a; const { triggerType = ['icon'] } = editable.value; const children = props.ellipsis || props.editable ? props.content !== undefined ? props.content : (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots) : slots.default ? slots.default() : props.content; if (editing.value) { return renderEditInput(); } return (0, _vue.createVNode)(_LocaleReceiver.default, { "componentName": "Text", "children": locale => { const _a = (0, _extends2.default)((0, _extends2.default)({}, props), attrs), { type, disabled, content, class: className, style } = _a, restProps = __rest(_a, ["type", "disabled", "content", "class", "style"]); const { rows, suffix, tooltip } = ellipsis.value; const { edit, copy: copyStr, copied, expand } = locale; state.editStr = edit; state.copyStr = copyStr; state.copiedStr = copied; state.expandStr = expand; const textProps = (0, _omit.default)(restProps, ['prefixCls', 'editable', 'copyable', 'ellipsis', 'mark', 'code', 'delete', 'underline', 'strong', 'keyboard', 'onUpdate:content']); const cssEllipsis = canUseCSSEllipsis.value; const cssTextOverflow = rows === 1 && cssEllipsis; const cssLineClamp = rows && rows > 1 && cssEllipsis; let textNode = children; let ariaLabel; // Only use js ellipsis when css ellipsis not support if (rows && state.isEllipsis && !state.expanded && !cssEllipsis) { const { title } = restProps; let restContent = title || ''; if (!title && (typeof children === 'string' || typeof children === 'number')) { restContent = String(children); } // show rest content as title on symbol restContent = restContent === null || restContent === void 0 ? void 0 : restContent.slice(String(state.ellipsisContent || '').length); // We move full content to outer element to avoid repeat read the content by accessibility textNode = (0, _vue.createVNode)(_vue.Fragment, null, [(0, _vue.toRaw)(state.ellipsisContent), (0, _vue.createVNode)("span", { "title": restContent, "aria-hidden": "true" }, [ELLIPSIS_STR]), suffix]); } else { textNode = (0, _vue.createVNode)(_vue.Fragment, null, [children, suffix]); } textNode = wrapperDecorations(props, textNode); const showTooltip = tooltip && rows && state.isEllipsis && !state.expanded && !cssEllipsis; const title = slots.ellipsisTooltip ? slots.ellipsisTooltip() : tooltip; return (0, _vue.createVNode)(_vcResizeObserver.default, { "onResize": resizeOnNextFrame, "disabled": !rows }, { default: () => [(0, _vue.createVNode)(_Typography.default, (0, _objectSpread2.default)({ "ref": contentRef, "class": [{ [`${prefixCls.value}-${type}`]: type, [`${prefixCls.value}-disabled`]: disabled, [`${prefixCls.value}-ellipsis`]: rows, [`${prefixCls.value}-single-line`]: rows === 1 && !state.isEllipsis, [`${prefixCls.value}-ellipsis-single-line`]: cssTextOverflow, [`${prefixCls.value}-ellipsis-multiple-line`]: cssLineClamp }, className], "style": (0, _extends2.default)((0, _extends2.default)({}, style), { WebkitLineClamp: cssLineClamp ? rows : undefined }), "aria-label": ariaLabel, "direction": direction.value, "onClick": triggerType.indexOf('text') !== -1 ? onEditClick : () => {} }, textProps), { default: () => [showTooltip ? (0, _vue.createVNode)(_tooltip.default, { "title": tooltip === true ? children : title }, { default: () => [(0, _vue.createVNode)("span", null, [textNode])] }) : textNode, renderOperations()] })] }); } }, null); }; } }); var _default = exports.default = Base;