UNPKG

@jannie-shao/components-antd4

Version:
143 lines 5.54 kB
import "antd/es/space/style"; import _Space from "antd/es/space"; import React, { useRef, useEffect } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { throttle } from 'lodash'; import DropdownMenu from "../dropdown-menu"; import { rootPrefix } from "../style/config"; import { getValue, formatPlaceholder, formatVal, getNextLength, insertRange, pasteRange } from "./util"; var prefix = rootPrefix + "-layedit"; var Layedit = function Layedit(_ref) { var _classnames; var _ref$className = _ref.className, className = _ref$className === void 0 ? '' : _ref$className, value = _ref.value, onChange = _ref.onChange, disabled = _ref.disabled, placeholder = _ref.placeholder, rows = _ref.rows, barList = _ref.barList, showCount = _ref.showCount, maxLength = _ref.maxLength; var compIframe = useRef(); // 解决回调函数里无法监听 value 变化 var valRef = useRef(value); var handleChange = throttle(function () { if (!compIframe.current) return; var iframeWin = compIframe.current.contentWindow; var valNew = getValue(iframeWin.document.body); if (valNew !== valRef.current) { onChange(valNew); } }, 200); var handleInsertEle = function handleInsertEle(key) { if (disabled || !compIframe.current) return; var iframeWin = compIframe.current.contentWindow; iframeWin.document.body.focus(); var val = "${" + key + "}"; // 剩余长度不足 var len = getNextLength(valRef.current, maxLength); if (len !== -1 && len < val.length) return; insertRange(formatPlaceholder(val), iframeWin); handleChange(); }; useEffect(function () { valRef.current = value; if (!compIframe.current) return; var iframeWin = compIframe.current.contentWindow; if (value === '') { iframeWin.document.body.innerHTML = ''; return; } var text = getValue(iframeWin.document.body); if (text !== value) { iframeWin.document.body.innerHTML = formatVal(value); } }, [value]); useEffect(function () { if (!compIframe.current) return; var iframeWin = compIframe.current.contentWindow; iframeWin.document.body.contentEditable = Boolean(!disabled); }, [disabled]); useEffect(function () { if (!compIframe.current) return; var iframeWin = compIframe.current.contentWindow; // 写入样式 var style = iframeWin.document.createElement('style'); style.innerHTML = "\n html, body { margin: 0; padding: 0; }\n body { padding: 6px 11px; font-size: 12px; color: rgba(0, 0, 0, 0.25); }\n body[contenteditable=true] { color: rgba(0, 0, 0, 0.85); -webkit-user-modify: read-write-plaintext-only; }\n body:empty::before { content:'" + placeholder + "'; color: #ccc; font-size:12px; }\n body label { color: #3543ff; }"; iframeWin.document.head.append(style); iframeWin.document.body.addEventListener('keydown', function (e) { // 忽略组合键 if (e.ctrlKey || e.metaKey) return; var valueNow = getValue(iframeWin.document.body); // 长度限制 if (maxLength && e.keyCode !== 8 && e.key.length === 1 && valueNow.length >= Number(maxLength)) { e.preventDefault(); } }); // 粘贴纯文本 iframeWin.document.body.addEventListener('paste', function (e) { e.preventDefault(); var valueNow = getValue(iframeWin.document.body); var len = getNextLength(valueNow, maxLength); if (len === 0) return; pasteRange(e, len, iframeWin); handleChange(); }); // 监听输入内容 iframeWin.document.body.addEventListener('input', function () { return handleChange(); }); }, []); return /*#__PURE__*/React.createElement("div", { className: classnames(prefix, className, (_classnames = {}, _classnames[prefix + "-disabled"] = disabled, _classnames)) }, /*#__PURE__*/React.createElement("div", { className: prefix + "-bar" }, /*#__PURE__*/React.createElement(_Space, null, barList.map(function (b) { return /*#__PURE__*/React.createElement("div", { key: b.name, className: prefix + "-bar-item" }, b.type === 'placeholder' && /*#__PURE__*/React.createElement(DropdownMenu, { getPopupContainer: function getPopupContainer(n) { return n.parentNode; }, trigger: "click", menuItems: b.options, onClick: handleInsertEle }, /*#__PURE__*/React.createElement("span", null, b.name))); }))), /*#__PURE__*/React.createElement("div", { className: prefix + "-value" }, /*#__PURE__*/React.createElement("iframe", { ref: compIframe, title: "layedit", style: { height: rows * 32 } })), showCount && /*#__PURE__*/React.createElement("div", { className: prefix + "-show-count" }, value.length > maxLength && /*#__PURE__*/React.createElement("span", { className: prefix + "-show-count-warning" }, value.length), value.length <= maxLength && value.length, "/", maxLength)); }; Layedit.propTypes = { value: PropTypes.string, onChange: PropTypes.func, disabled: PropTypes.bool, placeholder: PropTypes.string, rows: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), barList: PropTypes.array, showCount: PropTypes.bool, maxLength: PropTypes.oneOfType([PropTypes.number, PropTypes.string]) }; Layedit.defaultProps = { value: '', onChange: function onChange() {}, disabled: false, placeholder: '', rows: 1, barList: [], showCount: false, maxLength: 0 }; export default Layedit;