z-react-ui
Version:
z-react-ui,是一款基于 Dumi,由 React + TypeScript 开发的组件库 🎉。
170 lines (146 loc) • 6.04 kB
JavaScript
import "antd/es/button/style";
import _Button from "antd/es/button";
import React, { useCallback, useRef, forwardRef, useImperativeHandle, useEffect } from 'react';
import { usePrefixCls } from '@/_hooks';
import sendMsg from '@/_utils/chat/sendMsg';
import Toolbar from './Toolbar';
import { chatEmojiPrefix } from '@/_config';
import readPasteData from '@/_utils/chat/readPasteData';
import { createImgNode } from '@/_utils/chat/createNode';
import { usePersistFn } from 'ahooks'; // #----------- 上: ts类型定义 ----------- 分割线 ----------- 下: JS代码 -----------
var SendMsg = function SendMsg(_ref, ref) {
var _ref$content = _ref.content,
content = _ref$content === void 0 ? '' : _ref$content,
onChange = _ref.onChange,
onUploadImg = _ref.onUploadImg,
onUploadFile = _ref.onUploadFile;
var prefixCls = usePrefixCls('chat-send-msg');
var cursorInfoRef = useRef({});
var msgContainerRef = useRef();
var handleKeyUp = function handleKeyUp(e) {
e.preventDefault(); // const msgText = sendMsg(msgContainerRef.current as Node);
// if (msgText.length > 2) {
// msgContainerRef.current.innerHTML = '';
// for (let child of msgContainerHtml.current) {
// console.log('child', child);
// msgContainerRef.current.appendChild(child)
// }
// if (window.getSelection) {//ie11 10 9 ff safari
// msgContainerRef.current.focus(); //解决ff不获取焦点无法定位问题
// var range = window.getSelection();//创建range
// range.selectAllChildren(msgContainerRef.current);//range 选择obj下所有子内容
// range.collapseToEnd();//光标移至最后
// }
// return
// }
var key = e.key; // 换行
if ((e.shiftKey || e.altKey) && key == 'Enter') {// ctrl+enter键
// onChangeInput(v => v + '\n');
// 提交
} else if (key == 'Enter') {
// ctrl+enter键
submit(true);
}
setLastEditRange();
};
var submit = useCallback(function (isClear) {
var msgText = sendMsg(msgContainerRef.current); // 消息发送: 发送文字,为空则不发送
if (msgText.trim().length > 0) {
if (typeof onChange === 'function') {
onChange(msgText);
} // 清空输入框中的内容
if (isClear) {
msgContainerRef.current.innerHTML = '';
}
}
}, [onChange]);
var handleEmojiClick = useCallback(function (emoji) {
var imgNode = createImgNode({
src: "".concat(chatEmojiPrefix, "/").concat(emoji.hover),
alt: emoji.info,
width: 28,
height: 28
});
insertNode(imgNode);
}, []); // 输入框聚焦
var editableFoucs = useCallback(function () {
return msgContainerRef.current.focus();
}, []); // 记录光标位置
var setLastEditRange = useCallback(function () {
// selection 代表了当前激活选中区,即高亮文本块
var selection = window.getSelection ? window.getSelection() : // @ts-ignore document.selection只有ie支持
document.selection; // 从选中区创建一个文本区域对象
var range = selection.createRange ? selection === null || selection === void 0 ? void 0 : selection.createRange() : selection === null || selection === void 0 ? void 0 : selection.getRangeAt(0);
cursorInfoRef.current = {
lastSelection: selection,
lastEditRange: range
};
}, []); // 插入节点
var insertNode = useCallback(function (node) {
var _cursorInfoRef$curren = cursorInfoRef.current,
lastSelection = _cursorInfoRef$curren.lastSelection,
range = _cursorInfoRef$curren.lastEditRange;
range.deleteContents(); // 删除选中的内容
range.insertNode(node); // 设置选择范围的内容为插入的内容
lastSelection.removeAllRanges(); // 移出所有选区
lastSelection.addRange(range);
range.collapse(false); // true 折叠到 range 的 start 节点,false 折叠到 end 节点。如果省略,则默认为 false
// 插入节点完成后,记录节点位置
setLastEditRange();
}, [setLastEditRange]);
var persistInsertNode = usePersistFn(insertNode); // 主要为了获取光标位置
var handleContendEditClick = function handleContendEditClick() {
return setLastEditRange();
}; // 点击表情按钮,出现光标
var handleEmojiBtnClick = useCallback(function () {
editableFoucs();
setLastEditRange();
}, []); // 父组件拿子组件的方法
useImperativeHandle(ref, function () {
return {
insertNode: insertNode,
editableFoucs: editableFoucs,
msgInputRef: msgContainerRef
};
}, [insertNode, editableFoucs]); // 监听输入框的粘贴事件
useEffect(function () {
var pasteEvent = function pasteEvent(clipboardEvent) {
readPasteData(clipboardEvent, persistInsertNode);
};
msgContainerRef.current.addEventListener('paste', pasteEvent);
return function () {
msgContainerRef.current.removeEventListener('paste', pasteEvent);
};
}, []);
return /*#__PURE__*/React.createElement("div", {
className: prefixCls
}, /*#__PURE__*/React.createElement(Toolbar, {
onEmojiClick: handleEmojiClick,
onEmojiBtnClick: handleEmojiBtnClick,
onUploadImg: onUploadImg,
onUploadFile: onUploadFile
}), /*#__PURE__*/React.createElement("div", {
id: "msgInputContainer",
className: "".concat(prefixCls, "-input-panel"),
ref: msgContainerRef,
onKeyUp: handleKeyUp,
contentEditable: true,
spellCheck: false,
onClick: handleContendEditClick,
dangerouslySetInnerHTML: {
__html: content
}
}), /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-btn")
}, /*#__PURE__*/React.createElement("span", {
style: {
color: 'gray'
}
}, "\uFF08Enter+Shift \u6362\u884C\uFF09 "), /*#__PURE__*/React.createElement(_Button, {
onClick: function onClick() {
return submit(true);
},
type: "primary"
}, "\u53D1\u9001 [Enter]")));
};
export default /*#__PURE__*/forwardRef(SendMsg);