@razorpay/blade
Version:
The Design System that powers Razorpay
199 lines (194 loc) • 9.52 kB
JavaScript
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import React__default from 'react';
import { chatInputMaxTextAreaHeight } from './chatInputTokens.js';
import { isFileAccepted } from '../FileUpload/isFileAccepted.js';
import { useControllableState } from '../../utils/useControllable.js';
import { useIsMobile } from '../../utils/useIsMobile.js';
import { useMergeRefs } from '../../utils/useMergeRefs.js';
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
var useChatInput = function useChatInput(_ref, ref) {
var controlledValue = _ref.value,
defaultValue = _ref.defaultValue,
_onChange = _ref.onChange,
onSubmit = _ref.onSubmit,
controlledFileList = _ref.fileList,
onFileChange = _ref.onFileChange,
onFileRemove = _ref.onFileRemove,
accept = _ref.accept,
suggestions = _ref.suggestions,
onSuggestionAccept = _ref.onSuggestionAccept;
var fileInputRef = React__default.useRef(null);
var textareaRef = React__default.useRef(null);
var mergedRef = useMergeRefs(ref, textareaRef);
var _useControllableState = useControllableState({
value: controlledValue,
defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : '',
onChange: function onChange(newValue) {
_onChange === null || _onChange === void 0 || _onChange({
value: newValue
});
}
}),
_useControllableState2 = _slicedToArray(_useControllableState, 2),
textValue = _useControllableState2[0],
setTextValue = _useControllableState2[1];
var _useControllableState3 = useControllableState({
value: controlledFileList,
defaultValue: controlledFileList !== null && controlledFileList !== void 0 ? controlledFileList : []
}),
_useControllableState4 = _slicedToArray(_useControllableState3, 2),
files = _useControllableState4[0],
setFiles = _useControllableState4[1];
var _React$useState = React__default.useState(0),
_React$useState2 = _slicedToArray(_React$useState, 2),
activeSuggestionIndex = _React$useState2[0],
setActiveSuggestionIndex = _React$useState2[1];
var isMobile = useIsMobile();
var hasText = textValue.trim().length > 0;
var hasFiles = files.length > 0;
var isSubmitDisabled = !hasText && !hasFiles;
var showGhostSuggestion = !hasText && Boolean(suggestions === null || suggestions === void 0 ? void 0 : suggestions.length) && !isMobile;
var adjustTextareaHeight = React__default.useCallback(function () {
var textarea = textareaRef.current;
if (textarea && textarea instanceof HTMLTextAreaElement) {
textarea.style.height = 'auto';
textarea.style.height = "".concat(Math.min(textarea.scrollHeight, chatInputMaxTextAreaHeight), "px");
}
}, []);
React__default.useEffect(function () {
adjustTextareaHeight();
}, [textValue, adjustTextareaHeight]);
var handleTextChange = React__default.useCallback(function (_ref2) {
var newValue = _ref2.value;
setTextValue(function () {
return newValue !== null && newValue !== void 0 ? newValue : '';
});
}, [setTextValue]);
var handleSubmit = React__default.useCallback(function () {
if (isSubmitDisabled) return;
onSubmit === null || onSubmit === void 0 || onSubmit({
value: textValue,
fileList: files
});
}, [isSubmitDisabled, onSubmit, textValue, files]);
var handleKeyDown = React__default.useCallback(function (_ref3) {
var event = _ref3.event;
if (!event) return;
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
handleSubmit();
return;
}
if (event.key === 'Tab' && showGhostSuggestion && suggestions !== null && suggestions !== void 0 && suggestions.length) {
event.preventDefault();
var currentSuggestion = suggestions[activeSuggestionIndex];
setTextValue(function () {
return currentSuggestion;
});
onSuggestionAccept === null || onSuggestionAccept === void 0 || onSuggestionAccept({
suggestion: currentSuggestion
});
}
}, [handleSubmit, showGhostSuggestion, suggestions, activeSuggestionIndex, setTextValue, onSuggestionAccept]);
var handleUploadClick = React__default.useCallback(function () {
var _fileInputRef$current;
(_fileInputRef$current = fileInputRef.current) === null || _fileInputRef$current === void 0 || _fileInputRef$current.click();
}, []);
var handleFileInputChange = React__default.useCallback(function (event) {
var _event$target$files;
var inputFiles = Array.from((_event$target$files = event.target.files) !== null && _event$target$files !== void 0 ? _event$target$files : []);
var validFiles = inputFiles.filter(function (file) {
if (accept && !isFileAccepted(file, accept)) return false;
return true;
});
var _iterator = _createForOfIteratorHelper(validFiles),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var file = _step.value;
if (!file.id) {
file.id = "".concat(Date.now()).concat(Math.floor(Math.random() * 1000000));
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
if (validFiles.length > 0) {
var newFileList = [].concat(_toConsumableArray(files), _toConsumableArray(validFiles));
setFiles(function () {
return newFileList;
});
onFileChange === null || onFileChange === void 0 || onFileChange({
fileList: newFileList
});
}
event.target.value = '';
}, [accept, files, setFiles, onFileChange]);
var handleFileRemove = React__default.useCallback(function (file) {
var newFileList = files.filter(function (f) {
return f.id !== file.id;
});
setFiles(function () {
return newFileList;
});
onFileRemove === null || onFileRemove === void 0 || onFileRemove({
file: file
});
}, [files, setFiles, onFileRemove]);
var handlePaste = React__default.useCallback(function (event) {
var _event$clipboardData$, _event$clipboardData;
var clipboardFiles = Array.from((_event$clipboardData$ = (_event$clipboardData = event.clipboardData) === null || _event$clipboardData === void 0 ? void 0 : _event$clipboardData.files) !== null && _event$clipboardData$ !== void 0 ? _event$clipboardData$ : []);
if (clipboardFiles.length === 0) return;
event.preventDefault();
for (var _i = 0, _clipboardFiles = clipboardFiles; _i < _clipboardFiles.length; _i++) {
var file = _clipboardFiles[_i];
if (!file.id) {
file.id = "".concat(Date.now()).concat(Math.floor(Math.random() * 1000000));
}
}
if (clipboardFiles.length > 0) {
var newFileList = [].concat(_toConsumableArray(files), clipboardFiles);
setFiles(function () {
return newFileList;
});
onFileChange === null || onFileChange === void 0 || onFileChange({
fileList: newFileList
});
}
}, [files, setFiles, onFileChange]);
var handleInnerMouseDownCapture = React__default.useCallback(function (event) {
var target = event.target;
if (!target) return;
// Allow normal behavior when clicking directly inside textarea.
if (target.closest('textarea')) return;
// Prevent focus from moving to internal controls (submit/upload/file actions).
event.preventDefault();
}, []);
return {
fileInputRef: fileInputRef,
mergedRef: mergedRef,
textValue: textValue,
files: files,
activeSuggestionIndex: activeSuggestionIndex,
setActiveSuggestionIndex: setActiveSuggestionIndex,
hasText: hasText,
hasFiles: hasFiles,
isSubmitDisabled: isSubmitDisabled,
showGhostSuggestion: showGhostSuggestion,
handleTextChange: handleTextChange,
handleSubmit: handleSubmit,
handleKeyDown: handleKeyDown,
handleUploadClick: handleUploadClick,
handleFileInputChange: handleFileInputChange,
handleFileRemove: handleFileRemove,
handlePaste: handlePaste,
handleInnerMouseDownCapture: handleInnerMouseDownCapture
};
};
export { useChatInput };
//# sourceMappingURL=useChatInput.js.map