UNPKG

z-react-ui

Version:

z-react-ui,是一款基于 Dumi,由 React + TypeScript 开发的组件库 🎉。

170 lines (146 loc) 6.04 kB
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);